123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /* 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(["jquery", "util", "peers", "session"], function ($, util, peers, session) {
- var assert = util.assert;
- var windowing = util.Module("windowing");
- var $window = $(window);
- // This is also in togetherjs.less, under .togetherjs-animated
- var ANIMATION_DURATION = 1000;
- /* Displays one window. A window must already exist. This hides other windows, and
- positions the window according to its data-bound-to attributes */
- windowing.show = function (element, options) {
- element = $(element);
- options = options || {};
- options.bind = options.bind || element.attr("data-bind-to");
- var notification = element.hasClass("togetherjs-notification");
- var modal = element.hasClass("togetherjs-modal");
- if (options.bind) {
- options.bind = $(options.bind);
- }
- windowing.hide();
- element.stop();
- element.show();
- // In addition to being hidden, the window can be faded out, which we want to undo:
- element.css({opacity: "1"});
- if (options.bind) {
- assert(! modal, "Binding does not currently work with modals");
- bind(element, options.bind);
- }
- if (notification) {
- element.slideIn();
- } else if (! modal) {
- element.popinWindow();
- }
- if (modal) {
- getModalBackground().show();
- modalEscape.bind();
- }
- onClose = options.onClose || null;
- session.emit("display-window", element.attr("id"), element);
- };
- var onClose = null;
- /* Moves a window to be attached to data-bind-to, e.g., the button
- that opened the window. Or you can provide an element that it should bind to. */
- function bind(win, bound) {
- if ($.browser.mobile) {
- return;
- }
- win = $(win);
- assert(bound.length, "Cannot find binding:", bound.selector, "from:", win.selector);
- // FIXME: hardcoding
- var ifacePos = "right";
- //var ifacePos = panelPosition();
- var boundPos = bound.offset();
- boundPos.height = bound.height();
- boundPos.width = bound.width();
- var windowHeight = $window.height();
- boundPos.top -= $window.scrollTop();
- boundPos.left -= $window.scrollLeft();
- // FIXME: I appear to have to add the padding to the width to get a "true"
- // width. But it's still not entirely consistent.
- var height = win.height() + 5;
- var width = win.width() + 20;
- var left, top;
- if (ifacePos == "right") {
- left = boundPos.left - 11 - width;
- top = boundPos.top + (boundPos.height / 2) - (height / 2);
- } else if (ifacePos == "left") {
- left = boundPos.left + boundPos.width + 15;
- top = boundPos.top + (boundPos.height / 2) - (height / 2);
- } else if (ifacePos == "bottom") {
- left = (boundPos.left + boundPos.width / 2) - (width / 2);
- top = boundPos.top - 10 - height;
- }
- top = Math.min(windowHeight - 10 - height, Math.max(10, top));
- win.css({
- top: top + "px",
- left: left + "px"
- });
- if (win.hasClass("togetherjs-window")) {
- $("#togetherjs-window-pointer-right, #togetherjs-window-pointer-left").hide();
- var pointer = $("#togetherjs-window-pointer-" + ifacePos);
- pointer.show();
- if (ifacePos == "right") {
- pointer.css({
- top: boundPos.top + Math.floor(boundPos.height / 2) + "px",
- left: left + win.width() + 9 + "px"
- });
- } else if (ifacePos == "left") {
- pointer.css({
- top: boundPos.top + Math.floor(boundPos.height / 2) + "px",
- left: (left - 5) + "px"
- });
- } else {
- console.warn("don't know how to deal with position:", ifacePos);
- }
- }
- win.data("boundTo", bound.selector || "#" + bound.attr("id"));
- bound.addClass("togetherjs-active");
- }
- session.on("resize", function () {
- var win = $(".togetherjs-modal:visible, .togetherjs-window:visible");
- if (! win.length) {
- return;
- }
- var boundTo = win.data("boundTo");
- if (! boundTo) {
- return;
- }
- boundTo = $(boundTo);
- bind(win, boundTo);
- });
- windowing.hide = function (els) {
- // FIXME: also hide modals?
- els = els || ".togetherjs-window, .togetherjs-modal, .togetherjs-notification";
- els = $(els);
- els = els.filter(":visible");
- els.filter(":not(.togetherjs-notification)").hide();
- getModalBackground().hide();
- var windows = [];
- els.each(function (index, element) {
- element = $(element);
- windows.push(element);
- var bound = element.data("boundTo");
- if (! bound) {
- return;
- }
- bound = $(bound);
- bound.addClass("togetherjs-animated").addClass("togetherjs-color-pulse");
- setTimeout(function () {
- bound.removeClass("togetherjs-color-pulse").removeClass("togetherjs-animated");
- }, ANIMATION_DURATION+10);
- element.data("boundTo", null);
- bound.removeClass("togetherjs-active");
- if (element.hasClass("togetherjs-notification")) {
- element.fadeOut().promise().then(function () {
- this.hide();
- });
- }
- });
- $("#togetherjs-window-pointer-right, #togetherjs-window-pointer-left").hide();
- if (onClose) {
- onClose();
- onClose = null;
- }
- if (windows.length) {
- session.emit("hide-window", windows);
- }
- };
- windowing.showNotification = function (element, options) {
- element = $(element);
- options = options || {};
- assert(false);
- };
- windowing.toggle = function (el) {
- el = $(el);
- if (el.is(":visible")) {
- windowing.hide(el);
- } else {
- windowing.show(el);
- }
- };
- function bindEvents(el) {
- el.find(".togetherjs-close, .togetherjs-dismiss").click(function (event) {
- var w = $(event.target).closest(".togetherjs-window, .togetherjs-modal, .togetherjs-notification");
- windowing.hide(w);
- event.stopPropagation();
- return false;
- });
- }
- function getModalBackground() {
- if (getModalBackground.element) {
- return getModalBackground.element;
- }
- var background = $("#togetherjs-modal-background");
- assert(background.length);
- getModalBackground.element = background;
- background.click(function () {
- windowing.hide();
- });
- return background;
- }
- var modalEscape = {
- bind: function () {
- $(document).keydown(modalEscape.onKeydown);
- },
- unbind: function () {
- $(document).unbind("keydown", modalEscape.onKeydown);
- },
- onKeydown: function (event) {
- if (event.which == 27) {
- windowing.hide();
- }
- }
- };
- session.on("close", function () {
- modalEscape.unbind();
- });
- session.on("new-element", function (el) {
- bindEvents(el);
- });
- return windowing;
- });
|