karl westin – the angry designer http://karlwestin.posterous.com Code, rants and occasional facts posterous.com Sun, 13 May 2012 15:11:00 -0700 Refactoring frontend javascript for unit testing http://karlwestin.posterous.com/refactoring-frontend-javascript-for-unit-test http://karlwestin.posterous.com/refactoring-frontend-javascript-for-unit-test

One opinion I hear every now and then concerning javascript unit testing for the frontend is "It sure is good, but we can't do that. The code is a piece of crap anyway. We should just re-write it, from scratch, with tests".

This is kind of a reckless statement, especially taken out of its' context. But I think it bears som truth in it. Writing testable javascript requires slightly different paradigms and patterns. Applying tests to existing code does often require some refactoring.

1. "Some old cruft we had lying around"

In this post, we gonna look at some weird lightbox code that's been on our page like forever. Now, your javascript looks much better than this :), but chances are you might at one point have written code that looks somewhat similar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
* Karl Westin
* Part of the "refactoring javascript for unit testing" blog post
*/

$(document).ready(function() {

    $("#boxlink").bind("click", function(e) {
        var content = "<div class='js-overlay'></div>" +
                      "<div class='js-dialog'>" +
                          "<a href='#' class='js-close'>Close</a>" +
                          "<div class='js-content'>" +

                          // content:
                          "<img height='331' width='500' src='img/spaceshuttle.jpg' title='Space shuttle on a Plane!'>" +
                          "<br>Gorgeous photo of the space shuttle by <a href='http://www.flickr.com/photos/deg_io/5702042693/'>flickr user deg_io</a>" +

                          "</div>" +
                      "</div>",
            width,
            height;

        e.preventDefault();
                      
        $("body").append(content);

        $(".js-overlay").bind("click", closeBox);
        $(".js-close").bind("click", closeBox);

        width = $(".js-content").width();
        height = $(".js-content").height();
        $(".js-dialog").width(width)
                       .height(height)
                       .css("margin-left", -width/2)
                       .css("margin-top", -height/2);

        $(".js-overlay").hide().fadeIn();
    });

    function closeBox(e) {
        e.preventDefault();
        $(".js-close").unbind("click");
        $(".js-overlay").unbind("click").fadeOut($(".js-overlay").remove.bind($(".js-overlay")));
        $(".js-dialog").remove();
    }

});

I tried to put some elements in here that you might encounter in your legacy codebase. First of all, everything is wrapped in $(document).ready(). Second, we try to avoid setting any global footprint. Not a single variable is exposed to the world.

2. Creating a class, and exposing it to the test suite

Step one in any testing-oriented refactoring is to make sure you can access what you need to access from the tests. We would also like to make the code a little bit more reusable. That's why we're rewriting it as a class instead.

We also need to expose the Lightbox class to a global, to be reachable. We could (or maybe even should) write it as a part of an AMD module instead. However, this blog post is not about AMD, and I'd like to keep the code simple here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/*
* Karl Westin
* Part of the "refactoring javascript for unit testing" blog post
*/

function Lightbox(boxcontent) {
    var content = "<div class='js-overlay'></div>" +
                  "<div class='js-dialog'>" +
                      "<a href='#' class='js-close'>Close</a>" +
                      "<div class='js-content'>" +
                      boxcontent +
                      "</div>" +
                  "</div>",
        width,
        height;

    $("body").append(content);

    $(".js-overlay").bind("click", this.closeBox);
    $(".js-close").bind("click", this.closeBox);

    width = $(".js-content").width();
    height = $(".js-content").height();
    $(".js-dialog").width(width)
                   .height(height)
                   .css("margin-left", -width/2)
                   .css("margin-top", -height/2);

    $(".js-overlay").hide().fadeIn();
}

Lightbox.prototype = {

    closeBox: function(e) {
        e.preventDefault();
        $(".js-close").unbind("click");
        $(".js-overlay").unbind("click").fadeOut($(".js-overlay").remove.bind($(".js-overlay")));
        $(".js-dialog").remove();
    }

};

$(document).ready(function() {
    $("#boxlink").bind("click", function(e) {
        var content = "<img height='331' width='500' src='img/spaceshuttle.jpg' title='Space shuttle on a Plane!'>" +
                      "<br>Gorgeous photo of the space shuttle by <a href='http://www.flickr.com/photos/deg_io/5702042693/'>flickr user deg_io</a>";

        e.preventDefault();
        new Lightbox(content);
    });
});

One nice side effect of the unit-testing is that the code gets executed multiple times. That gets us some kind of verification that the code is somewhat clean, and it can help us detecting unintentional modification of the prototype.

3. What and how to test - finding the endpoints

So, after this first, very basic, refactoring, I would like to add some tests before moving on. Before doing this, we need to define what behavior we'd like to test, and also (which I'm kind of missing in the discussion around testing), how we would like to test the behavior. Here's the behaviors we'd like to test:

  • Creating the necessary DOM

  • Adding the content

  • Auto-resizing the lightbox

  • Closing the box when clicking the "close" link or overlay

  • Removing the necessary DOM when closed

How do we test this in the best way? One "rule" in the testing community that you've surely heard is to test behavior, not implementation. This makes the tests more robust, and makes it easier to refactor code without rewriting the tests.

I'd like to think of it as finding the endpoints in the code. If I'm testing ajax, the endpoint is the ajax call itself (native or jquery depending on how I'm building it). The path from the interface call to the ajax call is implementation, and I try to leave that out of the test suite.

Let's look at a couple of examples:

  • Creating necessary DOM:

    1. Creating a lightbox
    2. Making sure the overlay is there
    3. Making sure the content box is there
    4. Making sure the close button is there
  • Adding the content:

    1. Creating the lightbox (with known content)
    2. Making sure the content is placed
  • Auto-resizing the lightbox:

    1. Creating the lightbox (with content with known size)
    2. Checking the size of the lightbox
    3. Checking margins for positioning
  • Closing the box when clicking "close"

    1. Creating the lightbox
    2. Clicking the close-button
    3. Asserting "close" got called, we'll do this for now by seeing if the overlay got removed.
  • Repeat the same steps for the overlay

  • Removing necessary DOM when closed

    1. Creating the lightbox
    2. Closing it
    3. Making sure overlay is removed
    4. Making sure content box is removed

So let's write those tests. I'm using Jasmine, but it should be simple to rewrite them to QUint, JSTestDriver or whatever you feel like.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
describe("Lightbox tests", function() {

    beforeEach(function() {
        var content = "<div style='width: 100px; height: 110px; position: relative; display: inline-block; background-color: #fff;'>My test-content</div>"

        // for unit-testing purposes, we turn jQuery.fx off
        $.fx.off = true;

        setFixtures(sandbox());
        this.$sandbox = $("#sandbox");
        this.lightBox = new Lightbox(content, this.$sandbox);
    });

    afterEach(function() {
        $.fx.off = false;
    });

    it("should create the necessary elements", function() {
        expect(this.$sandbox).toContain(".js-overlay");
        expect(this.$sandbox).toContain(".js-close");
        expect(this.$sandbox).toContain(".js-dialog");
    });
    
    it("should contain the content", function() {
        expect(this.$sandbox).toHaveText(/test-content/i);
    });

    it('should auto-resize the box', function() {
        expect($(".js-dialog").width()).toEqual(100);
        expect($(".js-dialog").height()).toEqual(110);
    });

    it("should remove the box when clicking 'close'", function() {
       $(".js-close").click();
       expect(this.$sandbox).not.toContain(".js-overlay");
    });
    
    it("should remove the box when clicking the overlay", function() {
       $(".js-overlay").click();
       expect(this.$sandbox).not.toContain(".js-overlay");
    });

    it("should remove the lightbox completely", function() {
       $(".js-close").click();
       expect(this.$sandbox).not.toContain(".js-overlay");
       expect(this.$sandbox).not.toContain(".js-dialog");
    });

});

Small notes in this steps:

I did a few extra changes to the source for further testability. First, I added an optional "parent" parameter to the Lightbox constructor. This just a convenient thing to be able to add the lightbox to a fixture instead of the specrunner DOM.

I'm using jasmine-jquery for fixtures. Fixtures can be either a specially loaded template (or html file), or just an empty, as in our case, that you can use to test DOM manipulations that you need to perform. With Jasmine-jQuery, you can load the actual template or html file where the script is going to be used, and make sure that you test the real html. This could be useful for integration tests with Jasmine. Also, some of the testing matchers: toHaveText for example, comes from jasmine-jquery.

A third note if you create this with another test-runner: Remember to include the style.css file!

The complete code after this step can be found on Github

4. Creating an interface (for test robustness)

Javascript frontend tests are sometimes critized for being fragile, and break because of very small changes to the implementation. The best way around this is to create an interface, a couple of set, public functions/properties, that we stick to.

In our tests we're accessing the DOM elements through JS selectors. In my experience, those are VERY likely to change, depending on the page that the script is used on. Therefore, we should have accessors for them in the interface for the lightbox. That way, we can change the css-class in the source, but because the test is using the accessor, it should still be able to work without changes.

Another interface that we need is the a close method. closeBox feels quite silly to me, I'd rather have myBox.close(); Lets change that.

Our new interface:

Lightbox (constructor)
  close     (method)
  $closeBtn (prop)
  $overlay  (prop)
  $dialog   (prop)

The DOM-element properties starts with a $, to annotate them as jQuery objects.

Here is the commit with the changes to tests and source to implement the interface

5. Refactor

Our code is a little bit more testable, but still not very pretty. However, now that we have some tests in place, lets try some refactoring with tests.

The big problem is the constructor. It's a mess. To make it clearer, and easier to add more things to the constructor, I want to break out a couple of things to separate, private, functions. In a case like this, I think it's enough to use the _ (underscore) annotation, to warn developers using the code: "Hey, this might change later on". Looking at the new refactored constructor, it now consists of three steps: Adding elements, binding events and auto sizing the box.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
* Karl Westin
* Part of the "refactoring javascript for unit testing" blog post
*/

function Lightbox(boxcontent, $parent) {
    this._addElements(boxcontent, $parent);
    this._autoSize();
    this._bindEvents();
}

Lightbox.prototype = {

    _addElements: function(boxcontent, $parent) {
        var content = "<div class='js-overlay'></div>" +
                      "<div class='js-dialog'>" +
                          "<a href='#' class='js-close'>Close</a>" +
                          "<div class='js-content'>" +
                          boxcontent +
                          "</div>" +
                      "</div>",
            width,
            height;

        $parent = $parent || $("body");
        $parent.append(content);

        this.$closeBtn = $parent.find('.js-close');
        this.$overlay = $parent.find('.js-overlay');
        this.$dialog = $parent.find('.js-dialog');

        this.$overlay.hide().fadeIn();
    },

    _autoSize: function() {
        var $content = this.$dialog.find(".js-content"),
            width = $content.width(),
            height = $content.height();

        this.$dialog.width(width)
                    .height(height)
                    .css("margin-left", -width/2)
                    .css("margin-top", -height/2);
    },

    _bindEvents: function() {
        this.$overlay.bind("click", this.close);
        this.$closeBtn.bind("click", this.close);
    },

    close: function(e) {
        if(e) {
            e.preventDefault();
        }
        $(".js-close").unbind("click");
        $(".js-overlay").unbind("click").fadeOut($(".js-overlay").remove.bind($(".js-overlay")));
        $(".js-dialog").remove();
    }

};

$(document).ready(function() {
    $("#boxlink").bind("click", function(e) {
        var content = "<img height='331' width='500' src='img/spaceshuttle.jpg' title='Space shuttle on a Plane!'>" +
                      "<br>Gorgeous photo of the space shuttle by <a href='http://www.flickr.com/photos/deg_io/5702042693/'>flickr user deg_io</a>";

        e.preventDefault();
        new Lightbox(content);
    });
});

I think it's much easier to understand what the constructor does now. If we need more features, there's "room" in the constructor for more. We can add functionality, and still be able to understand it easily. We can grow the code if we need to.

The class looks very different from our code in step one, but essentialy does the same job. It can be more easily re-used, it's easier to add more features and we can check whether our changes broke something we already built earlier.

Recommended reading

  1. This is a super concise and informative speakerdeck by @searls: I'm afraid of Javascript Very recommended, many of the testing techniques used here comes from there!

  2. Christian Johansens: Test-Driven Javascript Development Is a great book for digging deeper. Christian shows in a very realistic way how/what javascript testing is. He also discusses how to write tests, and what unit testing is actually good for and where you might need other tools or even manual testing. 5 Stars!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Sun, 15 Apr 2012 07:46:00 -0700 Nested models/collections and storage with Backbone.js and Backbone.LocalStorage http://karlwestin.posterous.com/nested-modelscollections-and-storage-with-bac http://karlwestin.posterous.com/nested-modelscollections-and-storage-with-bac

I recently needed to build an app with nested collections and models using Backbone.js, and adding a persistence layer with Backbone.LocalStorage, so that the data created would stay in the browser for the user. When doing this, I was stumbling around a little, and I found an open issue on the Backbone.LocalStorage github page saying that support was missing. However, my conclusion after doing this is that Backbone.LocalStorage already supports nested collections and models, and that it works really well.

Please see the example below. For each Team that is created, a new LocalStorage instance is made. Each team needs their own storage for this to work. When the premier-collection is fetched on application start, the teams are fetched recursively on when each Team-model is created.

Teams are recursively saved with the League.saveAll() method. Note that this save both the team model, and each of the player models in the team's player collection. With this, one idea could be to bind the League.saveAll method to certain important events, for example window.onunload, that way you only save data when necessary.

This example only supports one league, but it could be taken further by creating a League model, with a "teams" collection. Those could then be managed by a Federation collection at the top.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
* Example of using nested collections/models with backbone.js and backbone.js localStorage
*
* Read the complete blog post at karlwestin.posterous.com
*
* 1. run populate() from command line first time
* 2. reload the page (or open in another browser tab), and check the following:
*
* premier.at(0).get("name") => "Tottenham"
* premier.at(0).players.length => 3
*
*/

var teams = [{ name: "Tottenham" }, { name: "Manchester United" }],
    players1 = [{ name: "Ryan Giggs" }, { name: "Wayne Rooney" }, { name: "Michael Owen" }],
    players2 = [{ name: "Emmanuel Adebayor" }, { name: "Ledley King" }, { name: "Rafael van der Vaart" }],
    Team,
    League,
    premier

Team = Backbone.Model.extend({

    initialize: function(config) {
        this.players = new (Backbone.Collection.extend({
            localStorage: new Backbone.LocalStorage(config.name)
        }))()
        this.players.fetch()
    },

    saveAll: function() {
        _.each(this.players.models, function(player) {
            player.save()
        })

    },

    add: function(models) {
        this.players.add(models)
    }

})

League = Backbone.Collection.extend({

    localStorage: new Backbone.LocalStorage("league"),

    model: Team,

    saveAll: function() {
        _.each(this.models, function(team) {
            team.save()
            team.saveAll()
        })
    }
})


premier = new League()
premier.fetch()


function populate() {
    premier.add(teams[0])
    premier.add(teams[1])
    premier.at(0).add(players2)
    premier.at(1).add(players1)

    premier.saveAll()
}

Update: Scott Nelson was reviewing this post (Thanks man!), and pointed out while it doesn't matter with local storage, the technique shown here makes unnecessarily many server calls when used against a server API. If i understand him right, he meant that the "Players" collection could be created on parse (Backbones handler for pre-processing the data returned from a fetch() call). I think this technique sounds really interesting, however I haven't really grasped how to recursively save the models and collections then. Please post any ideas around this in the comments! 

If you want to see a further developed example, please see my music player example

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Thu, 08 Mar 2012 02:57:00 -0800 JSBin: Show line numbers + other tricks http://karlwestin.posterous.com/jsbin-show-line-numbers-other-tricks http://karlwestin.posterous.com/jsbin-show-line-numbers-other-tricks

If you use jsbin.com (by Remy Sharp) every day, like I do, you may have wanted line numbers at some point. Well, it turns out you can have it, I created this bookmarklet for convenience: 

1
2
3
4
// Since Posterous don't support javascript:
// Just add whatever link as bookmark, and paste this as the link instead

javascript:(function() { editors.javascript.setOption("lineNumbers", true); editors.html.setOption("lineNumbers", true); })();

Since JSBin is based on Codemirror, you can set any of the options that Codemirror allows you to set, including line-wrapping, tab-size and color theme. Check out the Codemirror options page for all the details.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 30 Jan 2012 15:37:00 -0800 Shiftin', Unshiftin', Pushin' n Poppin' http://karlwestin.posterous.com/shiftin-unshiftin-pushin-n-poppin http://karlwestin.posterous.com/shiftin-unshiftin-pushin-n-poppin

I would like to show a neat trick on looping through arrays, not using one value every time but sometimes one, sometimes two and so on.

I found this while doing the Bowling Game Code Kata. A kata is like a code practice, you try to solve a problem in many different ways to see what you find. I find this very interesting, cause I'm learning test driven development at the moment, and it's perfect to try different implementations once you got your tests set up.

A guy named Zach Leat has set up a very nice repository of javascript katas, and I will show you part of his Bowling Game, very true to the original Java implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// This is the implementation from https://github.com/zachleat/JavaScript-Code-Katas

Game.prototype.score = function()
{
    var points = 0,
        frameIndex = 0;

    for(var frame = 0; frame<10; frame++) {
        if(this.isStrike(frameIndex)) {
            points += this.strikeBonus(frameIndex);
            frameIndex++;
        } else if(this.isSpare(frameIndex)) {
            points += this.spareBonus(frameIndex);
            frameIndex += 2;
        } else {
            points += this.sumOfBallsInFrame(frameIndex);
            frameIndex += 2;
        }
    }

    return points;
};

What you see above is the "score" function, the way the bowling scores are summed up. As you see, when you hit a strike, you use one value from the array, and then you add up the following two but not passing by them. When you hit a spare, you use two values from the array, and then adding one following value, without passing by it. 

A nicer way of doing this, without having to deal with a counter variable, is simply shifting the array. That way you don't have to count, because you always use the latest values, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
var score = function() {
          var score = 0;

          for(var i = 0; i < 10; i++) {
              if(rolls[0] === 10)
                  score += rolls.shift() + rolls[0] + rolls[1];
              else if(rolls[0] + rolls[1] === 10)
                  score += rolls.shift() + rolls.shift() + rolls[0];
              else
                  score += rolls.shift() + rolls.shift();
          }
          return score;
};

The shift, unshift, push and pop functions are really great for working with arrays, though i have to admit it took me long to memorize. I think most people know push and pop. Here's an overview:

1
2
3
4
5
6
7
var arr = [1,2,3,4,5,6,7];

var first = arr.shift(); // first = 1, arr = [2,3,4,5,6,7]
arr.unshift(0); // arr = [0,2,3,4,5,6,7]

arr.push(8); // arr = [0,2,3,4,5,6,7,8]
var last = arr.pop() // last = 8, arr = [0,2,3,4,5,6,7]

Hope that helps with something! Anyway if you sit on any good code katas, i would really appreciate if you post them in the comments! Looking forward to it!

PS. Here's my entire bowling score kata, if you find it useful!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 09 Jan 2012 04:05:00 -0800 Some of javascript's more esoteric operators: http://karlwestin.posterous.com/some-of-javascript-more-exotic-operators http://karlwestin.posterous.com/some-of-javascript-more-exotic-operators

Bitwise NOT: ~

The bitwise "not"-operator has some pretty weird but interesting side effects. Its basic functions on numbers can be described as:

~N = -(N+1)

Now, the way you see this operator used is more often than not for flooring numbers:

~~10.23342 // returns 10

The reason this works is because all bitwise operations are performed on 32-bit integers in javascript:

~10.23342 // => -11 (Rounded when converted to integer)
~-11 // => 10 (-(-11+1) = 10)

Taking this one step further, this can be used to convert -1 to false. Functions like Array.indexOf, String.indexOf and String.search returns -1 on "not found".

var facon = "sundriedtomatoesisvegetarianbacon";
if(~facon.search("bacon")) eat(facon); 
// HAHA! tricking meat eaters into eating vegetarian

@webreflection Has written much better about the javascript tilde trick, and it's also mentioned by Dreaming Javascript

Bit-shifting ( >>, >>>, << )

One possible use-case for bitshifting in javascript is when working with hex colors, for example can we use bit-shifting to filter out Red, Green and Blue values:

Filtering out hex values:

111111111111111111111111

32-bit (16 777 215 in Base 10)

R        G        B
11111111 11111111 11111111

Mask for filtering G-value:
00000000 11111111 00000000

Combine with bitwise & (Only saving the spots where BOTH numbers are 1)
Example: Base-10 color-value: 16737792 – the orange color in the "Hacker News"-logo

00000000 11111111 00000000 // Mask
             &
11111111 01100110 00000000 // Color value
                         =
00000000 01100110 00000000 // result => 26112

Bit shift it to get only the "green"-value:
26112 >> 8 => 102 // removing the lowest (rightmost) 8 bits

Raphael.js uses bitshifting for the reverse operation, converting an object like { R: 10, G: 20, B: 255 } into a hex value:

rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
(Line 855, Raphael.js)

The bit-operator part is: (16777216 | blue | (green << 8) | (red << 16))

Dimitry is using the | (and/or) operator to add up a hex number:

So let look at this:
First we create a mask, that we add the numbers to: in base(2) 1000000000000000000000000. This is one number bigger than the highest RGB-color value on Base(10). We'll soon see why.

The "blue" value is a normal color-value, for example 255:

16777216 | 255 means:

1 00000000 00000000 00000000
                        | (inclusive or)
0 00000000 00000000 11111111
                        =
1 00000000 00000000 11111111

The green value needs to be shifted 8 bits to the left: 66

66 << 8 => 16896

1 00000000 00000000 11111111 // number after adding blue value:
                        |
0 00000000 01000010 00000000                        
                        =
1 00000000 01000010 11111111

(And the same thing repeated with the red color, that needs to be shifted 16 bits.)

  Red      Green    Blue        
1 01100100 01000010 11111111                        

This number is now converted to Hex with (number).toString(16):
(parseInt("1011001000100001011111111", 2)).toString(16) 
// we need to convert out binary number to Base 10 first, hence parseInt

Now we'll delete out initially added "1 time bigger" number:
(parseInt("1011001000100001011111111", 2)).toString(16).slice(1)

And add a # to the start, then we'll have a hex number.

Bit-shifting is extensively used in Mozilla's pdf.js and also appears in Mr Doob's Three.js. I'm sure it's relevant in those extremely performance-heavy use-cases, because when you start creeping up towards tens of millions of loops per second, the difference between shift-right 2 bits and divide by four (which is the same operation on integers) starts to make sense

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Tue, 16 Aug 2011 05:42:15 -0700 Should you use wordpress? (Beginners guide.) http://karlwestin.posterous.com/should-you-use-wordpress http://karlwestin.posterous.com/should-you-use-wordpress

Most people i have a professional relationship with know that i nurture an almost passionate hate for Wordpress. Sometimes even other people ask me for my opinion, hence this blog post.

So, the answer to "Can I use wordpress?", seems to be other questions:

You run your won company, wanna create a quick site yourself, and don't wanna pay a consultant/agency?

YESSS!!! Actually you SHOULD use wordpress. And you should use a *.wordpress.com-hosted blog, and have a friend setting up a custom domain name for you. It will be limited, but it will always be better and more hassle-free than any self-hosted wordpress installation with all the fancy functionality you can dream of. In fact, wordpress.com is the ONLY "create-your-own-website"-service i can recommend.

You want to accept payments on your site?

NO. To accept payments from a wordpress site, it will need to be self-hosted. Getting the security right on a self-hosted Wordpress blog is very hard. Get help. From someone else. I'm not an expert on internet payment systems, unfortunately.

You're looking for an extendable, lightweight, CMS?

NO. Wordpress is very extendable, but the problem is that the plugins are often very low quality, and when you need to upgrade a system, you're likely to end up having a broken website with 15/20 plugins broken because of Wordpress changes, or because they were badly written from the beginning. 

You're looking to have more than 1000 visits/day?

NO. Well i know there's a plugin called WP-Super Cache. Still, every day i see wordpress blogs crumbles under the load of 5-10 000 Hacker News visitors. It's just not easy to get it right. And if you do, you're very likely to break your site's security. The problem, must be admitted though, is also often in Apache settings rather than Wordpress. Did you have better load tolerance with other servers? Please comment!

You already know Wordpress, and want to get started now?

YES. See first question. Use a wordpress.com site and buy a custom domain. When it's time to add payments, bookings and other things, Wordpress has excellent export tools for getting your content out and move it to another system. 

Your question not here? Ask it in the comments! If i have a good answer, i'll add it!

Options to check out:

  • Jekyll: Generating static pages from Markdown. For extremely lightweight, fast blogging that can take a hit from reddit, digg or whatever. For self-hosted sites.
  • MojoMotor: Small, extendable, lightweight CMS based on the CodeIgniter PHP framework, for self-hosted sites.
  • ExpressionEngine: Also based on CodeIgniter. Full blown stuff, extendable for e-commerce, booking, applications etc. Self-hosted.
  • BigCartel: E-Commerce as a service. Good templates, they host it = take care of the hassle :)
  • Shopify: Same as above. Note that i haven't tried any of these two myself, but that'd be the first place i'd look if i needed to

 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 27 Jun 2011 05:53:44 -0700 Nokia N9 and an incomplete list of browser features http://karlwestin.posterous.com/nokia-n9-and-its-browser http://karlwestin.posterous.com/nokia-n9-and-its-browser

Faith gave me the chance to lay my filthy hands on a Nokia N9 this weekend. Not very long, but at least it gave me some impressions:

First of all the UI as smooth and snappy as in the videos

It looks really great to use! Trying to push it, the only time i saw a hiccup was the first time i got the notifications drawer out. I'm not enough of an iOS user to be able to compare, but my impression was that speed and animations were better than on my Nexus S running Android 2.3.4

Swipe to switch apps rocks

Swipe to switch apps is like the Dude's carpet. It really ties the phone together. It works like this: when you swipe on the screen, it is a normal swipe that for example browses photos in a gallery. When you swipe from the edge of the screen, it switches apps. The difference felt very distinct and far easier to perform than the 4-finger-swipe-to-switch-apps in iPad on iOS 5. 

Browser: 3D CSS Transforms, CSS Animations, Homescreen apps 

So during the few minutes i had i had the chance to run a html5test.com test. I don't remember the exact score, but it was something around 300. Accordning to the site, iOS 5 scores 303, so i guess they're around the same. The features are quite different though. Let's do some comparison:

According to the Nokia engineer i spoke to, the phone supports CSS3 3D transforms and CSS3 transitions and animations. I can't applaud this enough. He also claimed the phone to have good support for the application cache manifest, as well as Local Storage + WebSQL. This means that Nokia goes down the Apple path, and don't support the IndexedDB type of local database used by Google and Mozilla. According to the engineer i spoke to, they also included javascript touch-events and gesture-events, detecting up to 5 fingers on the screen.

One peculiar thing is that you can't actually bookmark a web-page. Only place it as a home-screen app. In the category "no's" we'll also find Websockets and WebGL. I honestly forgot to check whether it supported the DeviceMotion and DeviceOrientation javascript APIs for the accelerometer. So if you get the chance to check that out, please let me know!

On the video side, the browser supports the MPEG4, H.264 and Ogg Theora codecs. That means no WebM.

The browser priorities are right 

Whether this makes the phone and its' browser good or not is too early to say. But as a web developer i say that i have the impression that Nokia got their priorities right. CSS3 transitions and 3D animations might be eye-candy, but it's really important for creating user-friendly, touch-enabled websites that even comes close to the feel of native apps. While i pity the exclusion of websockets, I wouldn't prioritize WebGL for mobile on this point. Don't get me wrong, i think WebGL is one of the most interesting technologies to show up lately, but it still has to prove its' user value beyond cool demos and videos.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Wed, 13 Apr 2011 03:08:00 -0700 Internet Explorer 10 – Columns, Box-model and Gradients. No webGL or websockets yet. http://karlwestin.posterous.com/internet-explorer-10-columns-box-model-and-gr http://karlwestin.posterous.com/internet-explorer-10-columns-box-model-and-gr

So, yesterday microsoft released the first platform preview of IE10. I'm happy to see they seem to adopt shorter release cycles. Let's see what they put in there for now!

I was a little bit lazy, so i basically jsut went to modernizr.com and checked the new feature list. Microsoft seem to keep their habit of adding proprietary prefixes and stuff, but on the other hand, so does webkit and firefox too. Let me just say it sucks.

Well. This is just the very very first platform preview, so i hope there's more to come. At the moment it still looks pretty lame I'd say.

Feature table, according to modernizr:

FeatureIE10IE9Chrome 10
@font-face OK OK OK
Canvas OK OK OK
Canvas Text OK OK OK
HTML5 Audio OK OK OK
HTML5 Video OK OK OK
rgba() OK OK OK
hsla() OK OK OK
border-image: NO NO OK
border-radius: OK OK OK
box-shadow: OK OK OK
text-shadow: NO NO OK
opacity: OK OK OK
Multiple backgrounds OK OK OK
Flexible Box Model OK NO OK
CSS Animations NO NO OK
CSS Columns OK NO OK
CSS Gradients OK NO OK
CSS Reflections NO NO OK
CSS 2D Transforms OK OK OK
CSS 3D Transforms NO NO OK
CSS Transitions NO NO OK
Geolocation API OK OK OK
localStorage OK OK OK
sessionStorage OK OK OK
SVG OK OK OK
SMIL OK OK OK
SVG Clipping OK OK OK
Inline SVG OK OK OK
Drag and Drop OK OK OK
hashchange OK OK OK
X-window Messaging OK OK OK
History Management NO NO OK
applicationCache NO NO OK
Touch events NO NO OK
Web Sockets NO NO OK
Web Workers NO NO OK
Web SQL Database NO NO OK
WebGL NO NO OK
IndexedDB NO NO NO

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 28 Mar 2011 07:40:04 -0700 JavaScript Accelerometer on iOS & Android (via firefox)! http://karlwestin.posterous.com/javascript-accelerometer-on-ios-android-via-f http://karlwestin.posterous.com/javascript-accelerometer-on-ios-android-via-f

Since iOS 4.2, Mobile Safari supports accelerometer events. The native browser on Android doesnt do that yet. (I've heard that it does accelerometer in WebViews, ex via phonegap, but i couldn't confirm this now) Firefox 4 (currently in Beta 13, 28 March 2011) does support accelerometer events! Of course, this is awesome, not least for building games on websites!

So, this is how you do it:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Accelerometer Javascript example by @karlwestin, Nerd Communications, Berlin

// Firefox, works on desktop too
window.addEventListener("MozOrientation", updateText, true);

// Mobile Safari
window.addEventListener("devicemotion", updateText, true);

function updateText(e) {

if(!!e.x)
// Firefox
updateCounter(e.x*10, e.y*10, e.z*10);
else if (!!e.accelerationIncludingGravity)
// Mobile Safari
updateCounter(e.accelerationIncludingGravity.x, e.accelerationIncludingGravity.y, e.accelerationIncludingGravity.z);
else
alert("you don't really support devicemotion, do you?");

}

function updateCounter(x, y, z) {
document.getElementById("xAxis").innerHTML = x;
document.getElementById("yAxis").innerHTML = y;
document.getElementById("zAxis").innerHTML = z;
}

You can view the demo here: http://nerdcommunications.com/demos/accelerometer/

 

You can download the demo source here: http://nerdcommunications.com/demos/accelerometer/demo.zip

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Wed, 17 Nov 2010 03:31:59 -0800 Tracking lost users w/ Google Analytics http://karlwestin.posterous.com/tracking-lost-users-w-google-analytics http://karlwestin.posterous.com/tracking-lost-users-w-google-analytics Step 1: Set up your custom 404-page, put this in .htaccess:
ErrorDocument 404 /404.html

Step 2: Put this Google Analytics code on your 404.html:

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-19487197-1']);
  _gaq.push(['_trackPageview', '/404'+ '?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer]);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

That way, you catch both that you had an error, what path they tried to access and where the bad link is.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 14 Jun 2010 10:31:00 -0700 The facebook scam "101 hottest women" and why you clicked it http://karlwestin.posterous.com/the-facebook-scam-101-hottest-women-and-why-y http://karlwestin.posterous.com/the-facebook-scam-101-hottest-women-and-why-y

have you seen any of you're facebook friends clicking something like this lately?

Bild_3

Hmm... maybe not something you wanna show off to your friends. But how come?

It comes in various size and colors, Chinese Videos that makes you fall asleep (you MUST see it!), cutest pets, whatever. But what is it, and what do the people behind this want?

Since this one seems to be pretty common, plus that it's working in a lot of different versions currently. I wanted to look through it a little!

0. What is it?

Basically, some people want to fool you into filling out a survey, to see some old crappy content. The content is usually not even theirs.

The scam doesnt seem to attempt to steal anything from you PLEASE LOOK THIS UP, PEOPLE WITH THE RIGHT KNOWLEDGE.

Btw that porn-site you were looking for is here: http://www.maxim.com/girls/girls-of-maxim/92660/2010-hot-100.html

Here's what happens!

1. The moving "like button"

Wonder when you ever clicked "Like" on that link? You just clicked the normal link? No, you clicked the "like" button, which moves around with javascript:

    function lololol(e){

    if (window.event) 

    { // for IE

        aaaa.style.top = (window.event.y-5)+standardbody.scrollTop+'px';

        aaaa.style.left = (window.event.x-5)+standardbody.scrollLeft+'px';

    } 

    else 

    {

        aaaa.style.top = (e.pageY-5)+'px';

        aaaa.style.left = (e.pageX-5)+'px';

    }

    }

       document.onmousemove = function(e) {

        if (xxx == 0) {lololol(e);}

    }

Moves the button around. Then it redirects you:

function updateActiveElement()

{

    if ( $(document.activeElement).attr('id')=="xxx" ) 

    {

        clearInterval(interval);

        xxx=1;

window.location = "gallery.html";

    }    

}

 

2. The "tamper-proof" survey page

Is just an iframe with the link above. But there's some interesting JavaScript going on. It checks the following things:

  • That you haven't got an adblocker
  • If you're using mozilla firebug or other javascript console
  • If you're moving around the elements using this console or css editor

3. WTF is "surveys for charity?"

 

 

It's a website set up by the CPA leads (the company behind this). CPA Leads doesn't seem to be a serious company in any way. Registrar info for "surveys for charity": (whois.domaintools.com)

Domain Name:SURVEYSFORCHARITY.ORG
Created On:22-Jan-2010 20:19:29 UTC
Last Updated On:24-Mar-2010 03:48:04 UTC
Expiration Date:22-Jan-2012 20:19:29 UTC
Sponsoring Registrar:GoDaddy.com, Inc. (R91-LROR)
Status:CLIENT DELETE PROHIBITED
Status:CLIENT RENEW PROHIBITED
Status:CLIENT TRANSFER PROHIBITED
Status:CLIENT UPDATE PROHIBITED
Registrant ID:CR40825751
Registrant Name:CPAlead LLC
Registrant Organization:CPAlead.com
Registrant Street1:6845 Escondido Street
Registrant Street2:#107
Registrant Street3:
Registrant City:Las Vegas
Registrant State/Province:Nevada
Registrant Postal Code:89119
Registrant Country:US
Registrant Phone:+1.8669964666
Registrant Phone Ext.:
Registrant FAX:+1.2629224231
Registrant FAX Ext.:
Registrant Email:

 

4. Why the fuck are they doing this?

 

 

I don't know if there is any money in this. The company, CPA Lead, has at least fooled some people into believing that they can make money by serving up others peoples websites through a CPA Lead script. How much CPA themselves get from this, i don't know... Seems like they only wanna waste your time. By spreading it through facebook, using your friends as referalls, they can quickly get a lot of clicks. Its hard to find any information on how much each of these surveys pay, but it seems to be a couple of dollars, or some cents. 

The site 101hottestwomen.com is registered using a name protection service. That seems to be the case with these kind of things.

All the files i've found can be downloaded on: karlwestin.dienstleistungen.ws/scam_decon.zip

 


 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Tue, 18 May 2010 13:32:27 -0700 HTML5 in internet explorer 6 http://karlwestin.posterous.com/html5-in-internet-explorer-6 http://karlwestin.posterous.com/html5-in-internet-explorer-6 Wow!
You couldn't believe that!
When doing the final checks on the site for Malmö Stad Sommarscen (http://www.sommarscen2010.se) in Internet Explorer 6, it worked almost perfectly at the first attempt! And it's written using a lot of HTML5 tags, like <header> <nav> <section> and <article> !!
Who would have thought that??

OK, here's how we roll:

1. Register tags

Ok, IE6 won't recognize the tags without hassle. You'll need to "register" the tags by running a document.createElement(); on each of the tags you're gonna use before you can use them:

example:
         <script>
                  document.createElement("header");
         </script>

Of course, someone has already done this for us, so i used:

         <!--[if lt IE 9]>
                    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js" ></script>
         <![endif]-->

instead. Yes this code is CDN-hosted and you can hotlink it!

Optimizers!! Yessir we want our JS at the bottom, but this one you'll need to keep in the <head> section, else it won't work!

2. Some "safe" css

Then, in order to make sure the elements behaved as i wanted, i used some CSS:

article, header, section, nav, footer {
         display: block;
         position: relative
}

3. The double margin float bug:

To make your floats work in internet explorer 6, you'll have to give them half the margin in the direction the elements are floated. For example, if your original css is:

section {
         float: left;
         margin: 10px 16px 20px 16px;
}

you'll have to follow that up with:

* html section {
         margin-left: 8px;
}

Yes the star (*) is THE way to target internet explorer in your css files. First you write for everyone else, then you follow that by * html (tag) – forget about adding an extra stylesheet, adding extra HTTP-requests. This is how we roll!

We'll that's about it!
If you're site is well coded in general, things should work now!

Comments? Better ideas? Tips? Cool! Comment, please!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Sat, 15 May 2010 14:44:21 -0700 Facebook, pyFacebook and the infamous IntegrityError http://karlwestin.posterous.com/facebook-pyfacebook-and-the-infamous-integrit http://karlwestin.posterous.com/facebook-pyfacebook-and-the-infamous-integrit Currently developing the WalkTheTalk facebook app – i encountered a REALLY annoying error. When i tried to access the application, i got a 500 internal server error. When my friends accessed it, they got in. Why?

Integers and databases
Turns out pyFacebook uses a IntegerField to storing the user id. However, mid 2009 facebook got to many users to store in such a field. My user id had too many figures.

How to solve:
1. Changing the python:
Go to your application folder, and open the models.py file.

• Change all the table fields that uses the user id from models.IntegerField to models.CharField(max_length=64);
example:
        user_id = models.IntegerField
will be:
        user_id = models.CharField(max_length=64)

Then go to the fbcon folder of your web root.
Find the line that says:
        id = models.IntegerField
into
        id = models.CharField(max_length=64, primary_key=True)

2. Altering the mySQL database:
Log on to your mysql database:
        mysql -u username -p
        use
databasename;

First, you'll have to change to pyFacebook user table:
      ALTER TABLE fbcon_use MODIFY id char(64);

Then change the other fields needed in your app with the same command.

That's it, Cheers!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Wed, 12 May 2010 14:05:34 -0700 Using Geo Mashup Locations to sort Wordpress posts http://karlwestin.posterous.com/using-geo-mashup-locations-to-sort-wordpress http://karlwestin.posterous.com/using-geo-mashup-locations-to-sort-wordpress Playing around with geo mashup locations plugin for wordpress the other day, i found a couple of features that arent very well documented.
Geo Mashup adds a few new opportunities to query the posts.

Step 1: Download and install plugin:

http://code.google.com/p/wordpress-geo-mashup/

Step 2: Tag up some posts!

Instructions will be found under the "documentation" part on the site linked above

Step 3: Try out some new queries:

All examples below are entered just before the loop in the .php files.

All posts connected to a certain location:
This one is the easily most interesting one according to me.
GeoMashup::join_post_queries(true);
query_posts('geo_mashup_saved_name=Your Location');
change Your Location into something you've put into your database. Yes you can use that space sir!
combined with others:
GeoMashup::join_post_queries(true);
query_posts($query_vars.'&geo_mashup_saved_name=Your Location&post_type=post');
and so on... You can combine these with any normal wordpress query parameters.

Other options are:

  • geo_mashup_locality (city)
  • geo_mashup_country_code (country code)
  • geo_mashup_date ("Geo Date" don't ask me why :D)
  • geo_mashup_admin_code (administrative area/state code)
  • geo_mashup_postal_code (postal/ZIP Code)
To make the examples above work, make sure you've entered that information to your locations in the admin panel.

You can also order posts by location

GeoMashup::join_post_queries(true);
query_posts($query_vars.'&orderby=geo_mashup_saved_name');
Orders the post by the Location name.
Other possible values:
geo_mashup_country_code
geo_mashup_locality
geo_mashup_date
geo_mashup_admin_code
geo_mashup_postal_code

Thats all for this time :) Thanks!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 10 May 2010 08:34:12 -0700 Data scraping with jQuery and iFrame http://karlwestin.posterous.com/data-scraping-with-jquery-and-iframe http://karlwestin.posterous.com/data-scraping-with-jquery-and-iframe Every now and then, you find yourself having to go into a page, clicking a link, copying something from that page, going back, etc.
It's called data scraping i guess.

Here's an example of how to do it:

You will need
• A webkit browser (firefox with firebug works OK, too)
• Yellow commands is typed into the console (developer tools > console)

First, i need jQuery enabled on the page i wanna scrape.

$(document)

should return an object, if it doesn't, we'll have to enable jQuery:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", "http://code.jquery.com/jquery-1.4.2.js");
document.getElementsByTagName("head")[0].appendChild(fileref);

Alright!!

Step 1: create an iframe:

var yeah = document.createElement("iframe");
yeah.setAttribute("id", "ramen");
document.getElementsByTagName("body")[0].appendChild(yeah);

Step 2: collect the link's you'll need to click:
In my case, they were collected in a div named #fragment-2 :

var links = $("#fragment-2 a");
we'll also need a variable to loop through the links:
var f = 0;

Step 3: functions:
The first function is controlling the loop! It sets the src of the iFrame we created above to the next link in the order!
function loadLink(num) { yeah.setAttribute("src", links[num].href); }

If we'd just loop through the links using links.each( ... we wouldnt get any data, because the page needs to be loaded. Hence, we use $("#ramen").load() to call the script when the page in the iFrame is loaded:
$("#ramen").load(function() { var links2 = $("#ramen").contents().find(".TextShortFacts a"); console.log(links2[0].href); f++; loadLink(f);});

Ok! Lets go through that once! It consists of a couple of lines of code:
$("#ramen").load(function() { });
 is the event handler, it tells the browser when to run the code
var links2 = $("#ramen").contents().find(".TextShortFacts a");
The link we wanna copy is located in a div with the class .TextShortFacts
console.log(links2[0].href);
Types the link we want (the first link of the div retreived above) in the console, where we can easily copy it from later
f++;
Increases the
f
variable one step so we can load the next link on the next line
loadLink(f); is calling the function defined above to load the next link

Step 4: start
loadLink(f);

calls the loadLink function for the first link in the variable, and then the loop is on. Kick back and do something else!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Fri, 16 Apr 2010 16:13:09 -0700 XMLSocket – Streaming data into flash http://karlwestin.posterous.com/xmlsocket-streaming-data-into-flash http://karlwestin.posterous.com/xmlsocket-streaming-data-into-flash I went to see Martin from twingly today, and i learned something, which is awesome!

When you're making a "fake" data stream, for example by having a JavaScript asking for new data every two seconds, the headers of each request can be a couple of kilobytes. If you for example streaming data to aftonbladet, se, with a couple of thousand users at any given moment, these requests will soon eat your bandwith.

The solution? Having whats called an "open socket". How to do that? Well, i checked out one way, through the black sheep of today: flash.

It's actually really simple! Just open up a new flash file (as3), and put the following in the actionscript panel:

var myXML:XMLSocket = new XMLSocket;
configSocket(myXML);
myXML.connect("URL of streaming server", Port); //put your URL and port here

function configSocket(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.CLOSE, closeHandler);
            dispatcher.addEventListener(Event.CONNECT, connectHandler);
            dispatcher.addEventListener(DataEvent.DATA, dataHandler);
}

function closeHandler(event:Event):void {
            trace("closeHandler: " + event);
}

function connectHandler(event:Event):void {
            trace("connectHandler: " + event);
}

function dataHandler(event:DataEvent):void {
            trace("dataHandler: " + event.data);  
            //of course you should do something 
            //more fun than just tracing the data
}

The problem
I knew there was one!!! The problem is of course – how do i set up the XML Socket server to receive some data to my app???

The server must do two things, keep the connection open, plus start and end every "transmission" (not literally) with \0
I found a link to a PERL server that can do just that, good for demoing purposes. 

This demo server just echoes every message that's sent to it. You can send data from flash using the command:

myXML.send("message to send"); // if your variable to your socket connection is myXML

Cheers!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Thu, 15 Apr 2010 11:22:55 -0700 How to see if user is connected with Twitter Anywhere: http://karlwestin.posterous.com/how-to-see-if-user-is-connected-with-twitter http://karlwestin.posterous.com/how-to-see-if-user-is-connected-with-twitter Well, there are some problems in the Twitter Anywhere documentation. Here's how you see if the user is logged in with their twitter account:

<script src="http://platform.twitter.com/anywhere.js?id=yourAPIKey&v=1" type="text/javascript"></script>
<script type = "text/javascript">

twttr.anywhere(onAnywhereLoad);
  function onAnywhereLoad(twitter) {
             
              if(twitter.isConnected()) {
                          // tasks for connected user
              } else {
                          twitter("#twitter-connect-placeholder").connectButton(); //add connect button to users not logged in. Goes to div with id="twitter-connect-placeholder"
              }
  }

</script>

the parenthesis in twitter.isConnected() is very important. They're missing in the current documentation. Without them the statement will always return true!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Thu, 15 Apr 2010 04:41:14 -0700 Twitter user properties and how to get them via @anyhwere http://karlwestin.posterous.com/twitter-user-properties-and-how-to-get-them-v http://karlwestin.posterous.com/twitter-user-properties-and-how-to-get-them-v
Trying out Anywhere, i found that the method twitter.User.current didn't get me any data, just throwing javascript errors.
Looking around a little, a found another method that worked fine!

twttr.anywhere._clients[0].currentUser

try go to a @anywhere-enabled site, and type it into your javascript console (for example http://gowalkthetalk.com)
You need to be logged in to your twitter account (you can do it through the site above if you wanna)

Heres a list of what properties you now can get from the user:

currentUser: B
attributes: Object
contributors_enabled: false
created_at: "Wed Jul 08 22:13:32 +0000 2009"
description: "Web Designer | curtdesign.com | Afrobeat Movement | Flash | jQuery | Typography | Urban Development"
favourites_count: 7
followers_count: 99
following: false
friends_count: 155
geo_enabled: false
id: 55047696
lang: "en"
location: "Malmö, Sweden"
name: "Karl Westin"
notifications: false
profile_background_color: "9AE4E8"
profile_background_image_url: "
Media_httpa1twimgcomp_tdxhc
"
profile_background_tile: false
profile_image_url: "
Media_httpa3twimgcomp_igncd
"
profile_link_color: "0084B4"
profile_sidebar_border_color: "BDDCAD"
profile_sidebar_fill_color: "DDFFCC"
profile_text_color: "333333"
protected: false
screen_name: "karlwestin"
status: Object
statuses_count: 380
time_zone: "Stockholm"
utc_offset: 3600
verified: false

example: 
userName = twttr.anywhere._clients[0].currentUser. attributes;
alert('userName['screen_name'];

will give you "karlwestin" as a string in this case.

Hope it can help anyone!

//karl

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin
Mon, 06 Jul 2009 11:04:51 -0700 min första bild http://karlwestin.posterous.com/min-forsta-bild http://karlwestin.posterous.com/min-forsta-bild
Hstar2

Hej Jonas!

Jag vann!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/553533/skogen.jpg http://posterous.com/users/eG9Bv9WHlL karl westin karlwestin karl westin