michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "notification-icon")); michael@0: Social.setErrorListener(this.content, function(aBrowser) { michael@0: aBrowser.webNavigation.loadURI("about:socialerror?mode=compactInfo&origin=" + michael@0: encodeURIComponent(aBrowser.getAttribute("origin")), michael@0: null, null, null, null); michael@0: }); michael@0: if (!this.chatbar) { michael@0: document.getAnonymousElementByAttribute(this, "anonid", "minimize").hidden = true; michael@0: document.getAnonymousElementByAttribute(this, "anonid", "close").hidden = true; michael@0: } michael@0: let contentWindow = this.contentWindow; michael@0: this.addEventListener("DOMContentLoaded", function DOMContentLoaded(event) { michael@0: if (event.target != this.contentDocument) michael@0: return; michael@0: this.removeEventListener("DOMContentLoaded", DOMContentLoaded, true); michael@0: this.isActive = !this.minimized; michael@0: // process this._callbacks, then set to null so the chatbox creator michael@0: // knows to make new callbacks immediately. michael@0: if (this._callbacks) { michael@0: for (let callback of this._callbacks) { michael@0: if (callback) michael@0: callback(contentWindow); michael@0: } michael@0: this._callbacks = null; michael@0: } michael@0: michael@0: // content can send a socialChatActivity event to have the UI update. michael@0: let chatActivity = function() { michael@0: this.setAttribute("activity", true); michael@0: if (this.chatbar) michael@0: this.chatbar.updateTitlebar(this); michael@0: }.bind(this); michael@0: contentWindow.addEventListener("socialChatActivity", chatActivity); michael@0: contentWindow.addEventListener("unload", function unload() { michael@0: contentWindow.removeEventListener("unload", unload); michael@0: contentWindow.removeEventListener("socialChatActivity", chatActivity); michael@0: }); michael@0: }, true); michael@0: if (this.src) michael@0: this.setAttribute("src", this.src); michael@0: ]]> michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "content"); michael@0: michael@0: michael@0: michael@0: michael@0: return this.content.contentWindow; michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: return this.content.contentDocument; michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: return this.getAttribute("minimized") == "true"; michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: if (this.parentNode.nodeName == "chatbar") michael@0: return this.parentNode; michael@0: return null; michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: return this.content.docShell.isActive; michael@0: michael@0: michael@0: this.content.docShell.isActive = !!val; michael@0: michael@0: // let the chat frame know if it is being shown or hidden michael@0: let evt = this.contentDocument.createEvent("CustomEvent"); michael@0: evt.initCustomEvent(val ? "socialFrameShow" : "socialFrameHide", true, true, {}); michael@0: this.contentDocument.documentElement.dispatchEvent(evt); michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: { michael@0: win.document.title = provider.name; michael@0: }); michael@0: } else { michael@0: // attach this chatbox to the topmost browser window michael@0: let findChromeWindowForChats = Cu.import("resource://gre/modules/MozSocialAPI.jsm").findChromeWindowForChats; michael@0: let win = findChromeWindowForChats(); michael@0: let chatbar = win.SocialChatBar.chatbar; michael@0: chatbar.openChat(provider, "about:blank", win => { michael@0: let cb = chatbar.selectedChat; michael@0: this.swapDocShells(cb); michael@0: michael@0: // chatboxForURL is a map of URL -> chatbox used to avoid opening michael@0: // duplicate chat windows. Ensure reattached chat windows aren't michael@0: // registered with about:blank as their URL, otherwise reattaching michael@0: // more than one chat window isn't possible. michael@0: chatbar.chatboxForURL.delete("about:blank"); michael@0: chatbar.chatboxForURL.set(this.src, Cu.getWeakReference(cb)); michael@0: michael@0: chatbar.focus(); michael@0: this.close(); michael@0: }); michael@0: } michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: if (this.chatbar) michael@0: this.chatbar.selectedChat = this; michael@0: michael@0: michael@0: michael@0: michael@0: if (this.isActive == this.minimized) michael@0: this.isActive = !this.minimized; michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: // to avoid reflows we cache the width of the nub. michael@0: this.cachedWidthNub = 0; michael@0: this._selectedChat = null; michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "innerbox"); michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "nubMenu"); michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "nub"); michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: new WeakMap() michael@0: new Map(); michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: as it michael@0: // must exist before the (possibly delayed) bindings are created. michael@0: cb._callbacks = [aCallback]; michael@0: // src also a javascript property; the src attribute is set in the ctor. michael@0: cb.src = aURL; michael@0: if (aMode == "minimized") michael@0: cb.setAttribute("minimized", "true"); michael@0: cb.setAttribute("origin", aProvider.origin); michael@0: this.insertBefore(cb, this.firstChild); michael@0: this.selectedChat = cb; michael@0: this.chatboxForURL.set(aURL, Cu.getWeakReference(cb)); michael@0: this.resize(); michael@0: ]]> michael@0: michael@0: michael@0: michael@0: availWidth) { michael@0: // we need to collapse some. michael@0: let toCollapse = []; michael@0: for (let child of this.collapsibleChildren) { michael@0: if (currentWidth <= availWidth) michael@0: break; michael@0: toCollapse.push(child); michael@0: currentWidth -= this.getTotalChildWidth(child); michael@0: } michael@0: if (toCollapse.length) { michael@0: for (let child of toCollapse) michael@0: this.collapseChat(child); michael@0: } michael@0: } else if (currentWidth < availWidth) { michael@0: // we *might* be able to expand some - see how many. michael@0: // XXX - if this was clever, it could know when removing the nub michael@0: // leaves enough space to show all collapsed michael@0: let toShow = []; michael@0: for (let child of this.collapsedChildren) { michael@0: currentWidth += this.getTotalChildWidth(child); michael@0: if (currentWidth > availWidth) michael@0: break; michael@0: toShow.push(child); michael@0: } michael@0: for (let child of toShow) michael@0: this._showChat(child); michael@0: michael@0: // If none remain collapsed remove the nub. michael@0: if (!this.hasCollapsedChildren) { michael@0: this.nub.collapsed = true; michael@0: } michael@0: } michael@0: // else: achievement unlocked - we are pixel-perfect! michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: { michael@0: win.document.title = provider.name; michael@0: }); michael@0: michael@0: event.stopPropagation(); michael@0: ]]> michael@0: michael@0: michael@0: michael@0: