123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- define(["require", "jquery", "util", "session", "templates", "templating", "linkify", "peers", "windowing", "tinycolor", "elementFinder", "visibilityApi"], function (require, $, util, session, templates, templating, linkify, peers, windowing, tinycolor, elementFinder, visibilityApi) {
- var ui = util.Module('ui');
- var assert = util.assert;
- var AssertionError = util.AssertionError;
- var chat;
- var $window = $(window);
- // This is also in togetherjs.less, as @button-height:
- var BUTTON_HEIGHT = 60 + 1; // 60 is button height, 1 is border
- // chat TextArea
- var TEXTAREA_LINE_HEIGHT = 20; // in pixels
- var TEXTAREA_MAX_LINES = 5;
- // This is also in togetherjs.less, under .togetherjs-animated
- var ANIMATION_DURATION = 1000;
- // Time the new user window sticks around until it fades away:
- var NEW_USER_FADE_TIMEOUT = 5000;
- // This is set when an animation will keep the UI from being ready
- // (until this time):
- var finishedAt = null;
- // Time in milliseconds for the dock to animate out:
- var DOCK_ANIMATION_TIME = 300;
- // If two chat messages come from the same person in this time
- // (milliseconds) then they are collapsed into one message:
- var COLLAPSE_MESSAGE_LIMIT = 5000;
- var COLORS = [
- "#8A2BE2", "#7FFF00", "#DC143C", "#00FFFF", "#8FBC8F", "#FF8C00", "#FF00FF",
- "#FFD700", "#F08080", "#90EE90", "#FF6347"];
- // This would be a circular import, but we just need the chat module sometime
- // after everything is loaded, and this is sure to complete by that time:
- require(["chat"], function (c) {
- chat = c;
- });
- /* Displays some toggleable element; toggleable elements have a
- data-toggles attribute that indicates what other elements should
- be hidden when this element is shown. */
- ui.displayToggle = function (el) {
- el = $(el);
- assert(el.length, "No element", arguments[0]);
- var other = $(el.attr("data-toggles"));
- assert(other.length, "Cannot toggle", el[0], "selector", other.selector);
- other.hide();
- el.show();
- };
- function panelPosition() {
- var iface = $("#togetherjs-dock");
- if (iface.hasClass("togetherjs-dock-right")) {
- return "right";
- } else if (iface.hasClass("togetherjs-dock-left")) {
- return "left";
- } else if (iface.hasClass("togetherjs-dock-bottom")) {
- return "bottom";
- } else {
- throw new AssertionError("#togetherjs-dock doesn't have positioning class");
- }
- }
- ui.container = null;
- // This is used for some signalling when ui.prepareUI and/or
- // ui.activateUI is called before the DOM is fully loaded:
- var deferringPrepareUI = null;
- function deferForContainer(func) {
- /* Defers any calls to func() until after ui.container is set
- Function cannot have a return value (as sometimes the call will
- become async). Use like:
- method: deferForContainer(function (args) {...})
- */
- return function () {
- if (ui.container) {
- func.apply(this, arguments);
- }
- var self = this;
- var args = Array.prototype.slice.call(arguments);
- session.once("ui-ready", function () {
- func.apply(self, args);
- });
- };
- }
- // This is called before activateUI; it doesn't bind anything, but does display
- // the dock
- // FIXME: because this module has lots of requirements we can't do
- // this before those requirements are loaded. Maybe worth splitting
- // this out? OTOH, in production we should have all the files
- // combined so there's not much problem loading those modules.
- ui.prepareUI = function () {
- if (! (document.readyState == "complete" || document.readyState == "interactive")) {
- // Too soon! Wait a sec...
- deferringPrepareUI = "deferring";
- document.addEventListener("DOMContentLoaded", function () {
- var d = deferringPrepareUI;
- deferringPrepareUI = null;
- ui.prepareUI();
- // This happens when ui.activateUI is called before the document has been
- // loaded:
- if (d == "activate") {
- ui.activateUI();
- }
- });
- return;
- }
- var container = ui.container = $(templates("interface"));
- assert(container.length);
- $("body").append(container);
- fixupAvatars(container);
- if (session.firstRun && TogetherJS.startTarget) {
- // Time at which the UI will be fully ready:
- // (We have to do this because the offset won't be quite right
- // until the animation finishes - attempts to calculate the
- // offset without taking into account CSS transforms have so far
- // failed.)
- var timeoutSeconds = DOCK_ANIMATION_TIME / 1000;
- finishedAt = Date.now() + DOCK_ANIMATION_TIME + 50;
- setTimeout(function () {
- finishedAt = Date.now() + DOCK_ANIMATION_TIME + 40;
- var iface = container.find("#togetherjs-dock");
- var start = iface.offset();
- var pos = $(TogetherJS.startTarget).offset();
- pos.top = Math.floor(pos.top - start.top);
- pos.left = Math.floor(pos.left - start.left);
- var translate = "translate(" + pos.left + "px, " + pos.top + "px)";
- iface.css({
- MozTransform: translate,
- WebkitTransform: translate,
- transform: translate,
- opacity: "0.0"
- });
- setTimeout(function () {
- // We keep recalculating because the setTimeout times aren't always so accurate:
- finishedAt = Date.now() + DOCK_ANIMATION_TIME + 20;
- var transition = "transform " + timeoutSeconds + "s ease-out, ";
- transition += "opacity " + timeoutSeconds + "s ease-out";
- iface.css({
- opacity: "1.0",
- MozTransition: "-moz-" + transition,
- MozTransform: "translate(0, 0)",
- WebkitTransition: "-webkit-" + transition,
- WebkitTransform: "translate(0, 0)",
- transition: transition,
- transform: "translate(0, 0)"
- });
- setTimeout(function () {
- finishedAt = null;
- iface.attr("style", "");
- }, 510);
- }, 5);
- }, 5);
- }
- if (TogetherJS.startTarget) {
- var el = $(TogetherJS.startTarget);
- var text = el.text().toLowerCase().replace(/\s+/g, " ");
- text = text.replace(/^\s*/, "").replace(/\s*$/, "");
- if (text == "start togetherjs") {
- el.attr("data-end-togetherjs-html", "End TogetherJS");
- }
- if (el.attr("data-end-togetherjs-html")) {
- el.attr("data-start-togetherjs-html", el.html());
- el.html(el.attr("data-end-togetherjs-html"));
- }
- el.addClass("togetherjs-started");
- }
- ui.container.find(".togetherjs-window > header, .togetherjs-modal > header").each(function () {
- $(this).append($('<button class="togetherjs-close"></button>'));
- });
- TogetherJS.config.track("disableWebRTC", function (hide, previous) {
- if (hide && ! previous) {
- ui.container.find("#togetherjs-audio-button").hide();
- adjustDockSize(-1);
- } else if ((! hide) && previous) {
- ui.container.find("#togetherjs-audio-button").show();
- adjustDockSize(1);
- }
- });
- };
- // After prepareUI, this actually makes the interface live. We have
- // to do this later because we call prepareUI when many components
- // aren't initialized, so we don't even want the user to be able to
- // interact with the interface. But activateUI is called once
- // everything is loaded and ready for interaction.
- ui.activateUI = function () {
- if (deferringPrepareUI) {
- console.warn("ui.activateUI called before document is ready; waiting...");
- deferringPrepareUI = "activate";
- return;
- }
- if (! ui.container) {
- ui.prepareUI();
- }
- var container = ui.container;
- //create the overlay
- if($.browser.mobile) {
- // $("body").append( "\x3cdiv class='overlay' style='position: absolute; top: 0; left: 0; background-color: rgba(0,0,0,0); width: 120%; height: 100%; z-index: 1000; margin: -10px'>\x3c/div>" );
- }
- // The share link:
- ui.prepareShareLink(container);
- container.find("input.togetherjs-share-link").on("keydown", function (event) {
- if (event.which == 27) {
- windowing.hide("#togetherjs-share");
- return false;
- }
- return undefined;
- });
- session.on("shareId", updateShareLink);
- // The chat input element:
- var input = container.find("#togetherjs-chat-input");
- input.bind("keydown", function (event) {
- if (event.which == 13 && !event.shiftKey) { // Enter without Shift pressed
- submitChat();
- return false;
- }
- if (event.which == 27) { // Escape
- windowing.hide("#togetherjs-chat");
- return false;
- }
- });
- function submitChat() {
- var val = input.val();
- if ($.trim(val)) {
- input.val("");
- // triggering the event manually to avoid the addition of newline character to the textarea:
- input.trigger("input").trigger("propertychange");
- chat.submit(val);
- }
- }
- // auto-resize textarea:
- input.on("input propertychange", function () {
- var $this = $(this);
- var actualHeight = $this.height();
- // reset the height of textarea to remove trailing empty space (used for shrinking):
- $this.height(TEXTAREA_LINE_HEIGHT);
- this.scrollTop = 0;
- // scroll to bottom:
- this.scrollTop = 9999;
- var newHeight = this.scrollTop + $this.height();
- var maxHeight = TEXTAREA_MAX_LINES * TEXTAREA_LINE_HEIGHT;
- if (newHeight > maxHeight) {
- newHeight = maxHeight;
- this.style.overflowY = "scroll";
- } else {
- this.style.overflowY = "hidden";
- }
- this.style.height = newHeight + "px";
- var diff = newHeight - actualHeight;
- $("#togetherjs-chat-input-box").height($("#togetherjs-chat-input-box").height() + diff);
- $("#togetherjs-chat-messages").height($("#togetherjs-chat-messages").height() - diff);
- return false;
- });
- util.testExpose({submitChat: submitChat});
- // Moving the window:
- // FIXME: this should probably be stickier, and not just move the window around
- // so abruptly
- var anchor = container.find("#togetherjs-dock-anchor");
- assert(anchor.length);
- // FIXME: This is in place to temporarily disable dock dragging:
- anchor = container.find("#togetherjs-dock-anchor-disabled");
- anchor.mousedown(function (event) {
- var iface = $("#togetherjs-dock");
- // FIXME: switch to .offset() and pageX/Y
- var startPos = panelPosition();
- function selectoff() {
- return false;
- }
- function mousemove(event2) {
- var fromRight = $window.width() + window.pageXOffset - event2.pageX;
- var fromLeft = event2.pageX - window.pageXOffset;
- var fromBottom = $window.height() + window.pageYOffset - event2.pageY;
- // FIXME: this is to temporarily disable the bottom view:
- fromBottom = 10000;
- var pos;
- if (fromLeft < fromRight && fromLeft < fromBottom) {
- pos = "left";
- } else if (fromRight < fromLeft && fromRight < fromBottom) {
- pos = "right";
- } else {
- pos = "bottom";
- }
- iface.removeClass("togetherjs-dock-left");
- iface.removeClass("togetherjs-dock-right");
- iface.removeClass("togetherjs-dock-bottom");
- iface.addClass("togetherjs-dock-" + pos);
- if (startPos && pos != startPos) {
- windowing.hide();
- startPos = null;
- }
- }
- $(document).bind("mousemove", mousemove);
- // If you don't turn selection off it will still select text, and show a
- // text selection cursor:
- $(document).bind("selectstart", selectoff);
- // FIXME: it seems like sometimes we lose the mouseup event, and it's as though
- // the mouse is stuck down:
- $(document).one("mouseup", function () {
- $(document).unbind("mousemove", mousemove);
- $(document).unbind("selectstart", selectoff);
- });
- return false;
- });
- function openDock() {
- $('.togetherjs-window').animate({
- opacity: 1
- });
- $('#togetherjs-dock-participants').animate({
- opacity: 1
- });
- $('#togetherjs-dock #togetherjs-buttons').animate({
- opacity: 1
- });
- //for iphone
- if($(window).width() < 480) {
- $('.togetherjs-dock-right').animate({
- width: "204px"
- }, {
- duration:60, easing:"linear"
- });
- }
- //for ipad
- else {
- $('.togetherjs-dock-right').animate({
- width: "27%"
- }, {
- duration:60, easing:"linear"
- });
- }
- // add bg overlay
- // $("body").append( "\x3cdiv class='overlay' style='position: absolute; top: 0; left: -2px; background-color: rgba(0,0,0,0.5); width: 200%; height: 400%; z-index: 1000; margin: 0px;'>\x3c/div>" );
- //disable vertical scrolling
- // $("body").css({
- // "position": "fixed",
- // top: 0,
- // left: 0
- // });
- //replace the anchor icon
- var src = "/togetherjs/images/togetherjs-logo-close.png";
- $("#togetherjs-dock-anchor #togetherjs-dock-anchor-horizontal img").attr("src", src);
- }
- function closeDock() {
- //enable vertical scrolling
- $("body").css({
- "position": "",
- top: "",
- left: ""
- });
- //replace the anchor icon
- var src = "/togetherjs/images/togetherjs-logo-open.png";
- $("#togetherjs-dock-anchor #togetherjs-dock-anchor-horizontal img").attr("src", src);
- $('.togetherjs-window').animate({
- opacity: 0
- });
- $('#togetherjs-dock-participants').animate({
- opacity: 0
- });
- $('#togetherjs-dock #togetherjs-buttons').animate({
- opacity: 0
- });
- $('.togetherjs-dock-right').animate({
- width: "40px"
- }, {
- duration:60, easing:"linear"
- });
- // remove bg overlay
- //$(".overlay").remove();
- }
- // Setting the anchor button + dock mobile actions
- if($.browser.mobile) {
- // toggle the audio button
- $("#togetherjs-audio-button").click(function () {
- windowing.toggle("#togetherjs-rtc-not-supported");
- });
- // toggle the profile button
- $("#togetherjs-profile-button").click(function () {
- windowing.toggle("#togetherjs-menu-window");
- });
- // $("body").append( "\x3cdiv class='overlay' style='position: absolute; top: 0; left: -2px; background-color: rgba(0,0,0,0.5); width: 200%; height: 400%; z-index: 1000; margin: 0px'>\x3c/div>" );
- //disable vertical scrolling
- // $("body").css({
- // "position": "fixed",
- // top: 0,
- // left: 0
- // });
- //replace the anchor icon
- var src = "/togetherjs/images/togetherjs-logo-close.png";
- $("#togetherjs-dock-anchor #togetherjs-dock-anchor-horizontal img").attr("src", src);
- $("#togetherjs-dock-anchor").toggle(function() {
- closeDock();
- },function(){
- openDock();
- });
- }
- $("#togetherjs-share-button").click(function () {
- windowing.toggle("#togetherjs-share");
- });
- $("#togetherjs-profile-button").click(function (event) {
- if ($.browser.mobile) {
- windowing.show("#togetherjs-menu-window");
- return false;
- }
- toggleMenu();
- event.stopPropagation();
- return false;
- });
- $("#togetherjs-menu-feedback, #togetherjs-menu-feedback-button").click(function(){
- windowing.hide();
- hideMenu();
- windowing.show("#togetherjs-feedback-form");
- });
- $("#togetherjs-menu-help, #togetherjs-menu-help-button").click(function () {
- windowing.hide();
- hideMenu();
- require(["walkthrough"], function (walkthrough) {
- windowing.hide();
- walkthrough.start(false);
- });
- });
- $("#togetherjs-menu-update-name").click(function () {
- var input = $("#togetherjs-menu .togetherjs-self-name");
- input.css({
- width: $("#togetherjs-menu").width() - 32 + "px"
- });
- ui.displayToggle("#togetherjs-menu .togetherjs-self-name");
- $("#togetherjs-menu .togetherjs-self-name").focus();
- });
- $("#togetherjs-menu-update-name-button").click(function () {
- windowing.show("#togetherjs-edit-name-window");
- $("#togetherjs-edit-name-window input").focus();
- });
- $("#togetherjs-menu .togetherjs-self-name").bind("keyup change", function (event) {
- console.log("alrighty", event);
- if (event.which == 13) {
- ui.displayToggle("#togetherjs-self-name-display");
- return;
- }
- var val = $("#togetherjs-menu .togetherjs-self-name").val();
- console.log("values!!", val);
- if (val) {
- peers.Self.update({name: val});
- }
- });
- $("#togetherjs-menu-update-avatar, #togetherjs-menu-update-avatar-button").click(function () {
- hideMenu();
- windowing.show("#togetherjs-avatar-edit");
- });
- $("#togetherjs-menu-end, #togetherjs-menu-end-button").click(function () {
- hideMenu();
- windowing.show("#togetherjs-confirm-end");
- });
- $("#togetherjs-end-session").click(function () {
- session.close();
- //$(".overlay").remove();
- });
- $("#togetherjs-menu-update-color").click(function () {
- var picker = $("#togetherjs-pick-color");
- if (picker.is(":visible")) {
- picker.hide();
- return;
- }
- picker.show();
- bindPicker();
- picker.find(".togetherjs-swatch-active").removeClass("togetherjs-swatch-active");
- picker.find(".togetherjs-swatch[data-color=\"" + peers.Self.color + "\"]").addClass("togetherjs-swatch-active");
- });
- $("#togetherjs-pick-color").click(".togetherjs-swatch", function (event) {
- var swatch = $(event.target);
- var color = swatch.attr("data-color");
- peers.Self.update({
- color: color
- });
- event.stopPropagation();
- return false;
- });
- $("#togetherjs-pick-color").click(function (event) {
- $("#togetherjs-pick-color").hide();
- event.stopPropagation();
- return false;
- });
- COLORS.forEach(function (color) {
- var el = templating.sub("swatch");
- el.attr("data-color", color);
- var darkened = tinycolor.darken(color);
- el.css({
- backgroundColor: color,
- borderColor: darkened
- });
- $("#togetherjs-pick-color").append(el);
- });
- $("#togetherjs-chat-button").click(function () {
- windowing.toggle("#togetherjs-chat");
- });
- session.on("display-window", function (id, element) {
- if (id == "togetherjs-chat") {
- if (! $.browser.mobile) {
- $("#togetherjs-chat-input").focus();
- }
- } else if (id == "togetherjs-share") {
- var link = element.find("input.togetherjs-share-link");
- if (link.is(":visible")) {
- link.focus().select();
- }
- }
- });
- container.find("#togetherjs-chat-notifier").click(function (event) {
- if ($(event.target).is("a") || container.is(".togetherjs-close")) {
- return;
- }
- windowing.show("#togetherjs-chat");
- });
- // FIXME: Don't think this makes sense
- $(".togetherjs header.togetherjs-title").each(function (index, item) {
- var button = $('<button class="togetherjs-minimize"></button>');
- button.click(function (event) {
- var window = button.closest(".togetherjs-window");
- windowing.hide(window);
- });
- $(item).append(button);
- });
- $("#togetherjs-avatar-done").click(function () {
- ui.displayToggle("#togetherjs-no-avatar-edit");
- });
- $("#togetherjs-self-color").css({backgroundColor: peers.Self.color});
- var avatar = peers.Self.avatar;
- if (avatar) {
- $("#togetherjs-self-avatar").attr("src", avatar);
- }
- var starterButton = $("#togetherjs-starter button");
- starterButton.click(function () {
- windowing.show("#togetherjs-about");
- }).addClass("togetherjs-running");
- if (starterButton.text() == "Start TogetherJS") {
- starterButton.attr("data-start-text", starterButton.text());
- starterButton.text("End TogetherJS Session");
- }
- ui.activateAvatarEdit(container, {
- onSave: function () {
- windowing.hide("#togetherjs-avatar-edit");
- }
- });
- TogetherJS.config.track("inviteFromRoom", function (inviter, previous) {
- if (inviter) {
- container.find("#togetherjs-invite").show();
- } else {
- container.find("#togetherjs-invite").hide();
- }
- });
- container.find("#togetherjs-menu-refresh-invite").click(refreshInvite);
- container.find("#togetherjs-menu-invite-anyone").click(function () {
- invite(null);
- });
- // The following lines should be at the end of this function
- // (new code goes above)
- session.emit("new-element", ui.container);
- if (finishedAt && finishedAt > Date.now()) {
- setTimeout(function () {
- finishedAt = null;
- session.emit("ui-ready", ui);
- }, finishedAt - Date.now());
- } else {
- session.emit("ui-ready", ui);
- }
- }; // End ui.activateUI()
- ui.activateAvatarEdit = function (container, options) {
- options = options || {};
- var pendingImage = null;
- container.find(".togetherjs-avatar-save").prop("disabled", true);
- container.find(".togetherjs-avatar-save").click(function () {
- if (pendingImage) {
- peers.Self.update({avatar: pendingImage});
- container.find(".togetherjs-avatar-save").prop("disabled", true);
- if (options.onSave) {
- options.onSave();
- }
- }
- });
- container.find(".togetherjs-upload-avatar").on("change", function () {
- util.readFileImage(this).then(function (url) {
- sizeDownImage(url).then(function (smallUrl) {
- pendingImage = smallUrl;
- container.find(".togetherjs-avatar-preview").css({
- backgroundImage: 'url(' + pendingImage + ')'
- });
- container.find(".togetherjs-avatar-save").prop("disabled", false);
- if (options.onPending) {
- options.onPending();
- }
- });
- });
- });
- };
- function sizeDownImage(imageUrl) {
- return util.Deferred(function (def) {
- var $canvas = $("<canvas>");
- $canvas[0].height = session.AVATAR_SIZE;
- $canvas[0].width = session.AVATAR_SIZE;
- var context = $canvas[0].getContext("2d");
- var img = new Image();
- img.src = imageUrl;
- // Sometimes the DOM updates immediately to call
- // naturalWidth/etc, and sometimes it doesn't; using setTimeout
- // gives it a chance to catch up
- setTimeout(function () {
- var width = img.naturalWidth || img.width;
- var height = img.naturalHeight || img.height;
- width = width * (session.AVATAR_SIZE / height);
- height = session.AVATAR_SIZE;
- context.drawImage(img, 0, 0, width, height);
- def.resolve($canvas[0].toDataURL("image/png"));
- });
- });
- }
- function fixupAvatars(container) {
- /* All <div class="togetherjs-person" /> elements need an element inside,
- so we add that element here */
- container.find(".togetherjs-person").each(function () {
- var $this = $(this);
- var inner = $this.find(".togetherjs-person-avatar-swatch");
- if (! inner.length) {
- $this.append('<div class="togetherjs-person-avatar-swatch"></div>');
- }
- });
- }
- ui.prepareShareLink = function (container) {
- container.find("input.togetherjs-share-link").click(function () {
- $(this).select();
- }).change(function () {
- updateShareLink();
- });
- container.find("a.togetherjs-share-link").click(function () {
- // FIXME: this is currently opening up Bluetooth, not sharing a link
- if (false && window.MozActivity) {
- var activity = new MozActivity({
- name: "share",
- data: {
- type: "url",
- url: $(this).attr("href")
- }
- });
- }
- // FIXME: should show some help if you actually try to follow the link
- // like this, instead of simply suppressing it
- return false;
- });
- updateShareLink();
- };
- // Menu
- function showMenu(event) {
- var el = $("#togetherjs-menu");
- assert(el.length);
- el.show();
- bindMenu();
- $(document).bind("click", maybeHideMenu);
- }
- function bindMenu() {
- var el = $("#togetherjs-menu:visible");
- if (el.length) {
- var bound = $("#togetherjs-profile-button");
- var boundOffset = bound.offset();
- el.css({
- top: boundOffset.top + bound.height() - $window.scrollTop() + "px",
- left: (boundOffset.left + bound.width() - 10 - el.width() - $window.scrollLeft()) + "px"
- });
- }
- }
- function bindPicker() {
- var picker = $("#togetherjs-pick-color:visible");
- if (picker.length) {
- var menu = $("#togetherjs-menu-update-color");
- var menuOffset = menu.offset();
- picker.css({
- top: menuOffset.top + menu.height(),
- left: menuOffset.left
- });
- }
- }
- session.on("resize", function () {
- bindMenu();
- bindPicker();
- });
- function toggleMenu() {
- if ($("#togetherjs-menu").is(":visible")) {
- hideMenu();
- } else {
- showMenu();
- }
- }
- function hideMenu() {
- var el = $("#togetherjs-menu");
- el.hide();
- $(document).unbind("click", maybeHideMenu);
- ui.displayToggle("#togetherjs-self-name-display");
- $("#togetherjs-pick-color").hide();
- }
- function maybeHideMenu(event) {
- var t = event.target;
- while (t) {
- if (t.id == "togetherjs-menu") {
- // Click inside the menu, ignore this
- return;
- }
- t = t.parentNode;
- }
- hideMenu();
- }
- function adjustDockSize(buttons) {
- /* Add or remove spots from the dock; positive number to
- add button(s), negative number to remove button(s)
- */
- assert(typeof buttons == "number");
- assert(buttons && Math.floor(buttons) == buttons);
- var iface = $("#togetherjs-dock");
- var newHeight = iface.height() + (BUTTON_HEIGHT * buttons);
- assert(newHeight >= BUTTON_HEIGHT * 3, "Height went too low (", newHeight,
- "), should never be less than 3 buttons high (", BUTTON_HEIGHT * 3, ")");
- iface.css({
- height: newHeight + "px"
- });
- }
- // Misc
- function updateShareLink() {
- var input = $("input.togetherjs-share-link");
- var link = $("a.togetherjs-share-link");
- var display = $("#togetherjs-session-id");
- if (! session.shareId) {
- input.val("");
- link.attr("href", "#");
- display.text("(none)");
- } else {
- input.val(session.shareUrl());
- link.attr("href", session.shareUrl());
- display.text(session.shareId);
- }
- }
- session.on("close", function () {
- if($.browser.mobile) {
- // remove bg overlay
- //$(".overlay").remove();
- //after hitting End, reset window draggin
- $("body").css({
- "position": "",
- top: "",
- left: ""
- });
- }
- if (ui.container) {
- ui.container.remove();
- ui.container = null;
- }
- // Clear out any other spurious elements:
- $(".togetherjs").remove();
- var starterButton = $("#togetherjs-starter button");
- starterButton.removeClass("togetherjs-running");
- if (starterButton.attr("data-start-text")) {
- starterButton.text(starterButton.attr("data-start-text"));
- starterButton.attr("data-start-text", "");
- }
- if (TogetherJS.startTarget) {
- var el = $(TogetherJS.startTarget);
- if (el.attr("data-start-togetherjs-html")) {
- el.html(el.attr("data-start-togetherjs-html"));
- }
- el.removeClass("togetherjs-started");
- }
- });
- ui.chat = {
- text: function (attrs) {
- assert(typeof attrs.text == "string");
- assert(attrs.peer);
- assert(attrs.messageId);
- var date = attrs.date || Date.now();
- var lastEl = ui.container.find("#togetherjs-chat .togetherjs-chat-message");
- if (lastEl.length) {
- lastEl = $(lastEl[lastEl.length-1]);
- }
- var lastDate = null;
- if (lastEl) {
- lastDate = parseInt(lastEl.attr("data-date"), 10);
- }
- if (lastEl && lastEl.attr("data-person") == attrs.peer.id &&
- lastDate && date < lastDate + COLLAPSE_MESSAGE_LIMIT) {
- lastEl.attr("data-date", date);
- var content = lastEl.find(".togetherjs-chat-content");
- assert(content.length);
- attrs.text = content.text() + "\n" + attrs.text;
- attrs.messageId = lastEl.attr("data-message-id");
- lastEl.remove();
- }
- var el = templating.sub("chat-message", {
- peer: attrs.peer,
- content: attrs.text,
- date: date
- });
- linkify(el.find(".togetherjs-chat-content"));
- el.attr("data-person", attrs.peer.id)
- .attr("data-date", date)
- .attr("data-message-id", attrs.messageId);
- ui.chat.add(el, attrs.messageId, attrs.notify);
- },
- joinedSession: function (attrs) {
- assert(attrs.peer);
- var date = attrs.date || Date.now();
- var el = templating.sub("chat-joined", {
- peer: attrs.peer,
- date: date
- });
- // FIXME: should bind the notification to the dock location
- ui.chat.add(el, attrs.peer.className("join-message-"), 4000);
- },
- leftSession: function (attrs) {
- assert(attrs.peer);
- var date = attrs.date || Date.now();
- var el = templating.sub("chat-left", {
- peer: attrs.peer,
- date: date,
- declinedJoin: attrs.declinedJoin
- });
- // FIXME: should bind the notification to the dock location
- ui.chat.add(el, attrs.peer.className("join-message-"), 4000);
- },
- system: function (attrs) {
- assert(! attrs.peer);
- assert(typeof attrs.text == "string");
- var date = attrs.date || Date.now();
- var el = templating.sub("chat-system", {
- content: attrs.text,
- date: date
- });
- ui.chat.add(el, undefined, true);
- },
- clear: deferForContainer(function () {
- var container = ui.container.find("#togetherjs-chat-messages");
- container.empty();
- }),
- urlChange: function (attrs) {
- assert(attrs.peer);
- assert(typeof attrs.url == "string");
- assert(typeof attrs.sameUrl == "boolean");
- var messageId = attrs.peer.className("url-change-");
- // FIXME: duplicating functionality in .add():
- var realId = "togetherjs-chat-" + messageId;
- var date = attrs.date || Date.now();
- var title;
- // FIXME: strip off common domain from msg.url? E.g., if I'm on
- // http://example.com/foobar, and someone goes to http://example.com/baz then
- // show only /baz
- // FIXME: truncate long titles
- if (attrs.title) {
- title = attrs.title + " (" + attrs.url + ")";
- } else {
- title = attrs.url;
- }
- var el = templating.sub("url-change", {
- peer: attrs.peer,
- date: date,
- href: attrs.url,
- title: title,
- sameUrl: attrs.sameUrl
- });
- el.find(".togetherjs-nudge").click(function () {
- attrs.peer.nudge();
- return false;
- });
- el.find(".togetherjs-follow").click(function () {
- var url = attrs.peer.url;
- if (attrs.peer.urlHash) {
- url += attrs.peer.urlHash;
- }
- location.href = url;
- });
- var notify = ! attrs.sameUrl;
- if (attrs.sameUrl && ! $("#" + realId).length) {
- // Don't bother showing a same-url notification, if no previous notification
- // had been shown
- return;
- }
- ui.chat.add(el, messageId, notify);
- },
- invite: function (attrs) {
- assert(attrs.peer);
- assert(typeof attrs.url == "string");
- var messageId = attrs.peer.className("invite-");
- var date = attrs.date || Date.now();
- var hrefTitle = attrs.url.replace(/\#?&togetherjs=.*/, "").replace(/^\w+:\/\//, "");
- var el = templating.sub("invite", {
- peer: attrs.peer,
- date: date,
- href: attrs.url,
- hrefTitle: hrefTitle,
- forEveryone: attrs.forEveryone
- });
- if (attrs.forEveryone) {
- el.find("a").click(function () {
- // FIXME: hacky way to do this:
- chat.submit("Followed link to " + attrs.url);
- });
- }
- ui.chat.add(el, messageId, true);
- },
- hideTimeout: null,
- add: deferForContainer(function (el, id, notify) {
- if (id) {
- el.attr("id", "togetherjs-chat-" + util.safeClassName(id));
- }
- var container = ui.container.find("#togetherjs-chat-messages");
- assert(container.length);
- var popup = ui.container.find("#togetherjs-chat-notifier");
- container.append(el);
- ui.chat.scroll();
- var doNotify = !! notify;
- var section = popup.find("#togetherjs-chat-notifier-message");
- if (notify && visibilityApi.hidden()) {
- ui.container.find("#togetherjs-notification")[0].play();
- }
- if (id && section.data("message-id") == id) {
- doNotify = true;
- }
- if (container.is(":visible")) {
- doNotify = false;
- }
- if (doNotify) {
- section.empty();
- section.append(el.clone(true, true));
- if (section.data("message-id") != id) {
- section.data("message-id", id || "");
- windowing.show(popup);
- } else if (! popup.is(":visible")) {
- windowing.show(popup);
- }
- if (typeof notify == "number") {
- // This is the amount of time we're supposed to notify
- if (this.hideTimeout) {
- clearTimeout(this.hideTimeout);
- this.hideTimeout = null;
- }
- this.hideTimeout = setTimeout((function () {
- windowing.hide(popup);
- this.hideTimeout = null;
- }).bind(this), notify);
- }
- }
- }),
- scroll: deferForContainer(function () {
- var container = ui.container.find("#togetherjs-chat-messages")[0];
- container.scrollTop = container.scrollHeight;
- })
- };
- session.on("display-window", function (id, win) {
- if (id == "togetherjs-chat") {
- ui.chat.scroll();
- windowing.hide("#togetherjs-chat-notifier");
- }
- });
- /* This class is bound to peers.Peer instances as peer.view.
- The .update() method is regularly called by peer objects when info changes. */
- ui.PeerView = util.Class({
- constructor: function (peer) {
- assert(peer.isSelf !== undefined, "PeerView instantiated with non-Peer object");
- this.peer = peer;
- this.dockClick = this.dockClick.bind(this);
- },
- /* Takes an element and sets any person-related attributes on the element
- Different from updates, which use the class names we set here: */
- setElement: function (el) {
- var count = 0;
- var classes = ["togetherjs-person", "togetherjs-person-status",
- "togetherjs-person-name", "togetherjs-person-name-abbrev",
- "togetherjs-person-bgcolor", "togetherjs-person-swatch",
- "togetherjs-person-status", "togetherjs-person-role",
- "togetherjs-person-url", "togetherjs-person-url-title",
- "togetherjs-person-bordercolor"];
- classes.forEach(function (cls) {
- var els = el.find("." + cls);
- els.addClass(this.peer.className(cls + "-"));
- count += els.length;
- }, this);
- if (! count) {
- console.warn("setElement(", el, ") doesn't contain any person items");
- }
- this.updateDisplay(el);
- },
- updateDisplay: deferForContainer(function (container) {
- container = container || ui.container;
- var abbrev = this.peer.name;
- if (this.peer.isSelf) {
- abbrev = "me";
- }
- container.find("." + this.peer.className("togetherjs-person-name-")).text(this.peer.name || "");
- container.find("." + this.peer.className("togetherjs-person-name-abbrev-")).text(abbrev);
- var avatarEl = container.find("." + this.peer.className("togetherjs-person-"));
- if (this.peer.avatar) {
- util.assertValidUrl(this.peer.avatar);
- avatarEl.css({
- backgroundImage: "url(" + this.peer.avatar + ")"
- });
- }
- if (this.peer.idle == "inactive") {
- avatarEl.addClass("togetherjs-person-inactive");
- } else {
- avatarEl.removeClass("togetherjs-person-inactive");
- }
- avatarEl.attr("title", this.peer.name);
- if (this.peer.color) {
- avatarEl.css({
- borderColor: this.peer.color
- });
- avatarEl.find(".togetherjs-person-avatar-swatch").css({
- borderTopColor: this.peer.color,
- borderRightColor: this.peer.color
- });
- }
- if (this.peer.color) {
- var colors = container.find("." + this.peer.className("togetherjs-person-bgcolor-"));
- colors.css({
- backgroundColor: this.peer.color
- });
- colors = container.find("." + this.peer.className("togetherjs-person-bordercolor-"));
- colors.css({
- borderColor: this.peer.color
- });
- }
- container.find("." + this.peer.className("togetherjs-person-role-"))
- .text(this.peer.isCreator ? "Creator" : "Participant");
- var urlName = this.peer.title || "";
- if (this.peer.title) {
- urlName += " (";
- }
- urlName += util.truncateCommonDomain(this.peer.url, location.href);
- if (this.peer.title) {
- urlName += ")";
- }
- container.find("." + this.peer.className("togetherjs-person-url-title-"))
- .text(urlName);
- var url = this.peer.url;
- if (this.peer.urlHash) {
- url += this.peer.urlHash;
- }
- container.find("." + this.peer.className("togetherjs-person-url-"))
- .attr("href", url);
- // FIXME: should have richer status:
- container.find("." + this.peer.className("togetherjs-person-status-"))
- .text(this.peer.idle == "active" ? "Active" : "Inactive");
- if (this.peer.isSelf) {
- // FIXME: these could also have consistent/reliable class names:
- var selfName = $(".togetherjs-self-name");
- selfName.each((function (index, el) {
- el = $(el);
- if (el.val() != this.peer.name) {
- el.val(this.peer.name);
- }
- }).bind(this));
- $("#togetherjs-menu-avatar").attr("src", this.peer.avatar);
- if (! this.peer.name) {
- $("#togetherjs-menu .togetherjs-person-name-self").text(this.peer.defaultName);
- }
- }
- if (this.peer.url != session.currentUrl()) {
- container.find("." + this.peer.className("togetherjs-person-"))
- .addClass("togetherjs-person-other-url");
- } else {
- container.find("." + this.peer.className("togetherjs-person-"))
- .removeClass("togetherjs-person-other-url");
- }
- if (this.peer.following) {
- if (this.followCheckbox) {
- this.followCheckbox.prop("checked", true);
- }
- } else {
- if (this.followCheckbox) {
- this.followCheckbox.prop("checked", false);
- }
- }
- // FIXME: add some style based on following?
- updateChatParticipantList();
- this.updateFollow();
- }),
- update: function () {
- if (! this.peer.isSelf) {
- if (this.peer.status == "live") {
- this.dock();
- } else {
- this.undock();
- }
- }
- this.updateDisplay();
- this.updateUrlDisplay();
- },
- updateUrlDisplay: function (force) {
- var url = this.peer.url;
- if ((! url) || (url == this._lastUpdateUrlDisplay && ! force)) {
- return;
- }
- this._lastUpdateUrlDisplay = url;
- var sameUrl = url == session.currentUrl();
- ui.chat.urlChange({
- peer: this.peer,
- url: this.peer.url,
- title: this.peer.title,
- sameUrl: sameUrl
- });
- },
- urlNudge: function () {
- // FIXME: do something more distinct here
- this.updateUrlDisplay(true);
- },
- notifyJoined: function () {
- ui.chat.joinedSession({
- peer: this.peer
- });
- },
- // when there are too many participants in the dock, consolidate the participants to one avatar, and on mouseOver, the dock expands down to reveal the rest of the participants
- // if there are X users in the session
- // then hide the users in the dock
- // and shrink the size of the dock
- // and if you rollover the dock, it expands and reveals the rest of the participants in the dock
- //if users hit X then show the participant button with the consol
- dock: deferForContainer(function () {
- var numberOfUsers = peers.getAllPeers().length;
- // collapse the Dock if too many users
- function CollapsedDock() {
- // decrease/reset dock height
- $("#togetherjs-dock").css("height", 260);
- //replace participant button
- $("#togetherjs-dock-participants").replaceWith("<button id='togetherjs-participantlist-button' class='togetherjs-button'><div class='togetherjs-tooltip togetherjs-dock-person-tooltip'><span class='togetherjs-person-name'>Participants</span><span class='togetherjs-person-tooltip-arrow-r'></span></div><div class='togetherjs-person togetherjs-person-status-overlay' title='Participant List' style='background-image: url("+TogetherJS.baseUrl+"/togetherjs/images/robot-avatar.png); border-color: rgb(255, 0, 0);'></div></button>");
- // new full participant window created on toggle
- $("#togetherjs-participantlist-button").click(function () {
- windowing.toggle("#togetherjs-participantlist");
- });
- }
- // FIXME: turned off for now
- if( numberOfUsers >= 5 && false) {
- CollapsedDock();
- } else {
- // reset
- }
- if (this.dockElement) {
- return;
- }
- this.dockElement = templating.sub("dock-person", {
- peer: this.peer
- });
- this.dockElement.attr("id", this.peer.className("togetherjs-dock-element-"));
- ui.container.find("#togetherjs-dock-participants").append(this.dockElement);
- this.dockElement.find(".togetherjs-person").animateDockEntry();
- adjustDockSize(1);
- this.detailElement = templating.sub("participant-window", {
- peer: this.peer
- });
- var followId = this.peer.className("togetherjs-person-status-follow-");
- this.detailElement.find('[for="togetherjs-person-status-follow"]').attr("for", followId);
- this.detailElement.find('#togetherjs-person-status-follow').attr("id", followId);
- this.detailElement.find(".togetherjs-follow").click(function () {
- location.href = $(this).attr("href");
- });
- this.detailElement.find(".togetherjs-nudge").click((function () {
- this.peer.nudge();
- }).bind(this));
- this.followCheckbox = this.detailElement.find("#" + followId);
- this.followCheckbox.change(function () {
- if (! this.checked) {
- this.peer.unfollow();
- }
- // Following doesn't happen until the window is closed
- // FIXME: should we tell the user this?
- });
- this.maybeHideDetailWindow = this.maybeHideDetailWindow.bind(this);
- session.on("hide-window", this.maybeHideDetailWindow);
- ui.container.append(this.detailElement);
- this.dockElement.click((function () {
- if (this.detailElement.is(":visible")) {
- windowing.hide(this.detailElement);
- } else {
- windowing.show(this.detailElement, {bind: this.dockElement});
- this.scrollTo();
- this.cursor().element.animate({
- opacity:0.3
- }).animate({
- opacity:1
- }).animate({
- opacity:0.3
- }).animate({
- opacity:1
- });
- }
- }).bind(this));
- this.updateFollow();
- }),
- undock: function () {
- if (! this.dockElement) {
- return;
- }
- this.dockElement.animateDockExit().promise().then((function () {
- this.dockElement.remove();
- this.dockElement = null;
- this.detailElement.remove();
- this.detailElement = null;
- adjustDockSize(-1);
- }).bind(this));
- },
- scrollTo: function () {
- if (this.peer.url != session.currentUrl()) {
- return;
- }
- var pos = this.peer.scrollPosition;
- if (! pos) {
- console.warn("Peer has no scroll position:", this.peer);
- return;
- }
- pos = elementFinder.pixelForPosition(pos);
- $("html, body").easeTo(pos);
- },
- updateFollow: function () {
- if (! this.peer.url) {
- return;
- }
- if (! this.detailElement) {
- return;
- }
- var same = this.detailElement.find(".togetherjs-same-url");
- var different = this.detailElement.find(".togetherjs-different-url");
- if (this.peer.url == session.currentUrl()) {
- same.show();
- different.hide();
- } else {
- same.hide();
- different.show();
- }
- },
- maybeHideDetailWindow: function (windows) {
- if (this.detailElement && windows[0] && windows[0][0] === this.detailElement[0]) {
- if (this.followCheckbox[0].checked) {
- this.peer.follow();
- } else {
- this.peer.unfollow();
- }
- }
- },
- dockClick: function () {
- // FIXME: scroll to person
- },
- cursor: function () {
- return require("cursor").getClient(this.peer.id);
- },
- destroy: function () {
- // FIXME: should I get rid of the dockElement?
- session.off("hide-window", this.maybeHideDetailWindow);
- }
- });
- function updateChatParticipantList() {
- var live = peers.getAllPeers(true);
- if (live.length) {
- ui.displayToggle("#togetherjs-chat-participants");
- $("#togetherjs-chat-participant-list").text(
- live.map(function (p) {return p.name;}).join(", "));
- } else {
- ui.displayToggle("#togetherjs-chat-no-participants");
- }
- }
- function inviteHubUrl() {
- var base = TogetherJS.config.get("inviteFromRoom");
- assert(base);
- return util.makeUrlAbsolute(base, session.hubUrl());
- }
- var inRefresh = false;
- function refreshInvite() {
- if (inRefresh) {
- return;
- }
- inRefresh = true;
- require(["who"], function (who) {
- var def = who.getList(inviteHubUrl());
- function addUser(user, before) {
- var item = templating.sub("invite-user-item", {peer: user});
- item.attr("data-clientid", user.id);
- if (before) {
- item.insertBefore(before);
- } else {
- $("#togetherjs-invite-users").append(item);
- }
- item.click(function() {
- invite(user.clientId);
- });
- }
- function refresh(users, finished) {
- var sorted = [];
- for (var id in users) {
- if (users.hasOwnProperty(id)) {
- sorted.push(users[id]);
- }
- }
- sorted.sort(function (a, b) {
- return a.name < b.name ? -1 : 1;
- });
- var pos = 0;
- ui.container.find("#togetherjs-invite-users .togetherjs-menu-item").each(function () {
- var $this = $(this);
- if (finished && ! users[$this.attr("data-clientid")]) {
- $this.remove();
- return;
- }
- if (pos >= sorted.length) {
- return;
- }
- while (pos < sorted.length && $this.attr("data-clientid") !== sorted[pos].id) {
- addUser(sorted[pos], $this);
- pos++;
- }
- while (pos < sorted.length && $this.attr("data-clientid") == sorted[pos].id) {
- pos++;
- }
- });
- for (var i=pos; i<sorted.length; i++) {
- addUser(sorted[pos]);
- }
- }
- def.then(function (users) {
- refresh(users, true);
- inRefresh = false;
- });
- def.progress(refresh);
- });
- }
- session.hub.on("invite", function (msg) {
- if (msg.forClientId && msg.clientId != peers.Self.id) {
- return;
- }
- require(["who"], function (who) {
- var peer = who.ExternalPeer(msg.userInfo.clientId, msg.userInfo);
- ui.chat.invite({peer: peer, url: msg.url, forEveryone: ! msg.forClientId});
- });
- });
- function invite(clientId) {
- require(["who"], function (who) {
- // FIXME: use the return value of this to give a signal that
- // the invite has been successfully sent:
- who.invite(inviteHubUrl(), clientId).then(function () {
- hideMenu();
- });
- });
- }
- ui.showUrlChangeMessage = deferForContainer(function (peer, url) {
- var window = templating.sub("url-change", {peer: peer});
- ui.container.append(window);
- windowing.show(window);
- });
- session.hub.on("url-change-nudge", function (msg) {
- if (msg.to && msg.to != session.clientId) {
- // Not directed to us
- return;
- }
- msg.peer.urlNudge();
- });
- session.on("new-element", function (el) {
- if (TogetherJS.config.get("toolName")) {
- ui.updateToolName(el);
- }
- });
- var setToolName = false;
- ui.updateToolName = function (container) {
- container = container || $(document.body);
- var name = TogetherJS.config.get("toolName");
- if (setToolName && ! name) {
- name = "TogetherJS";
- }
- if (name) {
- container.find(".togetherjs-tool-name").text(name);
- setToolName = true;
- }
- };
- TogetherJS.config.track("toolName", function (name) {
- ui.updateToolName(ui.container);
- });
- return ui;
- });
|