silver%warwickcompsoc.co.uk bcf62b9cbc Bug 269633 - Land ChatZilla 0.9.67. Various changes, many bugs fixed, see bug 269633 for details.
ChatZilla only.
r=samuel@sieb.net


git-svn-id: svn://10.0.0.236/trunk@166871 18797224-902f-48f8-a5cc-f745e15eee43
2004-12-19 22:52:37 +00:00

454 lines
13 KiB
JavaScript

/* ***** 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 James Ross.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Ross, <silver@warwickcompsoc.co.uk>
*
* 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 client;
var network;
var channels = new Array();
var createChannelItem;
var channelTreeShare = new Object();
var channelTreeView;
const colIDToSortKey = { chanColName: "name",
chanColUsers: "users",
chanColTopic: "topic" };
const sortKeyToColID = { name: "chanColName",
users: "chanColUsers",
topic: "chanColTopic" };
function onLoad()
{
function ondblclick(event) { channelTreeView.onRouteDblClick(event); };
function onkeypress(event) { channelTreeView.onRouteKeyPress(event); };
function onfocus(event) { channelTreeView.onRouteFocus(event); };
function onblur(event) { channelTreeView.onRouteBlur(event); };
function doJoin()
{
if (joinChannel())
window.close();
};
client = window.arguments[0].client;
window.toUnicode = client.mainWindow.toUnicode;
window.getMsg = client.mainWindow.getMsg;
window.MSG_CHANNEL_OPENED = client.mainWindow.MSG_CHANNEL_OPENED;
window.MT_INFO = client.mainWindow.MT_INFO;
// Import "MSG_CD_*"...
for (var m in client.mainWindow)
{
if (m.substr(0, 7) == "MSG_CD_")
window[m] = client.mainWindow[m];
}
network = client.mainWindow.getObjectDetails(client.currentObject).network;
var tree = document.getElementById("channelList");
channelTreeView = new XULTreeView(channelTreeShare);
channelTreeView.onRowCommand = doJoin;
channelTreeView.cycleHeader = changeSort;
tree.treeBoxObject.view = channelTreeView;
// Sort by user count, decending.
changeSort("chanColUsers");
tree.addEventListener("dblclick", ondblclick, false);
tree.addEventListener("keypress", onkeypress, false);
tree.addEventListener("focus", onfocus, false);
tree.addEventListener("blur", onblur, false);
createChannelItem = new ChannelEntry("", "", MSG_CD_CREATE);
createChannelItem.first = true;
channelTreeView.childData.appendChild(createChannelItem);
document.title = getMsg(MSG_CD_TITLE, [network.unicodeName,
network.getURL()]);
setTimeout(startListRequest, 100, false);
}
function onKeyPress(event)
{
if (event.keyCode == event.DOM_VK_UP)
{
if (channelTreeView.selectedIndex > 0)
channelTreeView.selectedIndex = channelTreeView.selectedIndex - 1;
event.preventDefault();
}
else if (event.keyCode == event.DOM_VK_DOWN)
{
if (channelTreeView.selectedIndex < channelTreeView.rowCount - 1)
channelTreeView.selectedIndex = channelTreeView.selectedIndex + 1;
event.preventDefault();
}
}
function onSelectionChange()
{
var joinBtn = document.getElementById("joinBtn");
joinBtn.disabled = (channelTreeView.selectedIndex == -1);
}
function runFilter()
{
function process()
{
var exactMatch = null;
var channelText = text;
if (!channelText.match(/^[#&+!]/))
channelText = "#" + channelText;
for (var i = 0; i < channels.length; i++)
{
var match = (channels[i].name.toLowerCase().indexOf(text) != -1) ||
(searchTopics &&
(channels[i].topic.toLowerCase().indexOf(text) != -1));
if (minUsers && (channels[i].users < minUsers))
match = false;
if (maxUsers && (channels[i].users > maxUsers))
match = false;
if (channels[i].isHidden)
{
if (match)
channels[i].unHide();
}
else
{
if (!match)
channels[i].hide();
}
if (match && (channels[i].name.toLowerCase() == channelText))
exactMatch = channels[i];
if ((i % 100) == 0)
updateProgress(MSG_CD_FILTERING, 100 * i / channels.length);
}
updateProgress();
createChannelItem.name = channelText;
var tree = document.getElementById("channelList");
tree.treeBoxObject.invalidateRow(0);
if (exactMatch)
{
if (!createChannelItem.isHidden)
createChannelItem.hide();
channelTreeView.selectedIndex = exactMatch.calculateVisualRow();
}
else
{
if (createChannelItem.isHidden)
createChannelItem.unHide();
if (channelTreeView.selectedIndex == -1)
{
// The special 'create' row is visible, so prefer the first
// real channel over it.
if (channelTreeView.rowCount >= 2)
channelTreeView.selectedIndex = 1;
else if (channelTreeView.rowCount >= 1)
channelTreeView.selectedIndex = 0;
}
}
};
var text = document.getElementById("filterText").value.toLowerCase();
var searchTopics = document.getElementById("searchTopics").checked;
var minUsers = document.getElementById("minUsers").value * 1;
var maxUsers = document.getElementById("maxUsers").value * 1;
if (channels.length > 1000)
updateProgress(getMsg(MSG_CD_FILTERING1, channels.length));
else
updateProgress(getMsg(MSG_CD_FILTERING2, channels.length));
setTimeout(process, 100);
}
function joinChannel()
{
var index = channelTreeView.selectedIndex;
if (index == -1)
return false;
var row = channelTreeView.childData.locateChildByVisualRow(index);
network.dispatch("join", { channelName: row.name });
return true;
}
function focusSearch()
{
document.getElementById("filterText").focus();
}
function refreshList()
{
startListRequest(true);
}
function updateProgress(label, pro)
{
if (label)
{
document.getElementById("loadLabel").value = label;
}
else
{
var msg = getMsg(MSG_CD_SHOWING,
[(channelTreeView.rowCount - (createChannelItem.isHidden ? 0 : 1)),
channels.length]);
document.getElementById("loadLabel").value = msg;
}
var loadBarDeckIndex = ((typeof pro == "undefined") ? 1 : 0);
document.getElementById("loadBarDeck").selectedIndex = loadBarDeckIndex;
if ((typeof pro == "undefined") || (pro == -1))
{
document.getElementById("loadBar").mode = "undetermined";
}
else
{
document.getElementById("loadBar").mode = "determined";
document.getElementById("loadBar").position = pro;
}
}
function changeSort(col)
{
if (typeof col == "object")
col = col.id;
col = colIDToSortKey[col];
// Users default to decending, others accending.
var dir = (col == "users" ? -1 : 1);
if (col == channelTreeShare.sortColumn)
dir = -channelTreeShare.sortDirection;
var colID = sortKeyToColID[channelTreeShare.sortColumn];
var colNode = document.getElementById(colID);
if (colNode)
{
colNode.removeAttribute("sortActive");
colNode.removeAttribute("sortDirection");
}
channelTreeView.childData.setSortColumn(col, dir);
colID = sortKeyToColID[channelTreeShare.sortColumn];
colNode = document.getElementById(colID);
if (colNode)
{
colNode.setAttribute("sortActive", "true");
var sortDir = (dir > 0 ? "ascending" : "descending");
colNode.setAttribute("sortDirection", sortDir);
}
}
function startListRequest(force)
{
if (("_list" in network) && !network._list.done)
{
updateProgress(MSG_CD_WAIT_LIST);
setTimeout(startListRequest, 1000, force);
return;
}
updateProgress(MSG_CD_FETCHING, -1);
document.getElementById("refreshNow").disabled = true;
var file = new LocalFile(network.prefs["logFileName"]);
file.localFile.leafName = "list.txt";
if (file.localFile.exists() && !force)
{
startListFileLoad();
return;
}
network.list("", file.localFile.path);
setTimeout(duringListRequest, 1000);
}
function duringListRequest()
{
var lbl = document.getElementById("loadLabel");
updateProgress(getMsg(MSG_CD_FETCHED, network._list.count), -1);
if (!network._list.done)
setTimeout(duringListRequest, 1000);
else
afterListRequest();
}
function afterListRequest()
{
if ("error" in network._list)
{
updateProgress(MSG_CD_ERROR_LIST);
document.getElementById("refreshNow").disabled = false;
// Can't seem to "undefine" the parameters using the function format.
setTimeout("updateProgress()", 10000);
}
else
{
updateProgress();
startListFileLoad();
}
}
var pendingData;
function startListFileLoad()
{
// Nuke contents.
channelTreeView.selectedIndex = -1;
// Should ideally be calling freeze()/thaw() here, but unfortunately they
// mess up the selection, even if they make this so much faster.
while (channelTreeView.childData.childData.length > 1)
channelTreeView.childData.removeChildAtIndex(1);
// Nuke more stuff.
channels = new Array();
pendingData = "";
// And... here we go.
var file = new LocalFile(network.prefs["logFileName"]);
file.localFile.leafName = "list.txt";
file = new LocalFile(file.localFile, "<");
duringListFileLoad(file);
}
function duringListFileLoad(file)
{
var data = file.read(10000);
pendingData += data;
while (pendingData.indexOf("\n") != -1)
{
var lines = pendingData.split("\n");
pendingData = lines.pop();
for (var i = 0; i < lines.length; i++)
{
var ary = lines[i].match(/^([^ ]+) ([^ ]+) (.*)$/);
if (ary)
{
var chan = new ChannelEntry(toUnicode(ary[1], "UTF-8"), ary[2],
toUnicode(ary[3], "UTF-8"));
channels.push(chan);
}
}
}
updateProgress(getMsg(MSG_CD_LOADED, channels.length), -1);
if (file.inputStream.available() != 0)
setTimeout(duringListFileLoad, 100, file);
else
afterListFileLoad(file);
}
function afterListFileLoad(file)
{
document.getElementById("refreshNow").disabled = false;
if (channels.length > 0)
channelTreeView.childData.appendChildren(channels);
updateProgress();
runFilter();
}
// Tree ChannelEntry objects //
function ChannelEntry(name, users, topic)
{
this.setColumnPropertyName("chanColName", "name");
this.setColumnPropertyName("chanColUsers", "users");
this.setColumnPropertyName("chanColTopic", "topic");
// Nuke color codes and bold etc.
topic = topic.replace(/[\x1F\x02\x0F\x16]/g, "");
topic = topic.replace(/\x03\d{1,2}(?:,\d{1,2})?/g, "");
this.name = name;
this.users = users;
this.topic = topic;
}
ChannelEntry.prototype = new XULTreeViewRecord(channelTreeShare);
ChannelEntry.prototype.sortCompare =
function chanentry_sortcmp(a, b)
{
var sc = a._share.sortColumn;
var sd = a._share.sortDirection;
// Make sure the special 'first' row is always first.
if ("first" in a)
return -1;
if ("first" in b)
return 1;
if (sc == "users")
{
// Force a numeric comparison.
a = 1 * a[sc];
b = 1 * b[sc];
}
else
{
// Case-insensitive, please.
a = a[sc].toLowerCase();
b = b[sc].toLowerCase();
}
if (a < b)
return -1 * sd;
if (a > b)
return 1 * sd;
return 0;
}