<commit_before>var search = (function () {

var exports = {};

var cached_term = "";
var cached_matches = [];
var cached_index;
var cached_table = $('table.focused_table');
var current_search_term;

function narrow_or_search_for_term(search_string) {
    var search_query_box = $("#search_query");
    ui.change_tab_to('#home');
    var operators = narrow.parse(search_string);
    narrow.activate(operators, {trigger: 'search'});

    // It's sort of annoying that this is not in a position to
    // blur the search box, because it means that Esc won't
    // unnarrow, it'll leave the searchbox.

    // Narrowing will have already put some operators in the search box,
    // so leave the current text in.
    search_query_box.blur();
    return search_query_box.val();
}

function update_buttons_with_focus(focused) {
    var search_query = $('#search_query');

    // Show buttons iff the search input is focused, or has non-empty contents,
    // or we are narrowed.
    if (focused
        || search_query.val()
        || narrow.active()) {
        $('.search_button').removeAttr('disabled');
    } else {
        $('.search_button').attr('disabled', 'disabled');
    }
}

exports.update_button_visibility = function () {
    update_buttons_with_focus($('#search_query').is(':focus'));
};

exports.initialize = function () {

    // Data storage for the typeahead.
    // This maps a search string to an object with a "description" field.
    // (It's a bit of legacy that we have an object with only one important
    // field.  There's also a "search_string" field on each element that actually
    // just represents the key of the hash, so it's redundant.)
    var search_object = {};

    $( "#search_query" ).typeahead({
        source: function (query) {
            var suggestions = search_suggestion.get_suggestions(query);
            // Update our global search_object hash
            search_object = suggestions.lookup_table;
            return suggestions.strings;
        },
        items: 30,
        helpOnEmptyStrings: true,
        naturalSearch: true,
        highlighter: function (item) {
            var obj = search_object[item];
            return obj.description;
        },
        matcher: function (item) {
            return true;
        },
        updater: narrow_or_search_for_term,
        sorter: function (items) {
            return items;
        }
    });

    $("#searchbox_form").keydown(function (e) {
        exports.update_button_visibility();
        var code = e.which;
        var search_query_box = $("#search_query");
        if (code === 13 && search_query_box.is(":focus")) {
            // Don't submit the form so that the typeahead can instead
            // handle our Enter keypress. Any searching that needs
            // to be done will be handled in the keyup.
            e.preventDefault();
            return false;
        }
    }).keyup(function (e) {
        var code = e.which;
        var search_query_box = $("#search_query");
        if (code === 13 && search_query_box.is(":focus")) {
            // We just pressed enter and the box had focus, which
            // means we didn't use the typeahead at all.  In that
            // case, we should act as though we're searching by
            // operators.  (The reason the other actions don't call
            // this codepath is that they first all blur the box to
            // indicate that they've done what they need to do)
            narrow.activate(narrow.parse(search_query_box.val()));
            search_query_box.blur();
            update_buttons_with_focus(false);
        }
    });

    // Some of these functions don't actually need to be exported,
    // but the code was moved here from elsewhere, and it would be
    // more work to re-order everything and make them private.
    $('#search_exit' ).on('click', exports.clear_search);

    var query = $('#search_query');
    query.on('focus', exports.focus_search)
         .on('blur' , function () {

        // The search query box is a visual cue as to
        // whether search or narrowing is active.  If
        // the user blurs the search box, then we should
        // update the search string to reflect the currect
        // narrow (or lack of narrow).
        //
        // But we can't do this right away, because
        // selecting something in the typeahead menu causes
        // the box to lose focus a moment before.
        //
        // The workaround is to check 100ms later -- long
        // enough for the search to have gone through, but
        // short enough that the user won't notice (though
        // really it would be OK if they did).

        setTimeout(function () {
            var search_string = narrow.search_string();
            query.val(search_string);
            exports.update_button_visibility();
        }, 100);
    });
};

function match_on_visible_text(row, search_term) {
    // You can't select on :visible, since that includes hidden elements that
    // take up space.
    return row.find(".message_content, .message_header")
              .text().toLowerCase().indexOf(search_term) !== -1;
}

exports.focus_search = function () {
    // The search bar is not focused yet, but will be.
    update_buttons_with_focus(true);
};

exports.initiate_search = function () {
    $('#search_query').select();
};

exports.clear_search = function () {
    narrow.deactivate();

    $('table tr').removeHighlight();
    $('#search_query').blur();
    exports.update_button_visibility();
};

return exports;

}());
if (typeof module !== 'undefined') {
    module.exports = search;
}
<commit_msg>Remove dead vars in search.js<commit_after>var search = (function () {

var exports = {};

function narrow_or_search_for_term(search_string) {
    var search_query_box = $("#search_query");
    ui.change_tab_to('#home');
    var operators = narrow.parse(search_string);
    narrow.activate(operators, {trigger: 'search'});

    // It's sort of annoying that this is not in a position to
    // blur the search box, because it means that Esc won't
    // unnarrow, it'll leave the searchbox.

    // Narrowing will have already put some operators in the search box,
    // so leave the current text in.
    search_query_box.blur();
    return search_query_box.val();
}

function update_buttons_with_focus(focused) {
    var search_query = $('#search_query');

    // Show buttons iff the search input is focused, or has non-empty contents,
    // or we are narrowed.
    if (focused
        || search_query.val()
        || narrow.active()) {
        $('.search_button').removeAttr('disabled');
    } else {
        $('.search_button').attr('disabled', 'disabled');
    }
}

exports.update_button_visibility = function () {
    update_buttons_with_focus($('#search_query').is(':focus'));
};

exports.initialize = function () {

    // Data storage for the typeahead.
    // This maps a search string to an object with a "description" field.
    // (It's a bit of legacy that we have an object with only one important
    // field.  There's also a "search_string" field on each element that actually
    // just represents the key of the hash, so it's redundant.)
    var search_object = {};

    $( "#search_query" ).typeahead({
        source: function (query) {
            var suggestions = search_suggestion.get_suggestions(query);
            // Update our global search_object hash
            search_object = suggestions.lookup_table;
            return suggestions.strings;
        },
        items: 30,
        helpOnEmptyStrings: true,
        naturalSearch: true,
        highlighter: function (item) {
            var obj = search_object[item];
            return obj.description;
        },
        matcher: function (item) {
            return true;
        },
        updater: narrow_or_search_for_term,
        sorter: function (items) {
            return items;
        }
    });

    $("#searchbox_form").keydown(function (e) {
        exports.update_button_visibility();
        var code = e.which;
        var search_query_box = $("#search_query");
        if (code === 13 && search_query_box.is(":focus")) {
            // Don't submit the form so that the typeahead can instead
            // handle our Enter keypress. Any searching that needs
            // to be done will be handled in the keyup.
            e.preventDefault();
            return false;
        }
    }).keyup(function (e) {
        var code = e.which;
        var search_query_box = $("#search_query");
        if (code === 13 && search_query_box.is(":focus")) {
            // We just pressed enter and the box had focus, which
            // means we didn't use the typeahead at all.  In that
            // case, we should act as though we're searching by
            // operators.  (The reason the other actions don't call
            // this codepath is that they first all blur the box to
            // indicate that they've done what they need to do)
            narrow.activate(narrow.parse(search_query_box.val()));
            search_query_box.blur();
            update_buttons_with_focus(false);
        }
    });

    // Some of these functions don't actually need to be exported,
    // but the code was moved here from elsewhere, and it would be
    // more work to re-order everything and make them private.
    $('#search_exit' ).on('click', exports.clear_search);

    var query = $('#search_query');
    query.on('focus', exports.focus_search)
         .on('blur' , function () {

        // The search query box is a visual cue as to
        // whether search or narrowing is active.  If
        // the user blurs the search box, then we should
        // update the search string to reflect the currect
        // narrow (or lack of narrow).
        //
        // But we can't do this right away, because
        // selecting something in the typeahead menu causes
        // the box to lose focus a moment before.
        //
        // The workaround is to check 100ms later -- long
        // enough for the search to have gone through, but
        // short enough that the user won't notice (though
        // really it would be OK if they did).

        setTimeout(function () {
            var search_string = narrow.search_string();
            query.val(search_string);
            exports.update_button_visibility();
        }, 100);
    });
};

function match_on_visible_text(row, search_term) {
    // You can't select on :visible, since that includes hidden elements that
    // take up space.
    return row.find(".message_content, .message_header")
              .text().toLowerCase().indexOf(search_term) !== -1;
}

exports.focus_search = function () {
    // The search bar is not focused yet, but will be.
    update_buttons_with_focus(true);
};

exports.initiate_search = function () {
    $('#search_query').select();
};

exports.clear_search = function () {
    narrow.deactivate();

    $('table tr').removeHighlight();
    $('#search_query').blur();
    exports.update_button_visibility();
};

return exports;

}());
if (typeof module !== 'undefined') {
    module.exports = search;
}
<|endoftext|>


<commit_before>function highlight(evt){
    var tag = $(evt.target).prop("name");
    $("div#source-text").unhighlight();

    // highlight a beginning tag (two cases)
    $("div#source-text").highlight("<"+tag +">");
    $("div#source-text").highlight("<"+tag +" ");

    // highlight an ending tag
    $("div#source-text").highlight("</"+tag+">");

    $("#tag-info").empty();
    $("#tag-info").html(""+tag+" tag is highlighted");
}

// $(function() {

    function displayTagCount(data){
        $("#tag-count-header").show();
        $("#tag-count-loading").hide();

        // iterate through the object of tags and counts
        $.each( data, function( key, value ) {
          $("#tag-count").append( ""+key +""+ ": " + value+" time(s)
" );
        });
    }

    function displaySourceText(data){
        $("#source-text-header").show();
        $("#source-text-loading").hide();
        $("#source-text").html(data);
        $("#submit-btn").removeAttr("disabled");

        // show TOP buttom (at bottom of source text)
        $("#top-btn").show();
    }

    function executeSearch(){

        var url = {
            "source": $("#source").val()
        };

        // AJAX calls - fill in tag counts and source text of URL
        $.get("/count-tags.json", url, displayTagCount);
        $.get("/source-text.json", url, displaySourceText);

        // get rid of previous content
        $("#tag-count").empty();
        $("#source-text").empty();
        $("#tag-info").empty();

        // loading wheels in each section
        $("#tag-count-loading").show();
        $("#source-text-loading").show();

        // show the div tag that has all tag count / source text info
        $("#tag").show();

        // scroll
        window.location = "#tag";

    }

    function checkAnswer(data){

        // URL
        var source = $("#source").val();

        // if the URL is valid
        if(data === "True"){
            executeSearch();
        }

        // if the URL is not valid
        else{

            // checks to see if there is an http in the address and there isn't
            // capture both upper and lower case
            if (source.indexOf("http") == -1 || source.indexOf("HTTP") == -1){
                $("#warning").show();
                $("#warning").html(" This is not a valid URL
Try adding 'http://' or 'https://' to the beginning");
            }

            // has http in addresss
            else{
                $("#warning").show();
                $("#warning").html(" This is not a valid URL");
            }

            // enable search again
            $("#submit-btn").removeAttr("disabled");

            // hide div with tag count and source text
            $("#tag").hide();
        }

    }

    function checkUrl(evt){
        evt.preventDefault();

        // disable button
        $("#submit-btn").prop("disabled", "true");

        // hide/clear the warning text
        $("#warning").hide().empty();

        var url = {
            "source": $("#source").val()
        };

        // if the user is searching for http://textsource.herokuapp.com
        if(url.source.indexOf("http://textsource.herokuapp.com") != -1){
            $('#myModal').modal('show');

            // enable search again
            $("#submit-btn").removeAttr("disabled");

        }

        // otherwise, AJAX to verify URL link
        else{
            $.get("/check-url.json", url, checkAnswer);
        }
    }

    // event listener for URL submission
    $("#input-form").on("submit", checkUrl);

    // hide warning box (even if empty, has opaque borders that show)
    $("#warning").hide();

// });
<commit_msg>cleaning up<commit_after>function highlight(evt){
    var tag = $(evt.target).prop("name");
    $("div#source-text").unhighlight();

    // highlight a beginning tag (two cases)
    $("div#source-text").highlight("<"+tag +">");
    $("div#source-text").highlight("<"+tag +" ");

    // highlight an ending tag
    $("div#source-text").highlight("</"+tag+">");

    $("#tag-info").empty();
    $("#tag-info").html(""+tag+" tag is highlighted");
}

// $(function() {

    function displayTagCount(data){
        $("#tag-count-header").show();
        $("#tag-count-loading").hide();

        // iterate through the object of tags and counts
        $.each( data, function( key, value ) {
          $("#tag-count").append( ""+key +""+ ": " + value+" time(s)
" );
        });
    }

    function displaySourceText(data){
        $("#source-text-header").show();
        $("#source-text-loading").hide();
        $("#source-text").html(data);
        $("#submit-btn").removeAttr("disabled");

        // show TOP buttom (at bottom of source text)
        $("#top-btn").show();
    }

    function executeSearch(){

        var url = {
            "source": $("#source").val()
        };

        // AJAX calls - fill in tag counts and source text of URL
        $.get("/count-tags.json", url, displayTagCount);
        $.get("/source-text.json", url, displaySourceText);

        // get rid of previous content
        $("#tag-count").empty();
        $("#source-text").empty();
        $("#tag-info").empty();

        // loading wheels in each section
        $("#tag-count-loading").show();
        $("#source-text-loading").show();

        // show the div tag that has all tag count / source text info
        $("#tag").show();

        // scroll to desired place on page
        window.location = "#tag";

    }

    function checkAnswer(data){

        // URL (converted to all lowercase)
        var source = $("#source").val().toLowerCase();

        // if the URL is valid
        if(data === "True"){
            executeSearch();
        }

        // if the URL is not valid
        else{

            // checks to see if there is an http in the address and there isn't
            if (source.indexOf("http") == -1){
                $("#warning").show();
                $("#warning").html(" This is not a valid URL
Try adding 'http://' or 'https://' to the beginning");
            }

            // has http in addresss
            else{
                $("#warning").show();
                $("#warning").html(" This is not a valid URL");
            }

            // enable search again
            $("#submit-btn").removeAttr("disabled");

            // hide div with tag count and source text
            $("#tag").hide();
        }

    }

    function checkUrl(evt){
        evt.preventDefault();

        // disable button
        $("#submit-btn").prop("disabled", "true");

        // hide/clear the warning text
        $("#warning").hide().empty();

        var url = {
            "source": $("#source").val().toLowerCase()
        };

        // if the user is searching for http://textsource.herokuapp.com
        if(url.source.indexOf("http://textsource.herokuapp.com") != -1){
            $('#myModal').modal('show');

            // enable search again
            $("#submit-btn").removeAttr("disabled");

        }

        // otherwise, AJAX to verify URL link
        else{
            $.get("/check-url.json", url, checkAnswer);
        }
    }

    // event listener for URL submission
    $("#input-form").on("submit", checkUrl);

    // hide warning box (even if empty, has opaque borders that show)
    $("#warning").hide();

// });
<|endoftext|>


<commit_before>var today = new Date();
var day = '06';
var monthi = '09';
var monthf = '10';
var dayCheck = today.getDate();
var monthCheck = today.getMonth();

if(((monthCheck == 00 && dayCheck <= 6) || (monthCheck == 11 && dayCheck >= 3))) {
	var snowMax=35;var snowColor=["#DDD","#EEE"];var snowEntity="•";var snowSpeed=0.75;var snowMinSize=8;var snowMaxSize=24;var snowRefresh=50;var snowStyles="cursor: default; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none;";var snow=[],pos=[],coords=[],lefr=[],marginBottom,marginRight;function randomise(range){rand=Math.floor(range*Math.random());return rand;}
	function initSnow(){var snowSize=snowMaxSize- snowMinSize;marginBottom=document.body.scrollHeight- 5;marginRight=document.body.clientWidth- 15;for(i=0;i<=snowMax;i++){coords[i]=0;lefr[i]=Math.random()*15;pos[i]=0.03+ Math.random()/ 10;
	snow[i]=document.getElementById("flake"+ i);snow[i].style.fontFamily="inherit";snow[i].size=randomise(snowSize)+ snowMinSize;snow[i].style.fontSize=snow[i].size+"px";snow[i].style.color=snowColor[randomise(snowColor.length)];snow[i].style.zIndex=1000;snow[i].sink=snowSpeed*snow[i].size/5;snow[i].posX=randomise(marginRight- snow[i].size);snow[i].posY=randomise(2*marginBottom- marginBottom- 2*snow[i].size);snow[i].style.left=snow[i].posX+"px";snow[i].style.top=snow[i].posY+"px";}
	moveSnow();}
	function resize(){marginBottom=document.body.scrollHeight- 5;marginRight=document.body.clientWidth- 15;}
	function moveSnow(){for(i=0;i<=snowMax;i++){coords[i]+=pos[i];snow[i].posY+=snow[i].sink;snow[i].style.left=snow[i].posX+ lefr[i]*Math.sin(coords[i])+"px";snow[i].style.top=snow[i].posY+"px";if(snow[i].posY>=marginBottom- 2*snow[i].size||parseInt(snow[i].style.left)>(marginRight- 3*lefr[i])){snow[i].posX=randomise(marginRight- snow[i].size);snow[i].posY=0;}}
	setTimeout("moveSnow()",snowRefresh);}
	for(i=0;i<=snowMax;i++){document.write(""+ snowEntity+"");}
	window.onresize=resize;window.onload=initSnow;
}
<commit_msg>Update winter.js<commit_after>var today = new Date();
var day = '06';
var monthi = '09';
var monthf = '10';
var dayCheck = today.getDate();
var monthCheck = today.getMonth();

if(((monthCheck == 00 && dayCheck <= 6) || (monthCheck == 11 && dayCheck >= 2))) {
	var snowMax=35;var snowColor=["#DDD","#EEE"];var snowEntity="•";var snowSpeed=0.75;var snowMinSize=8;var snowMaxSize=24;var snowRefresh=50;var snowStyles="cursor: default; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none;";var snow=[],pos=[],coords=[],lefr=[],marginBottom,marginRight;function randomise(range){rand=Math.floor(range*Math.random());return rand;}
	function initSnow(){var snowSize=snowMaxSize- snowMinSize;marginBottom=document.body.scrollHeight- 5;marginRight=document.body.clientWidth- 15;for(i=0;i<=snowMax;i++){coords[i]=0;lefr[i]=Math.random()*15;pos[i]=0.03+ Math.random()/ 10;
	snow[i]=document.getElementById("flake"+ i);snow[i].style.fontFamily="inherit";snow[i].size=randomise(snowSize)+ snowMinSize;snow[i].style.fontSize=snow[i].size+"px";snow[i].style.color=snowColor[randomise(snowColor.length)];snow[i].style.zIndex=1000;snow[i].sink=snowSpeed*snow[i].size/5;snow[i].posX=randomise(marginRight- snow[i].size);snow[i].posY=randomise(2*marginBottom- marginBottom- 2*snow[i].size);snow[i].style.left=snow[i].posX+"px";snow[i].style.top=snow[i].posY+"px";}
	moveSnow();}
	function resize(){marginBottom=document.body.scrollHeight- 5;marginRight=document.body.clientWidth- 15;}
	function moveSnow(){for(i=0;i<=snowMax;i++){coords[i]+=pos[i];snow[i].posY+=snow[i].sink;snow[i].style.left=snow[i].posX+ lefr[i]*Math.sin(coords[i])+"px";snow[i].style.top=snow[i].posY+"px";if(snow[i].posY>=marginBottom- 2*snow[i].size||parseInt(snow[i].style.left)>(marginRight- 3*lefr[i])){snow[i].posX=randomise(marginRight- snow[i].size);snow[i].posY=0;}}
	setTimeout("moveSnow()",snowRefresh);}
	for(i=0;i<=snowMax;i++){document.write(""+ snowEntity+"");}
	window.onresize=resize;window.onload=initSnow;
}
<|endoftext|>


<commit_before>/* jshint unused:false */

var _config = {DEBUG: false};
var _currentUserData;
var _presenceSocket;
var ports;
var browserPort;
var currentCall;
var currentUsers;

function openChatWindow() {
  browserPort.postEvent('social.request-chat', 'chat.html');
}

/**
 * Social API user profile data storage.
 * @param {Object|undefined}  initial  Initial data
 * @param {Object|undefined}  config   Environment configuration
 */
function UserData(initial, config) {
  var rootURL = config ? config.ROOTURL : '';

  this.defaults = {
    iconURL: rootURL + "/talkilla16.png",
    portrait: undefined,
    userName: undefined,
    displayName: undefined,
    profileURL: rootURL + "/user.html"
  };

  this.reset();

  if (initial) {
    for (var key in initial)
      this[key] = initial[key];
  }
}

UserData.prototype = {
  /**
   * Resets current properties to default ones.
   */
  reset: function() {
    for (var key in this.defaults)
      this[key] = this.defaults[key];
  }
};

var serverHandlers = {
  'users': function(data) {
    currentUsers = data;
    ports.broadcastEvent("talkilla.users", data);
  },

  'incoming_call': function(data) {
    currentCall = {port: undefined, data: data};
    openChatWindow();
  },

  'call_accepted': function(data) {
    currentCall.port.postEvent('talkilla.call-establishment', data);
  },

  'call_hangup': function(data) {
    currentCall.port.postEvent('talkilla.call-hangup', data);
    currentCall = undefined;
  }
};

function _presenceSocketOnMessage(event) {
  var data = JSON.parse(event.data);
  for (var eventType in data)
    if (eventType in serverHandlers)
      serverHandlers[eventType](data[eventType]);
    else
      ports.broadcastEvent("talkilla." + eventType, data[eventType]);
}

function _presenceSocketSendMessage(data) {
  _presenceSocket.send(data);
}

function _presenceSocketOnOpen(event) {
  "use strict";

  ports.broadcastEvent("talkilla.presence-open", event);
}

function _presenceSocketOnError(event) {
  "use strict";

  ports.broadcastEvent("talkilla.websocket-error", event);
}

function _presenceSocketOnClose(event) {
  "use strict";

  // XXX: this will need future work to handle retrying presence connections
  ports.broadcastEvent('talkilla.presence-unavailable', event.code);
  currentUsers = undefined;
}

function createPresenceSocket(nickname) {
  "use strict";

  _presenceSocket = new WebSocket(_config.WSURL + "?nick=" + nickname);
  _presenceSocket.onopen = _presenceSocketOnOpen;
  _presenceSocket.onmessage = _presenceSocketOnMessage;
  _presenceSocket.onerror = _presenceSocketOnError;
  _presenceSocket.onclose = _presenceSocketOnClose;

  ports.broadcastEvent("talkilla.presence-pending", {});
}

function _loginExpired() {
  _presenceSocket.removeEventListener("error", _loginExpired);
  ports.broadcastEvent("talkilla.logout-success", {});
}

function _presenceSocketReAttached(username, event) {
  _presenceSocket.removeEventListener("open", _presenceSocketReAttached);
  setupWebSocket(_presenceSocket);
  _setUserProfile(username);
  _presenceSocketOnOpen(event);
  ports.broadcastEvent("talkilla.login-success", {username: username});
}

function setupWebSocket(ws) {
  ws.onopen = _presenceSocketOnOpen;
  ws.onmessage = _presenceSocketOnMessage;
  ws.onerror = _presenceSocketOnError;
  ws.onclose = _presenceSocketOnClose;
}

function tryPresenceSocket(nickname) {
  "use strict";

  _presenceSocket = new WebSocket(_config.WSURL + "?nick=" + nickname);
  _presenceSocket.addEventListener("open", _presenceSocketReAttached.bind(this, nickname));
  _presenceSocket.addEventListener("error", _loginExpired);
  ports.broadcastEvent("talkilla.presence-pending", {});
}

function sendAjax(url, method, data, cb) {
  var xhr = new XMLHttpRequest();

  xhr.onload = function(event) {
    // sinon.js can call us with a null event a second time, so just ignore it.
    if (!event)
      return;
    if (xhr.readyState === 4 && xhr.status === 200)
      return cb(null, xhr.responseText);
    cb(xhr.statusText);
  };

  xhr.onerror = function(event) {
    if (event && event.target)
      cb(event.target.status ? event.target.statusText : "We are offline");
  };

  xhr.open(method || 'GET', url, true);
  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.send(JSON.stringify(data));
}

function loadconfig(cb) {
  sendAjax('/config.json', 'GET', {}, function(err, data) {
    var config;
    try {
      config = JSON.parse(data);
    } catch (err) {
      return cb(err);
    }
    cb(null, config);
  });
}

function _setUserProfile(username) {
  _currentUserData.userName = _currentUserData.displayName = username;
  _currentUserData.portrait = "test.png";
  browserPort.postEvent('social.user-profile', _currentUserData);
}

function _signinCallback(err, responseText) {
  if (err)
    return this.postEvent('talkilla.login-failure', err);
  var username = JSON.parse(responseText).nick;
  if (username) {
    _setUserProfile(username);

    ports.broadcastEvent('talkilla.login-success', {
      username: username
    });

    createPresenceSocket(username);
  }
}

function _signoutCallback(err, responseText) {
  if (err)
    return this.postEvent('talkilla.error', 'Bad signout:' + err);

  _currentUserData.reset();
  browserPort.postEvent('social.user-profile', _currentUserData);
  currentUsers = undefined;
  ports.broadcastEvent('talkilla.logout-success');
}

var handlers = {
  // SocialAPI events
  'social.port-closing': function() {
    ports.remove(this);
  },

  'social.initialize': function() {
    browserPort = this;
  },

  // Talkilla events
  'talkilla.login': function(msg) {
    if (!msg.data || !msg.data.username) {
      return this.postEvent('talkilla.login-failure', 'no username specified');
    }

    this.postEvent('talkilla.login-pending', null);

    sendAjax('/signin', 'POST', {nick: msg.data.username},
      _signinCallback.bind(this));
  },

  'talkilla.logout': function() {
    if (!_currentUserData.userName) {
      return this.postEvent('talkilla.error',
                            'trying to logout when not logged in');
    }

    _presenceSocket.close();
    sendAjax('/signout', 'POST', {nick: _currentUserData.userName},
      _signoutCallback.bind(this));
  },

  'talkilla.call-start': function(event) {
    // XXX Temporarily work around to only allow one call at a time.
    if (!currentCall) {
      currentCall = {port: undefined, data: event.data};
      openChatWindow();
    }
  },

  'talkilla.chat-window-ready': function() {
    currentCall.port = this;

    if (_currentUserData.userName) {
      // If there's currenty a logged in user,
      this.postEvent('talkilla.login-success', {
        username: _currentUserData.userName
      });
    }

   // If this is an incoming call, we won't have the port yet.
    var topic = currentCall.data.offer ?
      "talkilla.call-incoming" :
      "talkilla.call-start";

    this.postEvent(topic, currentCall.data);
  },

  'talkilla.sidebar-ready': function(event) {
    if (_currentUserData.userName) {
      // If there's currently a logged in user,
      this.postEvent('talkilla.login-success', {
        username: _currentUserData.userName
      });
      if (currentUsers)
        this.postEvent('talkilla.users', currentUsers);
    } else if (event.data.nick) {
      // No user data available, may still be logged in
      tryPresenceSocket(event.data.nick);
    }
  },

  /**
   * The data for talkilla.call-offer is:
   *
   * - callee: the person you are calling
   * - caller: the person who is calling you
   * - offer: an RTCSessionDescription containing the sdp data for the call.
   */
  'talkilla.call-offer': function(event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_offer': event.data }));
  },

  /**
   * The data for talkilla.call-answer is:
   *
   * - callee: the person you are calling
   * - caller: the person who is calling you
   * - offer: an RTCSessionDescription containing the sdp data for the call.
   */
  'talkilla.call-answer': function (event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_accepted': event.data }));
  },

  /**
   * Ends a call. The expected data is:
   *
   * - other: the person you are talking to.
   */
  'talkilla.call-hangup': function (event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_hangup': event.data }));
    currentCall = undefined;
  },

  'talkilla.sidebar-ready': function (event) {
    if (event.data.nick)
      tryPresenceSocket(event.data.nick);
  }
};

function Port(port) {
  this.port = port;
  this.id = port._portid;
  // configures this port
  port.onmessage = this.onmessage.bind(this);
}

Port.prototype = {
  /**
   * Posts an error event.
   * @param  {String} error
   */
  error: function(error) {
    this.postEvent("talkilla.error", error);
  },

  /**
   * Port message listener.
   * @param  {Event} event
   */
  onmessage: function(event) {
    var msg = event.data;
    if (msg && msg.topic && (msg.topic in handlers))
      handlers[msg.topic].call(this, msg);
    else
      this.error('Topic is missing or unknown');
  },

  /**
   * Posts a message event.
   * @param  {String} topic
   * @param  {Mixed}  data
   */
  postEvent: function(topic, data) {
    this.port.postMessage({topic: topic, data: data});
  }
};

function PortCollection() {
  this.ports = {};
}

PortCollection.prototype = {
  /**
   * Configures and add a port to the stack.
   * @param  {Port} port
   */
  add: function(port) {
    if (port.id in this.ports)
      return;
    this.ports[port.id] = port;
  },

  /**
   * Removes a port from this collection.
   * @param  {Port} port
   */
  remove: function(port) {
    if (port && port.id)
      delete this.ports[port.id];
  },

  /**
   * Retrieves a port from the collection by its id.
   * @param  {String} id
   * @return {Port}
   */
  find: function(id) {
    return this.ports[id];
  },

  /**
   * Broadcasts a message to all ports.
   * @param  {String} topic
   * @param  {Mixed}  data
   */
  broadcastEvent: function(topic, data) {
    for (var id in this.ports)
      this.ports[id].postEvent(topic, data);
  },

  /**
   * Broadcasts an error message to all ports.
   * @param  {String} message
   */
  broadcastError: function(message) {
    for (var id in this.ports)
      this.ports[id].error(message);
  }
};

ports = new PortCollection();

function onconnect(event) {
  ports.add(new Port(event.ports[0]));
}

loadconfig(function(err, config) {
  if (err)
    return ports.broadcastError(err);
  _config = config;
  _currentUserData = new UserData({}, config);
});
<commit_msg>Fix tests<commit_after>/* jshint unused:false */

var _config = {DEBUG: false};
var _currentUserData;
var _presenceSocket;
var ports;
var browserPort;
var currentCall;
var currentUsers;

function openChatWindow() {
  browserPort.postEvent('social.request-chat', 'chat.html');
}

/**
 * Social API user profile data storage.
 * @param {Object|undefined}  initial  Initial data
 * @param {Object|undefined}  config   Environment configuration
 */
function UserData(initial, config) {
  var rootURL = config ? config.ROOTURL : '';

  this.defaults = {
    iconURL: rootURL + "/talkilla16.png",
    portrait: undefined,
    userName: undefined,
    displayName: undefined,
    profileURL: rootURL + "/user.html"
  };

  this.reset();

  if (initial) {
    for (var key in initial)
      this[key] = initial[key];
  }
}

UserData.prototype = {
  /**
   * Resets current properties to default ones.
   */
  reset: function() {
    for (var key in this.defaults)
      this[key] = this.defaults[key];
  }
};

var serverHandlers = {
  'users': function(data) {
    currentUsers = data;
    ports.broadcastEvent("talkilla.users", data);
  },

  'incoming_call': function(data) {
    currentCall = {port: undefined, data: data};
    openChatWindow();
  },

  'call_accepted': function(data) {
    currentCall.port.postEvent('talkilla.call-establishment', data);
  },

  'call_hangup': function(data) {
    currentCall.port.postEvent('talkilla.call-hangup', data);
    currentCall = undefined;
  }
};

function _presenceSocketOnMessage(event) {
  var data = JSON.parse(event.data);
  for (var eventType in data)
    if (eventType in serverHandlers)
      serverHandlers[eventType](data[eventType]);
    else
      ports.broadcastEvent("talkilla." + eventType, data[eventType]);
}

function _presenceSocketSendMessage(data) {
  _presenceSocket.send(data);
}

function _presenceSocketOnOpen(event) {
  "use strict";

  ports.broadcastEvent("talkilla.presence-open", event);
}

function _presenceSocketOnError(event) {
  "use strict";

  ports.broadcastEvent("talkilla.websocket-error", event);
}

function _presenceSocketOnClose(event) {
  "use strict";

  // XXX: this will need future work to handle retrying presence connections
  ports.broadcastEvent('talkilla.presence-unavailable', event.code);
  currentUsers = undefined;
}

function createPresenceSocket(nickname) {
  "use strict";

  _presenceSocket = new WebSocket(_config.WSURL + "?nick=" + nickname);
  _presenceSocket.onopen = _presenceSocketOnOpen;
  _presenceSocket.onmessage = _presenceSocketOnMessage;
  _presenceSocket.onerror = _presenceSocketOnError;
  _presenceSocket.onclose = _presenceSocketOnClose;

  ports.broadcastEvent("talkilla.presence-pending", {});
}

function _loginExpired() {
  _presenceSocket.removeEventListener("error", _loginExpired);
  ports.broadcastEvent("talkilla.logout-success", {});
}

function _presenceSocketReAttached(username, event) {
  _presenceSocket.removeEventListener("open", _presenceSocketReAttached);
  setupWebSocket(_presenceSocket);
  _setUserProfile(username);
  _presenceSocketOnOpen(event);
  ports.broadcastEvent("talkilla.login-success", {username: username});
}

function setupWebSocket(ws) {
  ws.onopen = _presenceSocketOnOpen;
  ws.onmessage = _presenceSocketOnMessage;
  ws.onerror = _presenceSocketOnError;
  ws.onclose = _presenceSocketOnClose;
}

function tryPresenceSocket(nickname) {
  "use strict";

  _presenceSocket = new WebSocket(_config.WSURL + "?nick=" + nickname);
  _presenceSocket.addEventListener("open", _presenceSocketReAttached.bind(this, nickname));
  _presenceSocket.addEventListener("error", _loginExpired);
  ports.broadcastEvent("talkilla.presence-pending", {});
}

function sendAjax(url, method, data, cb) {
  var xhr = new XMLHttpRequest();

  xhr.onload = function(event) {
    // sinon.js can call us with a null event a second time, so just ignore it.
    if (!event)
      return;
    if (xhr.readyState === 4 && xhr.status === 200)
      return cb(null, xhr.responseText);
    cb(xhr.statusText);
  };

  xhr.onerror = function(event) {
    if (event && event.target)
      cb(event.target.status ? event.target.statusText : "We are offline");
  };

  xhr.open(method || 'GET', url, true);
  xhr.setRequestHeader("Content-Type", "application/json");
  xhr.send(JSON.stringify(data));
}

function loadconfig(cb) {
  sendAjax('/config.json', 'GET', {}, function(err, data) {
    var config;
    try {
      config = JSON.parse(data);
    } catch (err) {
      return cb(err);
    }
    cb(null, config);
  });
}

function _setUserProfile(username) {
  _currentUserData.userName = _currentUserData.displayName = username;
  _currentUserData.portrait = "test.png";
  browserPort.postEvent('social.user-profile', _currentUserData);
}

function _signinCallback(err, responseText) {
  if (err)
    return this.postEvent('talkilla.login-failure', err);
  var username = JSON.parse(responseText).nick;
  if (username) {
    _setUserProfile(username);

    ports.broadcastEvent('talkilla.login-success', {
      username: username
    });

    createPresenceSocket(username);
  }
}

function _signoutCallback(err, responseText) {
  if (err)
    return this.postEvent('talkilla.error', 'Bad signout:' + err);

  _currentUserData.reset();
  browserPort.postEvent('social.user-profile', _currentUserData);
  currentUsers = undefined;
  ports.broadcastEvent('talkilla.logout-success');
}

var handlers = {
  // SocialAPI events
  'social.port-closing': function() {
    ports.remove(this);
  },

  'social.initialize': function() {
    browserPort = this;
  },

  // Talkilla events
  'talkilla.login': function(msg) {
    if (!msg.data || !msg.data.username) {
      return this.postEvent('talkilla.login-failure', 'no username specified');
    }

    this.postEvent('talkilla.login-pending', null);

    sendAjax('/signin', 'POST', {nick: msg.data.username},
      _signinCallback.bind(this));
  },

  'talkilla.logout': function() {
    if (!_currentUserData.userName) {
      return this.postEvent('talkilla.error',
                            'trying to logout when not logged in');
    }

    _presenceSocket.close();
    sendAjax('/signout', 'POST', {nick: _currentUserData.userName},
      _signoutCallback.bind(this));
  },

  'talkilla.call-start': function(event) {
    // XXX Temporarily work around to only allow one call at a time.
    if (!currentCall) {
      currentCall = {port: undefined, data: event.data};
      openChatWindow();
    }
  },

  'talkilla.chat-window-ready': function() {
    currentCall.port = this;

    if (_currentUserData.userName) {
      // If there's currenty a logged in user,
      this.postEvent('talkilla.login-success', {
        username: _currentUserData.userName
      });
    }

   // If this is an incoming call, we won't have the port yet.
    var topic = currentCall.data.offer ?
      "talkilla.call-incoming" :
      "talkilla.call-start";

    this.postEvent(topic, currentCall.data);
  },

  'talkilla.sidebar-ready': function(event) {
    if (_currentUserData.userName) {
      // If there's currently a logged in user,
      this.postEvent('talkilla.login-success', {
        username: _currentUserData.userName
      });
      if (currentUsers)
        this.postEvent('talkilla.users', currentUsers);
    } else if (event.data.nick) {
      // No user data available, may still be logged in
      tryPresenceSocket(event.data.nick);
    }
  },

  /**
   * The data for talkilla.call-offer is:
   *
   * - callee: the person you are calling
   * - caller: the person who is calling you
   * - offer: an RTCSessionDescription containing the sdp data for the call.
   */
  'talkilla.call-offer': function(event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_offer': event.data }));
  },

  /**
   * The data for talkilla.call-answer is:
   *
   * - callee: the person you are calling
   * - caller: the person who is calling you
   * - offer: an RTCSessionDescription containing the sdp data for the call.
   */
  'talkilla.call-answer': function (event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_accepted': event.data }));
  },

  /**
   * Ends a call. The expected data is:
   *
   * - other: the person you are talking to.
   */
  'talkilla.call-hangup': function (event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_hangup': event.data }));
    currentCall = undefined;
  },

  /**
   * . The expected data is:
   *
   * - other: the person you are talking to.
   */
  'talkilla.call-hangup': function (event) {
    _presenceSocketSendMessage(JSON.stringify({ 'call_hangup': event.data }));
    currentCall = undefined;
  }
};

function Port(port) {
  this.port = port;
  this.id = port._portid;
  // configures this port
  port.onmessage = this.onmessage.bind(this);
}

Port.prototype = {
  /**
   * Posts an error event.
   * @param  {String} error
   */
  error: function(error) {
    this.postEvent("talkilla.error", error);
  },

  /**
   * Port message listener.
   * @param  {Event} event
   */
  onmessage: function(event) {
    var msg = event.data;
    if (msg && msg.topic && (msg.topic in handlers))
      handlers[msg.topic].call(this, msg);
    else
      this.error('Topic is missing or unknown');
  },

  /**
   * Posts a message event.
   * @param  {String} topic
   * @param  {Mixed}  data
   */
  postEvent: function(topic, data) {
    this.port.postMessage({topic: topic, data: data});
  }
};

function PortCollection() {
  this.ports = {};
}

PortCollection.prototype = {
  /**
   * Configures and add a port to the stack.
   * @param  {Port} port
   */
  add: function(port) {
    if (port.id in this.ports)
      return;
    this.ports[port.id] = port;
  },

  /**
   * Removes a port from this collection.
   * @param  {Port} port
   */
  remove: function(port) {
    if (port && port.id)
      delete this.ports[port.id];
  },

  /**
   * Retrieves a port from the collection by its id.
   * @param  {String} id
   * @return {Port}
   */
  find: function(id) {
    return this.ports[id];
  },

  /**
   * Broadcasts a message to all ports.
   * @param  {String} topic
   * @param  {Mixed}  data
   */
  broadcastEvent: function(topic, data) {
    for (var id in this.ports)
      this.ports[id].postEvent(topic, data);
  },

  /**
   * Broadcasts an error message to all ports.
   * @param  {String} message
   */
  broadcastError: function(message) {
    for (var id in this.ports)
      this.ports[id].error(message);
  }
};

ports = new PortCollection();

function onconnect(event) {
  ports.add(new Port(event.ports[0]));
}

loadconfig(function(err, config) {
  if (err)
    return ports.broadcastError(err);
  _config = config;
  _currentUserData = new UserData({}, config);
});
<|endoftext|>


<commit_before>function boxlog ( message ) {
	el = $( "#log-area" );
	el.text( message + "\n" + el.text() );
}

// Namespace
var LC = {

	/////// OBJECTS ///////
	player: function ( id, offset, sprite, orientation ) {
		this.id = id;
		this.offset = offset;
		this.sprite = sprite;
		this.orientation = orientation;

		this.draw = function () {
			var x_offset = this.offset[0] - LC.map_offset[0],
			    y_offset = this.offset[1] - LC.map_offset[1];

			if(
				x_offset < 0 ||
				x_offset > LC.VIEWPORT_WIDTH - LC.TILE_WIDTH ||
				y_offset < 0 ||
				y_offset > LC.VIEWPORT_HEIGHT - LC.TILE_HEIGHT
			) {
				boxlog( "Skip Draw: " + this.id );
				return;
			}
			else {
				boxlog( "Draw: " + this.id );
				LC.drawSprite(
					this.sprite + '_' + this.orientation,
					x_offset,
					y_offset
				);
			}
		};

		this.clear = function () {
			var x_offset = this.offset[0] - LC.map_offset[0],
			    y_offset = this.offset[1] - LC.map_offset[1];

			if(
				x_offset < 0 ||
				x_offset > LC.VIEWPORT_WIDTH - LC.TILE_WIDTH ||
				y_offset < 0 ||
				y_offset > LC.VIEWPORT_HEIGHT - LC.TILE_HEIGHT
			) {
				boxlog( "Skip Clear: " + this.id );
				return;
			}
			else {
				boxlog( "Clear: " + this.id );
				LC.clearSprite(
					this.sprite + '_' + this.orientation,
					x_offset,
					y_offset
				);
			}
		};
	},

	/////// CONSTANTS ///////
	// Size of a tile
	TILE_WIDTH: 40,
	TILE_HEIGHT: 40,
	// Total map size
	MAP_WIDTH: 1000,
	MAP_HEIGHT: 1000,
	// Size of the visible area
	VIEWPORT_WIDTH: 500,
	VIEWPORT_HEIGHT: 500,
	// How close you can get to the edge of the viewport before the map moves
	MOVE_BUFFER_HIGH: 400,
	MOVE_BUFFER_LOW: 100,
	// A map of where to find different tiles in the sprite image
	sprite_map: {
		// name_orientation :  [ x, y,  w,  h ]
		'cat_west' :  [ 0, 120, 40, 40 ],
		'cat_south':  [ 0, 0, 40, 40 ],
		'cat_east' :  [ 0, 80, 40, 40 ],
		'cat_north':  [ 0, 40, 40, 40 ],
	},

	/////// ELEMENTS ///////
	// Canvas contenxt
	ctx: null,
	// Map element (background)
	map: null,
	// Sprites origin
	sprites: null,
	// Faye client (communications)
	faye: null,

	/////// STATE ///////
	// Offset from 0,0 the viewable map is (pixels, not tiles)
	map_offset: [ 0, 0 ],
	// Stored data on the player
	user: null,
	// An array of objects currently on the map
	objects: [],

	/////// CORE ///////
	// Set up
	init: function () {
		LC.ctx = document.getElementById( "objects" ).getContext( "2d" );
		LC.map = $( "#map" );
		LC.sprites = document.getElementById( "sprites" );
		$( 'html' ).live( 'keyup', LC.keyUp );

		$.getJSON( '/init.json', function ( config ) {
			LC.user = new LC.player( config.you.uniqueID, config.you.offset, 'cat', 'south' );
			LC.faye = new Faye.Client( "http://" + window.location.hostname + ':' + config.you.port + '/faye', { timeout: 120 } );

			window.onbeforeunload = LC.quit;

			for( var idx in config.them ) {
				if( idx != LC.user.id ) {
					LC.objects[idx] = new LC.player( idx, config.them[idx].offset, 'cat', 'south' );
				}
			}

			LC.faye.subscribe( '/join', function ( message ) {
				if( message.uniqueID == LC.user.id ) {
					boxlog( "I JOINED!" );
					return;
				}
				boxlog( "SOMEBODY JOINED!" );
				LC.objects[message.uniqueID] = new LC.player( message.uniqueID, message.offset, 'cat', 'south' );
				LC.objects[message.uniqueID].draw();
			} );

			LC.faye.subscribe( '/move', function ( message ) {
				if( message.uniqueID == LC.user.id ) {
					boxlog( "I MOVED!" );
				}
				else {
					boxlog( "SOMEBODY MOVED! " + message.uniqueID );
					LC.objects[message.uniqueID].clear();
					LC.objects[message.uniqueID].offset = message.offset;
					LC.objects[message.uniqueID].draw();
				}
			} );

			LC.faye.subscribe( '/quit', function ( message ) {
				boxlog( "QUITTER! " + message.uniqueID );
				LC.objects[message.uniqueID].clear();
				delete LC.objects[message.uniqueID];
			} );

			LC.faye.subscribe( '/sync', function ( message ) {
				boxlog( "SYNC!" );
				LC.faye.unsubscribe( '/sync' );
			} );

			LC.spawn();
		} );

	},

	quit: function () {
		$.getJSON( '/quit.json', { uniqueID: LC.user.id } );
		alert( 'Thanks For Playing!' );
	},

	// Clear the space a sprite is currently taking up.
	clearSprite: function ( sprite, x, y ) {
		LC.ctx.clearRect( x, y, LC.TILE_WIDTH, LC.TILE_HEIGHT );
	},

	// Draw a new sprite on the screen. Doesn't overlay, clears.
	drawSprite: function ( sprite, x, y ) {
		LC.ctx.clearRect( x, y, LC.TILE_WIDTH, LC.TILE_HEIGHT );
		LC.ctx.drawImage(
			LC.sprites,
			LC.sprite_map[sprite][0],
			LC.sprite_map[sprite][1],
			LC.sprite_map[sprite][2],
			LC.sprite_map[sprite][3],
			x,
			y,
			LC.sprite_map[sprite][2],
			LC.sprite_map[sprite][3]
		);
	},

	// Shift the map in behind the user
	moveMap: function ( x, y ) {
		LC.map_offset[0] = LC.map_offset[0] + x;
		LC.map_offset[1] = LC.map_offset[1] + y;

		if( LC.map_offset[0] < 0 ) { LC.map_offset[0] = 0; }
		if( LC.map_offset[1] < 0 ) { LC.map_offset[1] = 0; }
		if( LC.map_offset[0] >= LC.VIEWPORT_WIDTH ) { LC.map_offset[0] = LC.VIEWPORT_WIDTH; }
		if( LC.map_offset[1] >= LC.VIEWPORT_HEIGHT ) { LC.map_offset[1] = LC.VIEWPORT_HEIGHT; }

		boxlog( 'Move Map: -' + LC.map_offset[0] + 'px -' + LC.map_offset[1] + 'px' )

		LC.map.css(
			'background-position',
			'-' + LC.map_offset[0] + 'px -' + LC.map_offset[1] + 'px'
		);
	},

	// Capture key events and trigger actions based on them
	keyUp: function ( e ) {
		switch ( e.which ) {
			case 37:
				LC.moveUser( 'w' );
				break;
			case 38:
				LC.moveUser( 'n' );
				break;
			case 39:
				LC.moveUser( 'e' );
				break;
			case 40:
				LC.moveUser( 's' );
				break;
		}
	},

	/////// GAMEPLAY ///////
	// Spawn the user at the given point
	spawn: function () {
		boxlog( "Spawn: " + LC.user.offset[0] + ", " + LC.user.offset[1] );

		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].clear(); }
		}

		LC.moveMap( -1 * LC.map_offset[0], -1 * LC.map_offset[1] ); // Back to 0,0
		LC.moveMap( LC.user.offset[0] - 260, LC.user.offset[1] - 260 ); // Move map out to player

		LC.user.draw();

		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].draw(); }
		}

		edge_proximity = [
			( LC.map_offset[0] + LC.VIEWPORT_WIDTH - LC.user.offset[0] ),
			( LC.map_offset[1] + LC.VIEWPORT_HEIGHT - LC.user.offset[1] )
		]
		$( '#edge-proximity' ).val( edge_proximity[0] + ', ' + edge_proximity[1] );
		$( '#map-offset' ).val( LC.map_offset[0] + ', ' + LC.map_offset[1] );
		$( '#user-offset' ).val( LC.user.offset[0] + ', ' + LC.user.offset[1] );
	},

	// Move the user one tile in a direction (n,s,e,w)
	moveUser: function ( direction ) {
		var new_offset = $.extend( {}, LC.user.offset ); // Shallow copy
		switch( direction ) {
			case 'w':
				new_offset[0] = LC.user.offset[0] - LC.TILE_HEIGHT;
				new_orientation = 'east';
				break;
			case 'e':
				new_offset[0] = LC.user.offset[0] + LC.TILE_HEIGHT;
				new_orientation = 'west';
				break;
			case 'n':
				new_offset[1] = LC.user.offset[1] - LC.TILE_WIDTH;
				new_orientation = 'north';
				break;
			case 's':
				new_offset[1] = LC.user.offset[1] + LC.TILE_WIDTH;
				new_orientation = 'south';
				break;
		}

		// No leaving the map!
		if( new_offset[0] >= LC.MAP_WIDTH || new_offset[1] >= LC.MAP_HEIGHT || new_offset[0] < 0 || new_offset[1] < 0 )
			return;

		LC.user.clear();
		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].clear(); }
		}

		LC.user.offset = new_offset;
		LC.user.orientation = new_orientation;

		edge_proximity = [
			( LC.map_offset[0] + LC.VIEWPORT_WIDTH - LC.user.offset[0] ),
			( LC.map_offset[1] + LC.VIEWPORT_HEIGHT - LC.user.offset[1] )
		]

		if( 'e' == direction && edge_proximity[0] <= LC.MOVE_BUFFER_LOW ) { LC.moveMap( LC.TILE_WIDTH, 0 ); }
		if( 'w' == direction && edge_proximity[0] >= LC.MOVE_BUFFER_HIGH ) { LC.moveMap( -1 * LC.TILE_WIDTH, 0 ); }
		if( 'n' == direction && edge_proximity[1] >= LC.MOVE_BUFFER_HIGH ) { LC.moveMap( 0, -1 * LC.TILE_HEIGHT ); }
		if( 's' == direction && edge_proximity[1] <= LC.MOVE_BUFFER_LOW ) { LC.moveMap( 0, LC.TILE_HEIGHT ); }

		LC.user.draw();
		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].draw(); }
		}

		LC.faye.publish( '/move', { offset: LC.user.offset, uniqueID: LC.user.id } );

		$( '#edge-proximity' ).val( edge_proximity[0] + ', ' + edge_proximity[1] );
		$( '#map-offset' ).val( LC.map_offset[0] + ', ' + LC.map_offset[1] );
		$( '#user-offset' ).val( LC.user.offset[0] + ', ' + LC.user.offset[1] );

	}

}
<commit_msg>Publish orientation information on updates.<commit_after>function boxlog ( message ) {
	el = $( "#log-area" );
	el.text( message + "\n" + el.text() );
}

// Namespace
var LC = {

	/////// OBJECTS ///////
	player: function ( id, offset, sprite, orientation ) {
		this.id = id;
		this.offset = offset;
		this.sprite = sprite;
		this.orientation = orientation;

		this.draw = function () {
			var x_offset = this.offset[0] - LC.map_offset[0],
			    y_offset = this.offset[1] - LC.map_offset[1];

			if(
				x_offset < 0 ||
				x_offset > LC.VIEWPORT_WIDTH - LC.TILE_WIDTH ||
				y_offset < 0 ||
				y_offset > LC.VIEWPORT_HEIGHT - LC.TILE_HEIGHT
			) {
				boxlog( "Skip Draw: " + this.id );
				return;
			}
			else {
				boxlog( "Draw: " + this.id );
				LC.drawSprite(
					this.sprite + '_' + this.orientation,
					x_offset,
					y_offset
				);
			}
		};

		this.clear = function () {
			var x_offset = this.offset[0] - LC.map_offset[0],
			    y_offset = this.offset[1] - LC.map_offset[1];

			if(
				x_offset < 0 ||
				x_offset > LC.VIEWPORT_WIDTH - LC.TILE_WIDTH ||
				y_offset < 0 ||
				y_offset > LC.VIEWPORT_HEIGHT - LC.TILE_HEIGHT
			) {
				boxlog( "Skip Clear: " + this.id );
				return;
			}
			else {
				boxlog( "Clear: " + this.id );
				LC.clearSprite(
					this.sprite + '_' + this.orientation,
					x_offset,
					y_offset
				);
			}
		};
	},

	/////// CONSTANTS ///////
	// Size of a tile
	TILE_WIDTH: 40,
	TILE_HEIGHT: 40,
	// Total map size
	MAP_WIDTH: 1000,
	MAP_HEIGHT: 1000,
	// Size of the visible area
	VIEWPORT_WIDTH: 500,
	VIEWPORT_HEIGHT: 500,
	// How close you can get to the edge of the viewport before the map moves
	MOVE_BUFFER_HIGH: 400,
	MOVE_BUFFER_LOW: 100,
	// A map of where to find different tiles in the sprite image
	sprite_map: {
		// name_orientation :  [ x, y,  w,  h ]
		'cat_west' :  [ 0, 120, 40, 40 ],
		'cat_south':  [ 0, 0, 40, 40 ],
		'cat_east' :  [ 0, 80, 40, 40 ],
		'cat_north':  [ 0, 40, 40, 40 ],
	},

	/////// ELEMENTS ///////
	// Canvas contenxt
	ctx: null,
	// Map element (background)
	map: null,
	// Sprites origin
	sprites: null,
	// Faye client (communications)
	faye: null,

	/////// STATE ///////
	// Offset from 0,0 the viewable map is (pixels, not tiles)
	map_offset: [ 0, 0 ],
	// Stored data on the player
	user: null,
	// An array of objects currently on the map
	objects: [],

	/////// CORE ///////
	// Set up
	init: function () {
		LC.ctx = document.getElementById( "objects" ).getContext( "2d" );
		LC.map = $( "#map" );
		LC.sprites = document.getElementById( "sprites" );
		$( 'html' ).live( 'keyup', LC.keyUp );

		$.getJSON( '/init.json', function ( config ) {
			LC.user = new LC.player( config.you.uniqueID, config.you.offset, 'cat', 'south' );
			LC.faye = new Faye.Client( "http://" + window.location.hostname + ':' + config.you.port + '/faye', { timeout: 120 } );

			window.onbeforeunload = LC.quit;

			for( var idx in config.them ) {
				if( idx != LC.user.id ) {
					LC.objects[idx] = new LC.player( idx, config.them[idx].offset, 'cat', 'south' );
				}
			}

			LC.faye.subscribe( '/join', function ( message ) {
				if( message.uniqueID == LC.user.id ) {
					boxlog( "I JOINED!" );
					return;
				}
				boxlog( "SOMEBODY JOINED!" );
				LC.objects[message.uniqueID] = new LC.player( message.uniqueID, message.offset, 'cat', 'south' );
				LC.objects[message.uniqueID].draw();
			} );

			LC.faye.subscribe( '/move', function ( message ) {
				if( message.uniqueID != LC.user.id ) {
					boxlog( "SOMEBODY MOVED! " + message.uniqueID );
					LC.objects[message.uniqueID].clear();
					LC.objects[message.uniqueID].offset = message.offset;
					LC.objects[message.uniqueID].orientation = message.orientation;
					LC.objects[message.uniqueID].draw();
				}
			} );

			LC.faye.subscribe( '/quit', function ( message ) {
				boxlog( "QUITTER! " + message.uniqueID );
				LC.objects[message.uniqueID].clear();
				delete LC.objects[message.uniqueID];
			} );

			LC.faye.subscribe( '/sync', function ( message ) {
				boxlog( "SYNC!" );
				LC.faye.unsubscribe( '/sync' );
			} );

			LC.spawn();
		} );

	},

	quit: function () {
		$.getJSON( '/quit.json', { uniqueID: LC.user.id } );
		alert( 'Thanks For Playing!' );
	},

	// Clear the space a sprite is currently taking up.
	clearSprite: function ( sprite, x, y ) {
		LC.ctx.clearRect( x, y, LC.TILE_WIDTH, LC.TILE_HEIGHT );
	},

	// Draw a new sprite on the screen. Doesn't overlay, clears.
	drawSprite: function ( sprite, x, y ) {
		LC.ctx.clearRect( x, y, LC.TILE_WIDTH, LC.TILE_HEIGHT );
		LC.ctx.drawImage(
			LC.sprites,
			LC.sprite_map[sprite][0],
			LC.sprite_map[sprite][1],
			LC.sprite_map[sprite][2],
			LC.sprite_map[sprite][3],
			x,
			y,
			LC.sprite_map[sprite][2],
			LC.sprite_map[sprite][3]
		);
	},

	// Shift the map in behind the user
	moveMap: function ( x, y ) {
		LC.map_offset[0] = LC.map_offset[0] + x;
		LC.map_offset[1] = LC.map_offset[1] + y;

		if( LC.map_offset[0] < 0 ) { LC.map_offset[0] = 0; }
		if( LC.map_offset[1] < 0 ) { LC.map_offset[1] = 0; }
		if( LC.map_offset[0] >= LC.VIEWPORT_WIDTH ) { LC.map_offset[0] = LC.VIEWPORT_WIDTH; }
		if( LC.map_offset[1] >= LC.VIEWPORT_HEIGHT ) { LC.map_offset[1] = LC.VIEWPORT_HEIGHT; }

		boxlog( 'Move Map: -' + LC.map_offset[0] + 'px -' + LC.map_offset[1] + 'px' )

		LC.map.css(
			'background-position',
			'-' + LC.map_offset[0] + 'px -' + LC.map_offset[1] + 'px'
		);
	},

	// Capture key events and trigger actions based on them
	keyUp: function ( e ) {
		switch ( e.which ) {
			case 37:
				LC.moveUser( 'w' );
				break;
			case 38:
				LC.moveUser( 'n' );
				break;
			case 39:
				LC.moveUser( 'e' );
				break;
			case 40:
				LC.moveUser( 's' );
				break;
		}
	},

	/////// GAMEPLAY ///////
	// Spawn the user at the given point
	spawn: function () {
		boxlog( "Spawn: " + LC.user.offset[0] + ", " + LC.user.offset[1] );

		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].clear(); }
		}

		LC.moveMap( -1 * LC.map_offset[0], -1 * LC.map_offset[1] ); // Back to 0,0
		LC.moveMap( LC.user.offset[0] - 260, LC.user.offset[1] - 260 ); // Move map out to player

		LC.user.draw();

		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].draw(); }
		}

		edge_proximity = [
			( LC.map_offset[0] + LC.VIEWPORT_WIDTH - LC.user.offset[0] ),
			( LC.map_offset[1] + LC.VIEWPORT_HEIGHT - LC.user.offset[1] )
		]
		$( '#edge-proximity' ).val( edge_proximity[0] + ', ' + edge_proximity[1] );
		$( '#map-offset' ).val( LC.map_offset[0] + ', ' + LC.map_offset[1] );
		$( '#user-offset' ).val( LC.user.offset[0] + ', ' + LC.user.offset[1] );
	},

	// Move the user one tile in a direction (n,s,e,w)
	moveUser: function ( direction ) {
		var new_offset = $.extend( {}, LC.user.offset ); // Shallow copy
		switch( direction ) {
			case 'w':
				new_offset[0] = LC.user.offset[0] - LC.TILE_HEIGHT;
				new_orientation = 'east';
				break;
			case 'e':
				new_offset[0] = LC.user.offset[0] + LC.TILE_HEIGHT;
				new_orientation = 'west';
				break;
			case 'n':
				new_offset[1] = LC.user.offset[1] - LC.TILE_WIDTH;
				new_orientation = 'north';
				break;
			case 's':
				new_offset[1] = LC.user.offset[1] + LC.TILE_WIDTH;
				new_orientation = 'south';
				break;
		}

		// No leaving the map!
		if( new_offset[0] >= LC.MAP_WIDTH || new_offset[1] >= LC.MAP_HEIGHT || new_offset[0] < 0 || new_offset[1] < 0 )
			return;

		LC.user.clear();
		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].clear(); }
		}

		LC.user.offset = new_offset;
		LC.user.orientation = new_orientation;

		edge_proximity = [
			( LC.map_offset[0] + LC.VIEWPORT_WIDTH - LC.user.offset[0] ),
			( LC.map_offset[1] + LC.VIEWPORT_HEIGHT - LC.user.offset[1] )
		]

		if( 'e' == direction && edge_proximity[0] <= LC.MOVE_BUFFER_LOW ) { LC.moveMap( LC.TILE_WIDTH, 0 ); }
		if( 'w' == direction && edge_proximity[0] >= LC.MOVE_BUFFER_HIGH ) { LC.moveMap( -1 * LC.TILE_WIDTH, 0 ); }
		if( 'n' == direction && edge_proximity[1] >= LC.MOVE_BUFFER_HIGH ) { LC.moveMap( 0, -1 * LC.TILE_HEIGHT ); }
		if( 's' == direction && edge_proximity[1] <= LC.MOVE_BUFFER_LOW ) { LC.moveMap( 0, LC.TILE_HEIGHT ); }

		LC.user.draw();
		for( var obj in LC.objects ) {
			if( obj != LC.user.id ) { LC.objects[obj].draw(); }
		}

		LC.faye.publish( '/move', { offset: LC.user.offset, uniqueID: LC.user.id, orientation: LC.user.orientation } );

		$( '#edge-proximity' ).val( edge_proximity[0] + ', ' + edge_proximity[1] );
		$( '#map-offset' ).val( LC.map_offset[0] + ', ' + LC.map_offset[1] );
		$( '#user-offset' ).val( LC.user.offset[0] + ', ' + LC.user.offset[1] );

	}

}
<|endoftext|>


<commit_before>var Telegram = require('node-telegram-bot-api');
var fs = require('fs');
var irc = require('./irc');

// tries to read chat ids from a file
var readChatIds = function(arr) {
    console.log('\n');
    console.log('NOTE!');
    console.log('=====');

    var idMissing = false;
    try {
        var json = JSON.parse(fs.readFileSync(process.env.HOME + '/.teleirc/chat_ids'));
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i].tgGroup;
            if (key in json) {
                arr[i].tgChatId = json[key];
                console.log('id found for:', key, ':', json[key]);
            } else {
                console.log('id not found:', key);
                idMissing = true;
            }
        }
    } catch (e) {
        console.log('~/.teleirc/chat_ids file not found!');
        idMissing = true;
    }

    if (idMissing) {
        console.log(
            '\nPlease add your Telegram bot to a Telegram group and have' +
            '\nsomeone send a message to that group.' +
            '\nteleirc will then automatically store your group chat_id.');
    }

    console.log('\n');
};

var writeChatIds = function(config) {
    var json = {};
    for (var i = 0; i < config.channels.length; i++) {
        if (config.channels[i].tgChatId) {
            json[config.channels[i].tgGroup] = config.channels[i].tgChatId;
        }
    }
    json = JSON.stringify(json);
    fs.writeFile(process.env.HOME + '/.teleirc/chat_ids', json, function(err) {
        if (err) {
            console.log('error while storing chat ID:');
            console.log(err);
        } else {
            console.log('successfully stored chat ID in ~/.teleirc/chat_ids');
        }
    });
};

module.exports = function(config, sendTo) {
    var tg = new Telegram(config.tgToken,{polling: true});

    readChatIds(config.channels);

    tg.on('message', function(msg) {
        var channel = config.channels.filter(function(channel) {
            return channel.tgGroup === msg.chat.title;
        })[0];

        if (!channel) {
            return;
        }

        if (!channel.tgChatId) {
            console.log('storing chat ID: ' + msg.chat.id);
            channel.tgChatId = msg.chat.id;
            writeChatIds(config);
        }

        var user = msg.from.first_name ? msg.from.first_name : '' +
                   msg.from.last_name ? msg.from.last_name : '';

        // skip posts containing media if it's configured off
        if ((msg.audio || msg.document || msg.photo || msg.sticker || msg.video ||
            msg.voice || msg.contact || msg.location) && !config.showMedia) {
            return;
        }

        var text;

        if (msg.reply_to_message && msg.text) {
            text = '@' + msg.reply_to_message.from.username + ', ' + msg.text;
        } else if (msg.audio) {
            text = '(Audio)';
        } else if (msg.document) {
            text = '(Document)';
        } else if (msg.photo) {
            text = '(Image, ' + msg.photo.slice(-1)[0].width + 'x' +
                                msg.photo.slice(-1)[0].height + ')';
        } else if (msg.sticker) {
            text = '(Sticker)';
        } else if (msg.video) {
            text = '(Video, ' + msg.video.duration + 's)';
        } else if (msg.voice) {
            text = '(Voice, ' + msg.audio.duration + 's)';
        } else if (msg.contact) {
            text = '(Contact, ' + '"' + msg.contact.first_name + ' ' +
                                        msg.contact.last_name + '", ' +
                                        msg.contact.phone_number + ')';
        } else if (msg.location) {
            text = '(Location, lon: ' + msg.location.longitude +
                            ', lat: ' + msg.location.latitude + ')';
        } else if (msg.new_chat_participant) {
            text = '(Added: ' + msg.new_chat_participant.first_name + ')';
        } else if (msg.left_chat_participant) {
            text = '(Removed: ' + msg.left_chat_participant.first_name + ')';
        } else {
            text = msg.text;
        }

        sendTo.irc(channel.ircChan, '<' + user + '>: ' + text);
    });

    sendTo.tg = function(channel, msg) {
        console.log('  >> relaying to TG: ' + msg);

        if (!channel.tgChatId) {
            var err = 'ERROR: No chat_id set! Add me to a Telegram group ' +
                      'and say hi so I can find your group\'s chat_id!';
            sendTo.irc(channel.ircChan, err);
            console.error(err);
            return;
        }

        tg.sendMessage(channel.tgChatId, msg);
    };
};
<commit_msg>I and the @fczuardi altered the lines of the code about the show the user with send the messages on the telegram to show his username too.<commit_after>var Telegram = require('node-telegram-bot-api');
var fs = require('fs');
var irc = require('./irc');

// tries to read chat ids from a file
var readChatIds = function(arr) {
    console.log('\n');
    console.log('NOTE!');
    console.log('=====');

    var idMissing = false;
    try {
        var json = JSON.parse(fs.readFileSync(process.env.HOME + '/.teleirc/chat_ids'));
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i].tgGroup;
            if (key in json) {
                arr[i].tgChatId = json[key];
                console.log('id found for:', key, ':', json[key]);
            } else {
                console.log('id not found:', key);
                idMissing = true;
            }
        }
    } catch (e) {
        console.log('~/.teleirc/chat_ids file not found!');
        idMissing = true;
    }

    if (idMissing) {
        console.log(
            '\nPlease add your Telegram bot to a Telegram group and have' +
            '\nsomeone send a message to that group.' +
            '\nteleirc will then automatically store your group chat_id.');
    }

    console.log('\n');
};

var writeChatIds = function(config) {
    var json = {};
    for (var i = 0; i < config.channels.length; i++) {
        if (config.channels[i].tgChatId) {
            json[config.channels[i].tgGroup] = config.channels[i].tgChatId;
        }
    }
    json = JSON.stringify(json);
    fs.writeFile(process.env.HOME + '/.teleirc/chat_ids', json, function(err) {
        if (err) {
            console.log('error while storing chat ID:');
            console.log(err);
        } else {
            console.log('successfully stored chat ID in ~/.teleirc/chat_ids');
        }
    });
};

module.exports = function(config, sendTo) {
    var tg = new Telegram(config.tgToken,{polling: true});

    readChatIds(config.channels);

    tg.on('message', function(msg) {
        var channel = config.channels.filter(function(channel) {
            return channel.tgGroup === msg.chat.title;
        })[0];

        if (!channel) {
            return;
        }

        if (!channel.tgChatId) {
            console.log('storing chat ID: ' + msg.chat.id);
            channel.tgChatId = msg.chat.id;
            writeChatIds(config);
        }

        var user = msg.from.first_name ? msg.from.first_name + ' ' : '';
            user += msg.from.last_name ? msg.from.last_name : '';
            user += msg.from.username ? '(@' + msg.from.username + ')' : '';

        // skip posts containing media if it's configured off
        if ((msg.audio || msg.document || msg.photo || msg.sticker || msg.video ||
            msg.voice || msg.contact || msg.location) && !config.showMedia) {
            return;
        }

        var text;

        if (msg.reply_to_message && msg.text) {
            text = '@' + msg.reply_to_message.from.username + ', ' + msg.text;
        } else if (msg.audio) {
            text = '(Audio)';
        } else if (msg.document) {
            text = '(Document)';
        } else if (msg.photo) {
            text = '(Image, ' + msg.photo.slice(-1)[0].width + 'x' +
                                msg.photo.slice(-1)[0].height + ')';
        } else if (msg.sticker) {
            text = '(Sticker)';
        } else if (msg.video) {
            text = '(Video, ' + msg.video.duration + 's)';
        } else if (msg.voice) {
            text = '(Voice, ' + msg.audio.duration + 's)';
        } else if (msg.contact) {
            text = '(Contact, ' + '"' + msg.contact.first_name + ' ' +
                                        msg.contact.last_name + '", ' +
                                        msg.contact.phone_number + ')';
        } else if (msg.location) {
            text = '(Location, lon: ' + msg.location.longitude +
                            ', lat: ' + msg.location.latitude + ')';
        } else if (msg.new_chat_participant) {
            text = '(Added: ' + msg.new_chat_participant.first_name + ')';
        } else if (msg.left_chat_participant) {
            text = '(Removed: ' + msg.left_chat_participant.first_name + ')';
        } else {
            text = msg.text;
        }

        sendTo.irc(channel.ircChan, '<' + user + '>: ' + text);
    });

    sendTo.tg = function(channel, msg) {
        console.log('  >> relaying to TG: ' + msg);

        if (!channel.tgChatId) {
            var err = 'ERROR: No chat_id set! Add me to a Telegram group ' +
                      'and say hi so I can find your group\'s chat_id!';
            sendTo.irc(channel.ircChan, err);
            console.error(err);
            return;
        }

        tg.sendMessage(channel.tgChatId, msg);
    };
};
<|endoftext|>


<commit_before>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

(function() {
  "use strict";

  var runFunc;
  var count = 0;

  function getId() {
    return "code" + (count++);
  }

  function text(node) {
    var s = "";
    for (var i = 0; i < node.childNodes.length; i++) {
      var n = node.childNodes[i];
      if (n.nodeType === 1 && n.tagName === "SPAN" && n.className != "number") {
        var innerText = n.innerText === undefined ? "textContent" : "innerText";
        s += n[innerText] + "\n";
        continue;
      }
      if (n.nodeType === 1 && n.tagName !== "BUTTON") {
        s += text(n);
      }
    }
    return s;
  }

  function init(code) {
    var id = getId();

    var output = document.createElement('div');
    var outpre = document.createElement('pre');
    var stopFunc;

    $(output).resizable({
      handles: "n,w,nw",
      minHeight:  27,
      minWidth:  135,
      maxHeight: 608,
      maxWidth:  990
    });

    function onKill() {
      if (stopFunc) {
        stopFunc();
      }
    }

    function onRun(e) {
      onKill();
      outpre.innerHTML = "";
      output.style.display = "block";
      run.style.display = "none";
      var options = {Race: e.shiftKey};
      stopFunc = runFunc(text(code), outpre, options);
    }

    function onClose() {
      onKill();
      output.style.display = "none";
      run.style.display = "inline-block";
    }

    var run = document.createElement('button');
    run.innerHTML = 'Run';
    run.className = 'run';
    run.addEventListener("click", onRun, false);
    var run2 = document.createElement('button');
    run2.className = 'run';
    run2.innerHTML = 'Run';
    run2.addEventListener("click", onRun, false);
    var kill = document.createElement('button');
    kill.className = 'kill';
    kill.innerHTML = 'Kill';
    kill.addEventListener("click", onKill, false);
    var close = document.createElement('button');
    close.className = 'close';
    close.innerHTML = 'Close';
    close.addEventListener("click", onClose, false);

    var button = document.createElement('div');
    button.classList.add('buttons');
    button.appendChild(run);
    // Hack to simulate insertAfter
    code.parentNode.insertBefore(button, code.nextSibling);

    var buttons = document.createElement('div');
    buttons.classList.add('buttons');
    buttons.appendChild(run2);
    buttons.appendChild(kill);
    buttons.appendChild(close);

    output.classList.add('output');
    output.appendChild(buttons);
    output.appendChild(outpre);
    output.style.display = "none";
    code.parentNode.insertBefore(output, button.nextSibling);
  }

  var play = document.querySelectorAll('div.playground');
  for (var i = 0; i < play.length; i++) {
    init(play[i]);
  }
  if (play.length > 0) {
    if (window.connectPlayground) {
      runFunc = window.connectPlayground("ws://" + window.location.host + "/socket");
    } else {
      // If this message is logged,
      // we have neglected to include socket.js or playground.js.
      console.log("No playground transport available.");
    }
  }
})();
<commit_msg>go.blog: remove resize code from blog javascript<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

(function() {
  "use strict";

  var runFunc;
  var count = 0;

  function getId() {
    return "code" + (count++);
  }

  function text(node) {
    var s = "";
    for (var i = 0; i < node.childNodes.length; i++) {
      var n = node.childNodes[i];
      if (n.nodeType === 1 && n.tagName === "SPAN" && n.className != "number") {
        var innerText = n.innerText === undefined ? "textContent" : "innerText";
        s += n[innerText] + "\n";
        continue;
      }
      if (n.nodeType === 1 && n.tagName !== "BUTTON") {
        s += text(n);
      }
    }
    return s;
  }

  function init(code) {
    var id = getId();

    var output = document.createElement('div');
    var outpre = document.createElement('pre');
    var stopFunc;

    function onKill() {
      if (stopFunc) {
        stopFunc();
      }
    }

    function onRun(e) {
      onKill();
      outpre.innerHTML = "";
      output.style.display = "block";
      run.style.display = "none";
      var options = {Race: e.shiftKey};
      stopFunc = runFunc(text(code), outpre, options);
    }

    function onClose() {
      onKill();
      output.style.display = "none";
      run.style.display = "inline-block";
    }

    var run = document.createElement('button');
    run.innerHTML = 'Run';
    run.className = 'run';
    run.addEventListener("click", onRun, false);
    var run2 = document.createElement('button');
    run2.className = 'run';
    run2.innerHTML = 'Run';
    run2.addEventListener("click", onRun, false);
    var kill = document.createElement('button');
    kill.className = 'kill';
    kill.innerHTML = 'Kill';
    kill.addEventListener("click", onKill, false);
    var close = document.createElement('button');
    close.className = 'close';
    close.innerHTML = 'Close';
    close.addEventListener("click", onClose, false);

    var button = document.createElement('div');
    button.classList.add('buttons');
    button.appendChild(run);
    // Hack to simulate insertAfter
    code.parentNode.insertBefore(button, code.nextSibling);

    var buttons = document.createElement('div');
    buttons.classList.add('buttons');
    buttons.appendChild(run2);
    buttons.appendChild(kill);
    buttons.appendChild(close);

    output.classList.add('output');
    output.appendChild(buttons);
    output.appendChild(outpre);
    output.style.display = "none";
    code.parentNode.insertBefore(output, button.nextSibling);
  }

  var play = document.querySelectorAll('div.playground');
  for (var i = 0; i < play.length; i++) {
    init(play[i]);
  }
  if (play.length > 0) {
    if (window.connectPlayground) {
      runFunc = window.connectPlayground("ws://" + window.location.host + "/socket");
    } else {
      // If this message is logged,
      // we have neglected to include socket.js or playground.js.
      console.log("No playground transport available.");
    }
  }
})();
<|endoftext|>


<commit_before>function genUni() {
	var code = prompt("Generate Unicode Character:");
	$('#code').val($('#code').val() + String.fromCharCode(parseInt(code)));
	updateByteCount();
};

function getByteCount(s) {
	return s.length;
}

function t(s){for(var i=0;i<s.length;i++){console.log(s.charCodeAt(i));}}

function updateByteCount() {
	var c = $('#code').val();
	var byteCount = getByteCount(c);
	var charCount = c.length;
	var s = byteCount + " bytes and " + charCount + " chars long.";
	$('#byteCount').html(s);
}

function getStrippedCode() {
	var stripped = $('#code').val();
	$('#stripped').html(
			'Stripped code: ' + stripped + ' Byte count: '
					+ getByteCount(stripped));
}

var string = false;
var codeBlock = false;

function getExplanation() {
	$('#explanation').html('');
	var code = $('#code').val();
	for (var x = 0, c = ''; c = code.charAt(x); x++) {
        if(c === '"') {
            string = !string;
        }
        else if(c === '`') {
            codeBlock = !codeBlock;
        }
		var original = $('#explanation').html();
		$('#explanation').html(
				original
						+ " "
                        + codeBlock?'    ':''
                        + string?'':explanations[c.charCodeAt()]
								+ "\r\n");
	}

}

function updateUtils() {
	updateByteCount();
	getStrippedCode();
	getExplanation();
}

updateUtils();

$(document).ready(
		function() {
			$("#permalink").click(
					function() {
						var code = $.param({
							code : $('#code').val(),
							input : $('#input').val()
						});
						prompt("Permalink:", "http://"
								+ window.location.hostname + "/link/" + code);
						window.location.pathname = "/link/" + code;
					});
			$('#code').on('input propertychange paste', function() {
				updateUtils();
			});
		});<commit_msg>fix explanations?<commit_after>function genUni() {
	var code = prompt("Generate Unicode Character:");
	$('#code').val($('#code').val() + String.fromCharCode(parseInt(code)));
	updateByteCount();
};

function getByteCount(s) {
    var count = 0, stringLength = s.length;
    s = String(s || "");
    for (var i = 0; i < stringLength; i++) {
        var partCount = encodeURI(s[i]).split("%").length;
        count += partCount == 1 ? 1 : partCount - 1;
    }
    return count;
}

function t(s){for(var i=0;i<s.length;i++){console.log(s.charCodeAt(i));}}

function updateByteCount() {
	var c = $('#code').val();
	var byteCount = getByteCount(c);
	var charCount = c.length;
	var s = byteCount + " bytes and " + charCount + " chars long.";
	$('#byteCount').html(s);
}

function getStrippedCode() {
	var stripped = $('#code').val();
	$('#stripped').html(
			'Stripped code: ' + stripped + ' Byte count: '
					+ getByteCount(stripped));
}

var string = false;
var codeBlock = false;

function getExplanation() {
	$('#explanation').html('');
	var code = $('#code').val();
    var explain = '';
    var indent = '   ';
	for (var x = 0, c = ''; c = code.charAt(x); x++) {
        if(c === '"') {
            string = !string;
        } else if(c === '`') {
            codeBlock = !codeBlock;
        }
        if(string) {
            explain = '';
        } else {
            explain = explanations[c.charCodeAt()]
        }
        if(codeBlock) {
            indent = '    ';
        } else {
            indent = '';
        }
		var original = $('#explanation').html();
		$('#explanation').html(
				original
						+ " "
                        + indent
                        + explain
								+ "\r\n");
	}

}

function updateUtils() {
	updateByteCount();
	getStrippedCode();
	getExplanation();
}

updateUtils();

$(document).ready(
		function() {
			$("#permalink").click(
					function() {
						var code = $.param({
							code : $('#code').val(),
							input : $('#input').val()
						});
						prompt("Permalink:", "http://"
								+ window.location.hostname + "/link/" + code);
						window.location.pathname = "/link/" + code;
					});
			$('#code').on('input propertychange paste', function() {
				updateUtils();
			});
		});<|endoftext|>


<commit_before>var channels = {"channels": [
    {"channel": "All", "feed": "/r/all/.json"}
    ,{"channel": "Videos", "feed": "/r/videos/.json"}
    ,{"channel": "YouTube", "feed": "/domain/youtube.com/.json"}
    ,{"channel": "Funny", "feed": "/r/funny/.json"}
    ,{"channel": "Politics", "feed": "/r/politics/.json"}
    ,{"channel": "WTF", "feed": "/r/wtf/.json"}
    ,{"channel": "Gaming", "feed": "/r/gaming/.json"}
    ,{"channel": "Science", "feed": "/r/science/.json"}
    ,{"channel": "Geek", "feed": "/r/geek/.json"}
    ,{"channel": "AWW", "feed": "/r/aww/.json"}
    ,{"channel": "Music", "feed": "/r/music/.json"}
    ,{"channel": "Listen", "feed": "/r/listentothis/.json"}
    ,{"channel": "Sports", "feed": "/r/sports/.json"}
    ,{"channel": "TED", "feed": "/domain/ted.com/.json"}
  ]
};

var videos = new Array();
var cur_video = 0;
var cur_chan = 0;
var cur_req = null;
var auto = true;

$().ready(function(){
	displayChannels();
	loadChannel("Videos");
        $('#auto').click(function() {
	        auto = ($('#auto').is(':checked')) ? true : false;
	    });
        $('#fill').click(function() {
	        fill = ($('#fill').is(':checked')) ? true : false;
		fillScreen();
            });
	$('#next-button').click(function() {
		loadVideo('next');
	    });
	$('#prev-button').click(function() {
		loadVideo('prev');;
	    });
	//bind arrow keys
	$(document).keydown(function (e) {
		var keyCode = e.keyCode || e.which;
		var arrow = {left: 37, up: 38, right: 39, down: 40 };
		switch (keyCode) {
		    case arrow.left:
		        loadVideo('prev');
			break;
		    case arrow.up:
		        chgChan('up');
			break;
		    case arrow.right:
			loadVideo('next');
			break;
		    case arrow.down:
		        chgChan('down');
			break;
		    case 32:
		        ytTogglePlay();
		        break;
		    case 70:
		        $('#fill').attr('checked', true);
		        fillScreen();
		        break;
		    case 27:
		        if($('#fill').is(':checked')){
			    fillScreen();
		        }
			break;
		}
	});
});

var displayChannels = function displayChannels() {
    var $channel_list = $('#channel-list');
    var list = $(
		 '
'
		 +'
'
		 );
    $channel_list.html(list);
    for(var x in channels.channels){
	$('#channel-list>ul').append('
'+channels.channels[x].channel+'
');
	$('#channel-'+x).bind(
			       'click'
			       ,{channel: channels.channels[x].channel}
			       , function(event) {
				   loadChannel(event.data.channel);
			       });
    }
}

var loadChannel = function loadChannel(channel) {
    var last_req = cur_req;
    if(last_req != null){
	last_req.abort();
    }

    cur_chan = getChan(channel);

    var $video_embed = $('#video-embed');
    var $video_title = $('#video-title');

    $video_title.html('Loading '+channels.channels[cur_chan].feed.slice(0,-5)+' ...');
    $video_embed.addClass('loading');
    $video_embed.empty();

    $('#channel-list>ul>li').removeClass('chan-selected');
    $('#channel-'+getChan(channel)).addClass('chan-selected');

    var feed = getFeedName(channel);
    cur_req = $.jsonp({
	url: "http://www.reddit.com"+feed+"?limit=100&jsonp=callback",
	callback: "callback",
	success: function(data) {
	    videos = new Array(); //clear out stored videos
            for(var x in data.data.children){
                if(!isEmpty(data.data.children[x].data.media_embed)
                         && data.data.children[x].data.media.type != 'soundcloud.com'
                         && data.data.children[x].data.media.type != 'craigslist.org'
                  )
                {
                    videos.push(data.data.children[x].data);
                }
            }
	    cur_video = 0;
	    loadVideo('first');
	},
	error: function() {
	    alert('Could not load feed. Is reddit down?');
	}
    });
}

var loadVideo = function loadVideo(video) {
    var this_video = cur_video;
    if(video == 'next' && cur_video < Object.size(videos)-1){
	cur_video++;
    }else if (cur_video > 0 && video != 'next'){
	cur_video--;
    }
    if(this_video != cur_video || video == 'first') {
	var title = $.unescapifyHTML(videos[cur_video].title);
	var embed = $.unescapifyHTML(videos[cur_video].media_embed.content);
	if(videos[cur_video].media.type == 'youtube.com'){
	    embed = prepYT(embed);
	}else{
	    yt_player = false;
	}
	var permalink = 'http://reddit.com'+$.unescapifyHTML(videos[cur_video].permalink);
	$('#video-title').html(''+title+'');
	$('#video-embed').html(embed);
	fillScreen();
    }
}

var chgChan = function chgChan(up_down) {
    var this_chan = cur_chan;
    if(up_down == 'up' && this_chan > 0){
	cur_chan--;
    }else if(up_down != 'up' && this_chan < channels.channels.length-1){
	cur_chan++;
    }
    if(this_chan != cur_chan){
	loadChannel(channels.channels[cur_chan].channel);
    }
}

var getFeedName = function getFeedName(channel) {
    for(var x in channels.channels){
	if(channels.channels[x].channel == channel){
	    return channels.channels[x].feed;
	}
    }
}

var getChan = function getChan(channel) {
    for(var x in channels.channels){
        if(channels.channels[x].channel == channel){
            return x;
        }
    }
}

var prepYT = function prepYT(embed) {
    var embed = embed;
    var js_str = '&enablejsapi=1';
    var split = embed.indexOf('?fs=1')+5;
    embed = embed.substr(0,split)+js_str+embed.substr(split);
    split = embed.indexOf('?fs=1" type="')+5;
    embed = embed.substr(0,split)+js_str+embed.substr(split);
    split = embed.indexOf('embed')+5;
    embed = embed.substr(0,split)+' id="ytplayer" '+embed.substr(split);
    return embed;
}

var fillScreen = function fillScreen() {
    if(yt_player){
	$object = $('#video-embed>object>embed');
	$fill = $('#fill');
	if($object.hasClass('fill-screen')){
	    $object.removeClass('fill-screen');
	    $fill.attr('checked', false);
	}else if($fill.is(':checked')){
	    $object.addClass('fill-screen');
	}
    }
}

function onYouTubePlayerReady(playerId) {
    yt_player = document.getElementById("ytplayer");
    yt_player.addEventListener("onStateChange", "ytAuto");
}

function ytAuto(state) {
    if(auto){
	if(state == 0){
	    loadVideo('next');
	}else if(state == 5){
	    ytTogglePlay();
	}
    }
}

function ytTogglePlay() {
    if (yt_player) {
	//unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)
	if(yt_player.getPlayerState() != 1){
	    yt_player.playVideo();
	}else{
	    yt_player.pauseVideo();
	}
    }
}

var isEmpty = function isEmpty(obj) {
    for(var prop in obj) {
	if(obj.hasOwnProperty(prop))
            return false;
    }
    return true;
}

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
	if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};<commit_msg>fix title link title attribute<commit_after>var channels = {"channels": [
    {"channel": "All", "feed": "/r/all/.json"}
    ,{"channel": "Videos", "feed": "/r/videos/.json"}
    ,{"channel": "YouTube", "feed": "/domain/youtube.com/.json"}
    ,{"channel": "Funny", "feed": "/r/funny/.json"}
    ,{"channel": "Politics", "feed": "/r/politics/.json"}
    ,{"channel": "WTF", "feed": "/r/wtf/.json"}
    ,{"channel": "Gaming", "feed": "/r/gaming/.json"}
    ,{"channel": "Science", "feed": "/r/science/.json"}
    ,{"channel": "Geek", "feed": "/r/geek/.json"}
    ,{"channel": "AWW", "feed": "/r/aww/.json"}
    ,{"channel": "Music", "feed": "/r/music/.json"}
    ,{"channel": "Listen", "feed": "/r/listentothis/.json"}
    ,{"channel": "Sports", "feed": "/r/sports/.json"}
    ,{"channel": "TED", "feed": "/domain/ted.com/.json"}
  ]
};

var videos = new Array();
var cur_video = 0;
var cur_chan = 0;
var cur_req = null;
var auto = true;

$().ready(function(){
	displayChannels();
	loadChannel("Videos");
        $('#auto').click(function() {
	        auto = ($('#auto').is(':checked')) ? true : false;
	    });
        $('#fill').click(function() {
	        fill = ($('#fill').is(':checked')) ? true : false;
		fillScreen();
            });
	$('#next-button').click(function() {
		loadVideo('next');
	    });
	$('#prev-button').click(function() {
		loadVideo('prev');;
	    });
	//bind arrow keys
	$(document).keydown(function (e) {
		var keyCode = e.keyCode || e.which;
		var arrow = {left: 37, up: 38, right: 39, down: 40 };
		switch (keyCode) {
		    case arrow.left:
		        loadVideo('prev');
			break;
		    case arrow.up:
		        chgChan('up');
			break;
		    case arrow.right:
			loadVideo('next');
			break;
		    case arrow.down:
		        chgChan('down');
			break;
		    case 32:
		        ytTogglePlay();
		        break;
		    case 70:
		        $('#fill').attr('checked', true);
		        fillScreen();
		        break;
		    case 27:
		        if($('#fill').is(':checked')){
			    fillScreen();
		        }
			break;
		}
	});
});

var displayChannels = function displayChannels() {
    var $channel_list = $('#channel-list');
    var list = $(
		 '
'
		 +'
'
		 );
    $channel_list.html(list);
    for(var x in channels.channels){
	$('#channel-list>ul').append('
'+channels.channels[x].channel+'
');
	$('#channel-'+x).bind(
			       'click'
			       ,{channel: channels.channels[x].channel}
			       , function(event) {
				   loadChannel(event.data.channel);
			       });
    }
}

var loadChannel = function loadChannel(channel) {
    var last_req = cur_req;
    if(last_req != null){
	last_req.abort();
    }

    cur_chan = getChan(channel);

    var $video_embed = $('#video-embed');
    var $video_title = $('#video-title');

    $video_title.html('Loading '+channels.channels[cur_chan].feed.slice(0,-5)+' ...');
    $video_embed.addClass('loading');
    $video_embed.empty();

    $('#channel-list>ul>li').removeClass('chan-selected');
    $('#channel-'+getChan(channel)).addClass('chan-selected');

    var feed = getFeedName(channel);
    cur_req = $.jsonp({
	url: "http://www.reddit.com"+feed+"?limit=100&jsonp=callback",
	callback: "callback",
	success: function(data) {
	    videos = new Array(); //clear out stored videos
            for(var x in data.data.children){
                if(!isEmpty(data.data.children[x].data.media_embed)
                         && data.data.children[x].data.media.type != 'soundcloud.com'
                         && data.data.children[x].data.media.type != 'craigslist.org'
                  )
                {
                    videos.push(data.data.children[x].data);
                }
            }
	    cur_video = 0;
	    loadVideo('first');
	},
	error: function() {
	    alert('Could not load feed. Is reddit down?');
	}
    });
}

var loadVideo = function loadVideo(video) {
    var this_video = cur_video;
    if(video == 'next' && cur_video < Object.size(videos)-1){
	cur_video++;
    }else if (cur_video > 0 && video != 'next'){
	cur_video--;
    }
    if(this_video != cur_video || video == 'first') {
	var title = $.unescapifyHTML(videos[cur_video].title);
	var esc_title = String(title).replace(/\"/g,'"');
	var embed = $.unescapifyHTML(videos[cur_video].media_embed.content);
	if(videos[cur_video].media.type == 'youtube.com'){
	    embed = prepYT(embed);
	}else{
	    yt_player = false;
	}
	var permalink = 'http://reddit.com'+$.unescapifyHTML(videos[cur_video].permalink);
	$('#video-title').html(''+title+'');
	$('#video-embed').html(embed);
	fillScreen();
    }
}

var chgChan = function chgChan(up_down) {
    var this_chan = cur_chan;
    if(up_down == 'up' && this_chan > 0){
	cur_chan--;
    }else if(up_down != 'up' && this_chan < channels.channels.length-1){
	cur_chan++;
    }
    if(this_chan != cur_chan){
	loadChannel(channels.channels[cur_chan].channel);
    }
}

var getFeedName = function getFeedName(channel) {
    for(var x in channels.channels){
	if(channels.channels[x].channel == channel){
	    return channels.channels[x].feed;
	}
    }
}

var getChan = function getChan(channel) {
    for(var x in channels.channels){
        if(channels.channels[x].channel == channel){
            return x;
        }
    }
}

var prepYT = function prepYT(embed) {
    var embed = embed;
    var js_str = '&enablejsapi=1';
    var split = embed.indexOf('?fs=1')+5;
    embed = embed.substr(0,split)+js_str+embed.substr(split);
    split = embed.indexOf('?fs=1" type="')+5;
    embed = embed.substr(0,split)+js_str+embed.substr(split);
    split = embed.indexOf('embed')+5;
    embed = embed.substr(0,split)+' id="ytplayer" '+embed.substr(split);
    return embed;
}

var fillScreen = function fillScreen() {
    if(yt_player){
	$object = $('#video-embed>object>embed');
	$fill = $('#fill');
	if($object.hasClass('fill-screen')){
	    $object.removeClass('fill-screen');
	    $fill.attr('checked', false);
	}else if($fill.is(':checked')){
	    $object.addClass('fill-screen');
	}
    }
}

function onYouTubePlayerReady(playerId) {
    yt_player = document.getElementById("ytplayer");
    yt_player.addEventListener("onStateChange", "ytAuto");
}

function ytAuto(state) {
    if(auto){
	if(state == 0){
	    loadVideo('next');
	}else if(state == 5){
	    ytTogglePlay();
	}
    }
}

function ytTogglePlay() {
    if (yt_player) {
	//unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)
	if(yt_player.getPlayerState() != 1){
	    yt_player.playVideo();
	}else{
	    yt_player.pauseVideo();
	}
    }
}

var isEmpty = function isEmpty(obj) {
    for(var prop in obj) {
	if(obj.hasOwnProperty(prop))
            return false;
    }
    return true;
}

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
	if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

function htmlEncode(value){
    return $('
').text(value).html();
}

function htmlDecode(value){
    return $('
').html(value).text();
}
<|endoftext|>