RetroZilla/extensions/irc/xul/content/output-window.js
2015-10-20 23:03:22 -04:00

512 lines
14 KiB
JavaScript

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is ChatZilla.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Ginda, <rginda@netscape.com>, original author
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var initialized = false;
var view;
var client;
var mainWindow;
var clickHandler;
var dd;
var getMsg;
var getObjectDetails;
var header = null;
var headers = {
IRCClient: {
prefix: "cli-",
fields: ["container", "netcount", "version-container", "version",
"connectcount"],
update: updateClient
},
IRCNetwork: {
prefix: "net-",
fields: ["container", "url-anchor", "status", "lag"],
update: updateNetwork
},
IRCChannel: {
prefix: "ch-",
fields: ["container", "url-anchor", "modestr", "usercount",
"topicnodes", "topicinput"],
update: updateChannel
},
IRCUser: {
prefix: "usr-",
fields: ["container", "url-anchor", "serverstr", "title",
"descnodes"],
update: updateUser
},
IRCDCCChat: {
prefix: "dcc-chat-",
fields: ["container", "remotestr", "title"],
update: updateDCCChat
},
IRCDCCFileTransfer: {
prefix: "dcc-file-",
fields: ["container", "file", "progress", "progressbar"],
update: updateDCCFile
}
};
var initOutputWindow = stock_initOutputWindow;
function stock_initOutputWindow(newClient, newView, newClickHandler)
{
function initHeader()
{
/* it's better if we wait a half a second before poking at these
* dom nodes. */
setHeaderState(view.prefs["displayHeader"]);
updateHeader();
var div = document.getElementById("messages-outer");
div.removeAttribute("hidden");
window.scrollTo(0, window.document.height);
};
client = newClient;
view = newView;
clickHandler = newClickHandler;
mainWindow = client.mainWindow;
client.messageManager.importBundle(client.defaultBundle, window);
getMsg = mainWindow.getMsg;
getObjectDetails = mainWindow.getObjectDetails;
dd = mainWindow.dd;
// Wheee... localize stuff!
//var nodes = document.getElementsByAttribute("localize", "*");
var nodes = document.getElementsByTagName("*");
for (var i = 0; i < nodes.length; i++)
{
if (nodes[i].hasAttribute("localize"))
{
var msg = nodes[i].getAttribute("localize");
msg = getMsg("msg." + msg);
nodes[i].appendChild(document.createTextNode(msg));
}
}
changeCSS(view.prefs["motif.current"]);
updateMotifSettings();
var output = document.getElementById("output");
output.appendChild(view.messages);
if (view.TYPE in headers)
{
header = cacheNodes(headers[view.TYPE].prefix,
headers[view.TYPE].fields);
header.update = headers[view.TYPE].update;
}
var splash = document.getElementById("splash");
var name;
if ("unicodeName" in view)
name = view.unicodeName;
else
name = view.name;
splash.appendChild(document.createTextNode(name));
setTimeout(initHeader, 500);
initialized = true;
}
function onTopicNodesClick(e)
{
if (!clickHandler(e))
{
if (e.which != 1)
return;
startTopicEdit();
}
e.stopPropagation();
}
function onTopicKeypress(e)
{
switch (e.keyCode)
{
case 13: /* enter */
var topic = header["topicinput"].value;
topic = mainWindow.replaceColorCodes(topic);
view.setTopic(topic);
view.dispatch("focus-input");
break;
case 27: /* esc */
view.dispatch("focus-input");
break;
default:
client.mainWindow.onInputKeyPress(e);
}
}
function startTopicEdit()
{
var me = view.getUser(view.parent.me.unicodeName);
if (!me || (!view.mode.publicTopic && !me.isOp && !me.isHalfOp) ||
!header["topicinput"].hasAttribute("hidden"))
{
return;
}
header["topicinput"].value = mainWindow.decodeColorCodes(view.topic);
header["topicnodes"].setAttribute("hidden", "true")
header["topicinput"].removeAttribute("hidden");
header["topicinput"].focus();
header["topicinput"].selectionStart = 0;
}
function cancelTopicEdit()
{
if (!header["topicnodes"].hasAttribute("hidden"))
return;
header["topicinput"].setAttribute("hidden", "true")
header["topicnodes"].removeAttribute("hidden");
}
function cacheNodes(pfx, ary, nodes)
{
if (!nodes)
nodes = new Object();
for (var i = 0; i < ary.length; ++i)
nodes[ary[i]] = document.getElementById(pfx + ary[i]);
return nodes;
}
function changeCSS(url, id)
{
if (!id)
id = "main-css";
node = document.getElementById(id);
if (!node)
{
node = document.createElement("link");
node.setAttribute("id", id);
node.setAttribute("rel", "stylesheet");
node.setAttribute("type", "text/css");
var head = document.getElementsByTagName("head")[0];
head.appendChild(node);
}
else
{
if (node.getAttribute("href") == url)
return;
}
node.setAttribute("href", url);
window.scrollTo(0, window.document.height);
}
function updateMotifSettings(existingTimeout)
{
// Try... catch with a repeat to cope with the style sheet not being loaded
const TIMEOUT = 100;
try
{
existingTimeout += TIMEOUT;
view.motifSettings = getMotifSettings();
}
catch(ex)
{
if (existingTimeout >= 30000) // Stop after trying for 30 seconds
return;
if (ex.name == "NS_ERROR_DOM_INVALID_ACCESS_ERR") //not ready, try again
setTimeout(updateMotifSettings, TIMEOUT, existingTimeout);
else // something else, panic!
dd(ex);
}
}
function getMotifSettings()
{
var re = new RegExp("czsettings\\.(\\w*)", "i");
var rules = document.getElementById("main-css").sheet.cssRules;
var rv = new Object();
var ary;
// Copy any settings, which are available in the motif using the
// "CZSETTINGS" selector. We only store the regexp match after checking
// the rule type because selectorText is not defined on other rule types.
for (var i = 0; i < rules.length; i++)
{
if ((rules[i].type == CSSRule.STYLE_RULE) &&
((ary = rules[i].selectorText.match(re)) != null))
{
rv[ary[1]] = true;
}
}
return rv;
}
function setText(field, text, checkCondition)
{
if (!header[field].firstChild)
header[field].appendChild(document.createTextNode(""));
if (typeof text != "string")
{
text = MSG_UNKNOWN;
if (checkCondition)
setAttribute(field, "condition", "red");
}
else if (checkCondition)
{
setAttribute(field, "condition", "green");
}
header[field].firstChild.data = text;
}
function setAttribute(field, name, value)
{
if (!value)
value = "true";
header[field].setAttribute(name, value);
}
function removeAttribute(field, name)
{
header[field].removeAttribute(name);
}
function hasAttribute(field, name)
{
header[field].hasAttribute(name);
}
function setHeaderState(state)
{
if (header)
{
if (state)
{
updateHeader();
removeAttribute("container", "hidden");
}
else
{
setAttribute("container", "hidden");
}
}
}
function updateHeader()
{
document.title = view.getURL();
if (!header || hasAttribute("container", "hidden"))
return;
for (var id in header)
{
var value;
if (id == "url-anchor")
{
value = view.getURL();
setAttribute("url-anchor", "href", value);
setText("url-anchor", value);
}
else if (id in view)
{
setText(id, view[id]);
}
}
if (header.update)
header.update();
}
function updateClient()
{
var n = 0, c = 0;
for (name in client.networks)
{
++n;
if (client.networks[name].isConnected())
++c;
}
setAttribute("version-container", "title", client.userAgent);
setAttribute("version-container", "condition", mainWindow.__cz_condition);
setText("version", mainWindow.__cz_version);
setText("netcount", String(n));
setText("connectcount", String(c));
}
function updateNetwork()
{
if (view.state == client.mainWindow.NET_CONNECTING)
{
setText("status", MSG_CONNECTING);
setAttribute("status","condition", "yellow");
removeAttribute("status", "title");
setText("lag", MSG_UNKNOWN);
}
else if (view.isConnected())
{
setText("status", MSG_CONNECTED);
setAttribute("status","condition", "green");
setAttribute("status", "title",
getMsg(MSG_CONNECT_VIA, view.primServ.unicodeName));
if (view.primServ.lag != -1)
setText("lag", getMsg(MSG_FMT_SECONDS, view.primServ.lag));
else
setText("lag", MSG_UNKNOWN);
}
else
{
setText("status", MSG_DISCONNECTED);
setAttribute("status","condition", "red");
removeAttribute("status", "title");
setText("lag", MSG_UNKNOWN);
}
}
function updateChannel()
{
header["topicnodes"].removeChild(header["topicnodes"].firstChild);
if (view.active)
{
var str = view.mode.getModeStr();
if (!str)
str = MSG_NO_MODE;
setText("modestr", str);
setAttribute("modestr", "condition", "green");
setText("usercount", getMsg(MSG_FMT_USERCOUNT,
[view.getUsersLength(), view.opCount,
view.halfopCount, view.voiceCount]));
setAttribute("usercount", "condition", "green");
if (view.topic)
{
var data = getObjectDetails(view);
data.dontLogURLs = true;
var nodes = client.munger.munge(view.topic, null, data);
header["topicnodes"].appendChild(nodes);
}
else
{
setText("topicnodes", MSG_NONE);
}
}
else
{
setText("modestr", MSG_UNKNOWN);
setAttribute("modestr", "condition", "red");
setText("usercount", MSG_UNKNOWN);
setAttribute("usercount", "condition", "red");
setText("topicnodes", MSG_UNKNOWN);
}
}
function updateUser()
{
var source;
if (view.name)
source = "<" + view.name + "@" + view.host + ">";
else
source = MSG_UNKNOWN;
if (view.parent.isConnected)
setText("serverstr", view.connectionHost, true);
else
setText("serverstr", null, true);
setText("title", getMsg(MSG_TITLE_USER, [view.unicodeName, source]));
header["descnodes"].removeChild(header["descnodes"].firstChild);
if (typeof view.desc != "undefined")
{
var data = getObjectDetails(view);
data.dontLogURLs = true;
var nodes = client.munger.munge(view.desc, null, data);
header["descnodes"].appendChild(nodes);
}
else
{
setText("descnodes", "");
}
}
function updateDCCChat()
{
if (view.state.state == 4)
setText("remotestr", view.remoteIP + ":" + view.port, true);
else
setText("remotestr", null, true);
setText("title", getMsg(MSG_TITLE_DCCCHAT, view.user.unicodeName));
}
function updateDCCFile()
{
var pcent = Math.floor(100 * view.position / view.size);
setText("file", view.filename);
setText("progress", getMsg(MSG_DCCFILE_PROGRESS,
[pcent, mainWindow.getSISize(view.position),
mainWindow.getSISize(view.size),
mainWindow.getSISpeed(view.speed)]));
setAttribute("progressbar", "width", pcent + "%");
}