July
1st 2011
Building an endless image/photo/screenshot stream

Posted under JavaScript & jQuery & Snippets & WoW-Screenshots

For WoW-Screenshots.net I was looking for a sweet Endless Stream script but I only stumbled into some weird scripts that did more then they should or nothing at all. Finally I ran into a simple script giving some good hints.

For this script jQuery is required and the str_replace port from phpjs.org.

The basics of the script is are simple: on the window scroll event check if the user scrolled nearly or to the bottom of the page if so fetch information from the server and add them to the page.

First off we start with the class constructor

1
2
3
function endlessEntityStream(conf) {
    var self = this;
}

We add a few configuration options and match them against the conf object:

1
2
3
4
5
6
7
self.conf = {};
self.conf.loading = false;
self.conf.identifier = conf.identifier || 'EES_%id%';
self.conf.url = conf.url;
self.conf.count = conf.count;
self.conf.prevId = conf.initalId;
self.conf.template = conf.template;

We load the first batch upon constructing the class. Since the backend provides us with information whether or not we should continue checking for more:

1
self.load(conf.startCount);

We hook into the window scroll event. This and the previous 2 blocks are code are all in the constructor:

1
2
3
$(window).scroll(function(){
    self.check();
});

Now we need 2 settings and 2 getters to keep the code a bit cleaner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
endlessEntityStream.prototype.setLoading = function(bool) {
    var self = this;
    self.conf.loading = bool ? true : false;
};

endlessEntityStream.prototype.getLoading = function() {
    var self = this;
    return self.conf.loading;
};

endlessEntityStream.prototype.setPrevId = function(prevId) {
    var self = this;
    self.conf.prevId = prevId;
};

endlessEntityStream.prototype.getPrevId = function() {
    var self = this;
    return self.conf.prevId;
};

The following functions are the most interesting. First the check function that checks the scroll status. Seccond the load function that does most of the heavy lifting.

The function works very simple. It check if you either scrolled to the end of the page or within the 500 pixels above the end of the page. Then it checks if a load is already in progress and load if not. Note the 500 in the function, change that to your needs if the default isn’t working properly.

1
2
3
4
5
6
7
8
endlessEntityStream.prototype.check = function() {
    var self = this;
    if($(window).scrollTop() == $(document).height() - $(window).height() || ($(window).scrollTop() + 500) >= $(document).height() - $(window).height()) {
        if(!self.getLoading()) {
            self.load(self.count);
        }
    }
};

We start the load function by preventing another load can start. Another imported part of this method is the replacing of 3 keywords with the corresponding information.

  • %id% – the id of the last added item, the backend uses this the determine where to start reading
  • %count% – the amount of items the backend should return
  • %mathrnd% – a random number, it can be used to force updates
1
2
3
4
5
6
7
8
endlessEntityStream.prototype.load = function(count) {
    var self = this;
    self.setLoading(true);
    url = self.conf.url;
    url = url.replace('%id%',self.conf.prevId);
    url = url.replace('%count%',self.conf.count);
    url = url.replace('%mathrnd%',Math.random().toString().replace('0.',''));
};

Now we know where we should fetch the information from we can send the request and parse the returned data:

1
2
3
4
5
6
7
$.get(url,
    function(data){
        if (data != "") {
            var entities = $.parseJSON(data);
        }
    }
);

After the data has been parsed we’ll walk through the data and add the item at the end of the stream. This happens in several steps. First off an identifier is generated for the current item and the identifier (based on the previous id) from the previous item is generated. Second the entity properties are matched against the template. And finally the item is added to the end of the stream and the current id is set as previous id.

1
2
3
4
5
6
7
8
9
10
11
for(var entity in entities.shots) {
    var identifier = self.conf.identifier.replace('%id%', entities.shots[entity].id);
    var previousIdentifier = self.conf.identifier.replace('%id%', self.getPrevId());
    var html = self.conf.template;
    $.each(entities.shots[entity], function(index,value) {
        html = str_replace('%' + index + '%', value , html);
    });
    html = html.replace('%identifier%', identifier);
    $('#' + previousIdentifier).after(html);
    self.setPrevId(entities.shots[entity].id);
}

Once everything has been loaded we’ll check the data if this is the last block or not. If it’s the last block it keeps the loading process locked. If it isn’t the last block it unlocks the loading process and invokes the check method again. This makes sure a user keeps buffered at all times until there is nothing more to fetch.

1
2
3
4
5
6
if(entities.lastShot) {
    self.setLoading(true);
} else {
    self.setLoading(false);
    self.check();
}

We now have all the class code ready to use we need to tell it where to get it’s data from and how to append it where. The following configuration options are needed to make it all work:

url – Url

1
http://domain.tld/path/to/stream/%id%/%count%/

target – The stream container

1
ESSContainer

initalId – The id of the last item in the preloaded stream.

1
123

count – The number of items to be returned by the server. %count% in the url parameter is replaced by this number.

1
25

template – Template for the item placed at the end of the stream.

1
<a href="%href%" id="%identifier%" title="%title%"><img src="%src%" alt="%title%" /></a>

debug – The debug option is optional but can be useful to debug issues with this script.

1
true

Combined that gives you this:

1
2
3
4
5
6
7
ees = new endlessEntityStream({
    url: 'http://domain.tld/path/to/stream/%id%/%count%/',    
    target: 'ESSContainer',
    initalId: 123,
    count: 5,
    template: '<a href="%href%" id="%identifier%" title="%title%"><img src="%src%" alt="%title%" /></a>'
});
1
2
3
4
5
<div id="ESSContainer">
    <a id="EES_121" href="/model/view/121.html" title=""><img src="/img/121.jpg" alt="" /></a>
    <a id="EES_122" href="/model/view/121.html" title=""><img src="/img/122.jpg" alt="" /></a>
    <a id="EES_123" href="/model/view/121.html" title=""><img src="/img/123.jpg" alt="" /></a>
</div>

The script expects a JSON object in the following format:

1
2
3
4
5
6
7
8
9
10
11
12
{
    "lastShot":false,
    "count":5,
    "shots":
    [
        {"id":"124","href":"\/model\/view\/124.html","src":"\/img\/124.jpg","title":""},
        {"id":"125","href":"\/model\/view\/125.html","src":"\/img\/125.jpg","title":""},
        {"id":"126","href":"\/model\/view\/126.html","src":"\/img\/126.jpg","title":""},
        {"id":"127","href":"\/model\/view\/127.html","src":"\/img\/127.jpg","title":""},
        {"id":"128","href":"\/model\/view\/128.html","src":"\/img\/128.jpg","title":""}
    ]
}

As you can see the object holds 2 configuration settings and 1 array with all the items. (Heck while writing this I realize that shots as name for the array might not but the appropriate name for a more general class.) The count property optional. lastShot tells the script if the shots array contains the last item and should stop polling after this.

This code is available on github. As for the future of this project it will evolve for the upcoming time to become an even more powerful script. (Might turn it into a jQuery plugin.) For a live demo see WoW-Screenshots.net.

No Comments »

July
4th 2010
My first Google Chrome extensions for Wowhead, Thottbot, MMOC and Wowdb

Posted under Google Chrome & Releases

After switching to Chrome a few days ago and hearing Joshua talking about how easy it is to write extensions for Chrome I decided to give it a try. One of the first thing coming to mind was everyone linking to wowhead, thottbot and all but you never know what exactly they are linking untill you click it. Most World of Warcraft database sites supply a handy tooltip script solving this problem. After a talk with Joshua and how Chrome plugins are written I gave it a shot.

The result are 4 extensions (tho basically the same code but adjusted for the 4 sites) that first check if the tooltip script is already in the webppage and stop there if it is. If the script isn’t present but links to the site are present it inserts the tooltip script into the body of the page thus attaching tooltips to the links.

The extensions:

Wowhead

Thottbot

MMO Champion DB

Wowdb.com

Planning to do the same for a few other database sites later on in the week after some phpBB3 MOD work :) .

No Comments »

May
27th 2010
Retaking of the Echo Isles (Zalazane’s Fall) PTR Screenshots

Posted under World of Warcraft

Here are some screenshots from the retaking of the Echo Isles (as requested here):


























1 Comment »

August
31st 2009
World of Warcraft Panorama’s try out: Thunderfall

Posted under World of Warcraft

Between all the coding, testing and sleeping I like to do something graphic once in a while. This time I tried out some idea's for panorama's. I went for Thunderfall in World of Warcraft. Below is the result of this.

Thunderfall

Now I have this idea spinning in my mind to create mare of these (higher detail and worked out better tho since this once contains some glitches) and add them to WyriMaps.net. What places should I do before Cataclysm strikes. Lemme know,

WyriHaximus

No Comments »

August
22nd 2009
World of Warcraft: Cataclysm logo’s

Posted under World of Warcraft

Just like I did with the WoW Trans logo here is the new logo for World of Warcraft: Cataclysm

Original Size:

World of Warcraft: Cataclysm Logo (Click for real size)

1024x 441:

World of Warcraft: Cataclysm Logo (Click for real size)

2 Comments »