Template/Update (Part 47)

* split global.js into its components, so it can be reasonably processed by setup
 * make reputation requirements configurable
 * move Markup and Locale back into global.js (removed associated build scripts)
 * extend Icon to display iconId in lightbox popup
This commit is contained in:
Sarjuuk
2025-08-11 16:00:18 +02:00
parent a48e94cd8b
commit 6557e70d5c
73 changed files with 26256 additions and 25699 deletions

3
.gitignore vendored
View File

@@ -11,8 +11,7 @@
# generated files
/static/js/profile_all.js
/static/js/locale.js
/static/js/Markup.js
/static/js/global.js
/static/widgets/power.js
/static/widgets/power/demo.html
/static/widgets/searchbox.js

View File

@@ -19,8 +19,6 @@ class ClassBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 12];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
public int $type = Type::CHR_CLASS;
public int $typeId = 0;
public ?string $expansion = null;

View File

@@ -20,7 +20,6 @@ class CompareBaseResponse extends TemplateResponse
[SC_JS_FILE, 'js/Draggable.js'],
[SC_JS_FILE, 'js/filters.js'],
[SC_JS_FILE, 'js/Summary.js'],
[SC_JS_FILE, 'js/swfobject.js'],
[SC_CSS_FILE, 'css/Summary.css']
);
protected array $expectedGET = array(

View File

@@ -0,0 +1,29 @@
<?php
namespace Aowow;
if (!defined('AOWOW_REVISION'))
die('illegal access');
class IconGetidfromnameResponse extends TextResponse
{
protected array $expectedGET = array(
'name' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => '/^[\w_-]+$/']]
);
protected function generate() : void
{
if (!$this->assertGET('name'))
{
$this->result = 'null';
return;
}
$this->result = 0;
if ($id = DB::Aowow()->selectCell('SELECT `id` FROM ?_icons WHERE `name` = ?', $this->_get['name']))
$this->result = $id;
}
}
?>

View File

@@ -18,7 +18,6 @@ class ItemBaseResponse extends TemplateResponse implements ICache
protected array $breadcrumb = [0, 0];
protected array $scripts = array(
[SC_JS_FILE, 'js/swfobject.js'],
[SC_JS_FILE, 'js/profile.js'],
[SC_JS_FILE, 'js/filters.js']
);

View File

@@ -19,7 +19,7 @@ class ItemsBaseResponse extends TemplateResponse implements ICache
protected array $breadcrumb = [0, 0];
protected array $dataLoader = ['weight-presets'];
protected array $scripts = [[SC_JS_FILE, 'js/filters.js'], [SC_JS_FILE, 'js/swfobject.js']];
protected array $scripts = [[SC_JS_FILE, 'js/filters.js']];
protected array $expectedGET = array(
'filter' => ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => Filter::PATTERN_PARAM]]
);

View File

@@ -17,7 +17,7 @@ class ItemsetBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 2];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js'], [SC_JS_FILE, 'js/Summary.js']];
protected array $scripts = [[SC_JS_FILE, 'js/Summary.js']];
public int $type = Type::ITEMSET;
public int $typeId = 0;

View File

@@ -17,7 +17,7 @@ class NpcBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 4];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js'], [SC_CSS_FILE, 'css/Profiler.css']];
protected array $scripts = [[SC_CSS_FILE, 'css/Profiler.css']];
public int $type = Type::NPC;
public int $typeId = 0;

View File

@@ -17,8 +17,6 @@ class ObjectBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 5];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
public int $type = Type::OBJECT;
public int $typeId = 0;
public ?Book $book = null;

View File

@@ -17,8 +17,6 @@ class PetBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 8];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
public int $type = Type::PET;
public int $typeId = 0;
public ?string $expansion = null;

View File

@@ -19,7 +19,6 @@ class PetcalcBaseResponse extends TemplateResponse
[SC_CSS_FILE, 'css/talentcalc.css'],
[SC_CSS_FILE, 'css/talent.css'],
[SC_JS_FILE, 'js/petcalc.js'],
[SC_JS_FILE, 'js/swfobject.js'],
[SC_CSS_FILE, 'css/petcalc.css']
);

View File

@@ -19,7 +19,6 @@ class ProfileBaseResponse extends TemplateResponse
protected array $scripts = array(
[SC_JS_FILE, 'js/filters.js'],
[SC_JS_FILE, 'js/TalentCalc.js'],
[SC_JS_FILE, 'js/swfobject.js'],
[SC_JS_FILE, 'js/profile_all.js'],
[SC_JS_FILE, 'js/profile.js'],
[SC_JS_FILE, 'js/Profiler.js'],

View File

@@ -23,8 +23,6 @@ class RaceBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 13];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
public int $type = Type::CHR_RACE;
public int $typeId = 0;
public ?string $expansion = null;

View File

@@ -23,7 +23,6 @@ class SearchBaseResponse extends TemplateResponse implements ICache
protected string $pageName = 'search';
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
protected array $expectedGET = array(
'search' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine']]
);

View File

@@ -23,8 +23,6 @@ class SpellBaseResponse extends TemplateResponse implements ICache
protected ?int $activeTab = parent::TAB_DATABASE;
protected array $breadcrumb = [0, 1];
protected array $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
public int $type = Type::SPELL;
public int $typeId = 0;
public array $reagents = [false, null];

View File

@@ -48,17 +48,17 @@ class Cfg
private static $isLoaded = false;
private static $rebuildScripts = array(
// 'rep_req_border_unco' => ['global'], // currently not a template or buildScript
// 'rep_req_border_rare' => ['global'],
// 'rep_req_border_epic' => ['global'],
// 'rep_req_border_lege' => ['global'],
'rep_req_border_uncommon' => ['globaljs'],
'rep_req_border_rare' => ['globaljs'],
'rep_req_border_epic' => ['globaljs'],
'rep_req_border_legendary' => ['globaljs'],
'profiler_enable' => ['realms', 'realmMenu'],
'battlegroup' => ['realms', 'realmMenu'],
'name_short' => ['searchplugin', 'searchboxBody', 'searchboxScript', 'demo'],
'site_host' => ['searchplugin', 'searchboxBody', 'searchboxScript', 'demo', 'power'],
'static_host' => ['searchplugin', 'searchboxBody', 'searchboxScript', 'power'],
'contact_email' => ['markup'],
'locales' => ['locales']
'contact_email' => ['globaljs'],
'locales' => ['globaljs']
);
public static function load() : void
@@ -294,16 +294,16 @@ class Cfg
yield $k => self::$store[$k];
}
public static function applyToString(string $string) : string
public static function applyToString(string $string, bool $nf = true) : string
{
return preg_replace_callback(
['/CFG_([A-Z_]+)/', '/((HOST|STATIC)_URL)/'],
function ($m) {
function ($m) use ($nf) {
if (!isset(self::$store[strtolower($m[1])]))
return $m[1];
[$val, $flags, , , ] = self::$store[strtolower($m[1])];
return $flags & (self::FLAG_TYPE_FLOAT | self::FLAG_TYPE_INT) ? Lang::nf($val) : $val;
return ($flags & (self::FLAG_TYPE_FLOAT | self::FLAG_TYPE_INT)) && $nf ? Lang::nf($val) : $val;
},
$string
);

View File

@@ -111,8 +111,6 @@ class TemplateResponse extends BaseResponse
[SC_JS_FILE, 'widgets/power.js', SC_FLAG_NO_TIMESTAMP | SC_FLAG_APPEND_LOCALE],
[SC_JS_FILE, 'js/locale_%s.js', SC_FLAG_LOCALIZED ],
[SC_JS_FILE, 'js/global.js' ],
[SC_JS_FILE, 'js/locale.js' ],
[SC_JS_FILE, 'js/Markup.js' ],
[SC_CSS_FILE, 'css/basic.css' ],
[SC_CSS_FILE, 'css/global.css' ],
[SC_CSS_FILE, 'css/aowow.css' ],

View File

@@ -9,8 +9,6 @@ if (!CLI)
die('not in cli mode');
// Create 'locale.js'-file in static/js
/*
0: { // English
id: LOCALE_ENUS,
@@ -55,11 +53,13 @@ CLISetup::registerSetup("build", new class extends SetupScript
use TrTemplateFile;
protected $info = array(
'locales' => [[], CLISetup::ARGV_PARAM, 'Compiles the Locale Object (static/js/locale.js) with available languages.']
'globaljs' => [[], CLISetup::ARGV_PARAM, 'Compiles the global javascript file (static/js/global.js).']
);
protected $fileTemplateDest = ['static/js/locale.js'];
protected $fileTemplateSrc = ['locale.js.in'];
protected $fileTemplateDest = ['static/js/global.js'];
protected $fileTemplateSrc = ['global.js'];
private bool $numFmt = false;
private function locales() : string
{

View File

@@ -1,24 +0,0 @@
<?php
namespace Aowow;
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
CLISetup::registerSetup("build", new class extends SetupScript
{
use TrTemplateFile;
protected $info = array(
'markup' => [[], CLISetup::ARGV_PARAM, 'Fills the markup parser (static/js/Markup.js) with site variables.']
);
protected $fileTemplateSrc = ['Markup.js.in'];
protected $fileTemplateDest = ['static/js/Markup.js'];
});
?>

View File

@@ -0,0 +1,73 @@
// Needed for IE because it's dumb
'abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video'.replace(/\w+/g,function(n){document.createElement(n)})
/*
User-related functions
TODO: Move global variables/functions into User class
*/
// IMPORTANT: If you update/change the permission groups below make sure to also update them in User.inc.php!
/*********/
/* ROLES */
/*********/
var U_GROUP_TESTER = 0x1;
var U_GROUP_ADMIN = 0x2;
var U_GROUP_EDITOR = 0x4;
var U_GROUP_MOD = 0x8;
var U_GROUP_BUREAU = 0x10;
var U_GROUP_DEV = 0x20;
var U_GROUP_VIP = 0x40;
var U_GROUP_BLOGGER = 0x80;
var U_GROUP_PREMIUM = 0x100;
var U_GROUP_LOCALIZER = 0x200;
var U_GROUP_SALESAGENT = 0x400;
var U_GROUP_SCREENSHOT = 0x800;
var U_GROUP_VIDEO = 0x1000;
var U_GROUP_APIONLY = 0x2000;
var U_GROUP_PENDING = 0x4000;
/******************/
/* ROLE SHORTCUTS */
/******************/
var U_GROUP_STAFF = U_GROUP_ADMIN | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_BLOGGER | U_GROUP_LOCALIZER | U_GROUP_SALESAGENT;
var U_GROUP_EMPLOYEE = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV;
var U_GROUP_GREEN_TEXT = U_GROUP_MOD | U_GROUP_BUREAU | U_GROUP_DEV;
var U_GROUP_PREMIUMISH = U_GROUP_PREMIUM | U_GROUP_EDITOR;
var U_GROUP_MODERATOR = U_GROUP_ADMIN | U_GROUP_MOD | U_GROUP_BUREAU;
var U_GROUP_COMMENTS_MODERATOR = U_GROUP_BUREAU | U_GROUP_MODERATOR | U_GROUP_LOCALIZER;
var U_GROUP_PREMIUM_PERMISSIONS = U_GROUP_PREMIUM | U_GROUP_STAFF | U_GROUP_VIP;
var g_users = {};
var g_favorites = [];
var g_customColors = {};
function g_isUsernameValid(username) {
return (username.match(/[^a-z0-9]/i) == null && username.length >= 4 && username.length <= 16);
}
var User = new function() {
var self = this;
/**********/
/* PUBLIC */
/**********/
self.hasPermissions = function(roles)
{
if(!roles)
return true;
return !!(g_user.roles & roles);
}
/**********/
/* PRIVATE */
/**********/
};

View File

@@ -0,0 +1,51 @@
function Ajax(url, opt)
{
if (!url)
return;
var _;
try { _ = new XMLHttpRequest() } catch (e)
{
try { _ = new ActiveXObject("Msxml2.XMLHTTP") } catch (e)
{
try { _ = new ActiveXObject("Microsoft.XMLHTTP") } catch (e)
{
if (window.createRequest)
_ = window.createRequest();
else
{
alert(LANG.message_ajaxnotsupported);
return;
}
}
}
}
this.request = _;
$WH.cO(this, opt);
this.method = this.method || (this.params && 'POST') || 'GET';
_.open(this.method, url, this.async == null ? true : this.async);
_.onreadystatechange = Ajax.onReadyStateChange.bind(this);
if (this.method.toUpperCase() == 'POST')
_.setRequestHeader('Content-Type', (this.contentType || 'application/x-www-form-urlencoded') + '; charset=' + (this.encoding || 'UTF-8'));
_.send(this.params);
}
Ajax.onReadyStateChange = function()
{
if (this.request.readyState == 4)
{
if (this.request.status == 0 || (this.request.status >= 200 && this.request.status < 300))
this.onSuccess != null && this.onSuccess(this.request, this);
else
this.onFailure != null && this.onFailure(this.request, this);
if (this.onComplete != null)
this.onComplete(this.request, this);
}
};

View File

@@ -0,0 +1,123 @@
/*
* jQuery Color Animations
* Copyright 2007 John Resig
* Released under the MIT and GPL licenses.
*/
(function(jQuery){
// We override the animation for all of these color styles
jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
jQuery.fx.step[attr] = function(fx){
if ( fx.state == 0 ) {
fx.start = getColor( fx.elem, attr );
fx.end = getRGB( fx.end );
}
fx.elem.style[attr] = "rgb(" + [
Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
].join(",") + ")";
}
});
// Color Conversion functions from highlightFade
// By Blair Mitchelmore
// http://jquery.offput.ca/highlightFade/
// Parse strings looking for color tuples [255,255,255]
function getRGB(color) {
var result;
// Check if we're already dealing with an array of colors
if ( color && color.constructor == Array && color.length == 3 )
return color;
// Look for rgb(num,num,num)
if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
// Look for rgb(num%,num%,num%)
if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
// Look for #a0b1c2
if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
// Look for #fff
if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
// Otherwise, we're most likely dealing with a named color
return colors[jQuery.trim(color).toLowerCase()];
}
function getColor(elem, attr) {
var color;
do {
color = jQuery.curCSS(elem, attr);
// Keep going until we find an element that has color, or we hit the body
if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") )
break;
attr = "backgroundColor";
} while ( elem = elem.parentNode );
return getRGB(color);
};
// Some named colors to work with
// From Interface by Stefan Petre
// http://interface.eyecon.ro/
var colors = {
aqua:[0,255,255],
azure:[240,255,255],
beige:[245,245,220],
black:[0,0,0],
blue:[0,0,255],
brown:[165,42,42],
cyan:[0,255,255],
darkblue:[0,0,139],
darkcyan:[0,139,139],
darkgrey:[169,169,169],
darkgreen:[0,100,0],
darkkhaki:[189,183,107],
darkmagenta:[139,0,139],
darkolivegreen:[85,107,47],
darkorange:[255,140,0],
darkorchid:[153,50,204],
darkred:[139,0,0],
darksalmon:[233,150,122],
darkviolet:[148,0,211],
fuchsia:[255,0,255],
gold:[255,215,0],
green:[0,128,0],
indigo:[75,0,130],
khaki:[240,230,140],
lightblue:[173,216,230],
lightcyan:[224,255,255],
lightgreen:[144,238,144],
lightgrey:[211,211,211],
lightpink:[255,182,193],
lightyellow:[255,255,224],
lime:[0,255,0],
magenta:[255,0,255],
maroon:[128,0,0],
navy:[0,0,128],
olive:[128,128,0],
orange:[255,165,0],
pink:[255,192,203],
purple:[128,0,128],
violet:[128,0,128],
red:[255,0,0],
silver:[192,192,192],
white:[255,255,255],
yellow:[255,255,0]
};
})(jQuery);

View File

@@ -0,0 +1,157 @@
var Announcement = function(opt)
{
if (!opt)
opt = {};
$WH.cO(this, opt);
if (this.parent)
this.parentDiv = $WH.ge(this.parent);
else
return;
if (g_user.id > 0 && (!g_cookiesEnabled() || g_getWowheadCookie('announcement-' + this.id) == 'closed'))
return;
this.initialize();
};
Announcement.prototype = {
initialize: function()
{
// aowow - animation fix
// this.parentDiv.style.display = 'none';
this.parentDiv.style.opacity = '0';
if (this.mode === undefined || this.mode == 1)
this.parentDiv.className = 'announcement announcement-contenttop';
else
this.parentDiv.className = 'announcement announcement-pagetop';
var div = this.innerDiv = $WH.ce('div');
div.className = 'announcement-inner text';
this.setStyle(this.style);
var a = null;
var id = parseInt(this.id);
if (g_user && (g_user.roles & (U_GROUP_ADMIN|U_GROUP_BUREAU)) > 0 && Math.abs(id) > 0)
{
if (id < 0)
{
a = $WH.ce('a');
a.style.cssFloat = a.style.styleFloat = 'right';
a.href = '?admin=announcements&id=' + Math.abs(id) + '&status=2';
a.onclick = function() { return confirm('Are you sure you want to delete ' + this.name + '?'); };
$WH.ae(a, $WH.ct('Delete'));
var small = $WH.ce('small');
$WH.ae(small, a);
$WH.ae(div, small);
a = $WH.ce('a');
a.style.cssFloat = a.style.styleFloat = 'right';
a.style.marginRight = '10px';
a.href = '?admin=announcements&id=' + Math.abs(id) + '&status=' + (this.status == 1 ? 0 : 1);
a.onclick = function() { return confirm('Are you sure you want to delete ' + this.name + '?'); };
$WH.ae(a, $WH.ct((this.status == 1 ? 'Disable' : 'Enable')));
var small = $WH.ce('small');
$WH.ae(small, a);
$WH.ae(div, small);
}
a = $WH.ce('a');
a.style.cssFloat = a.style.styleFloat = 'right';
a.style.marginRight = '22px';
a.href = '?admin=announcements&id=' + Math.abs(id) + '&edit';
$WH.ae(a, $WH.ct('Edit announcement'));
var small = $WH.ce('small');
$WH.ae(small, a);
$WH.ae(div, small);
}
var markupDiv = $WH.ce('div');
markupDiv.id = this.parent + '-markup';
$WH.ae(div, markupDiv);
if (id >= 0)
{
a = $WH.ce('a');
a.id = 'closeannouncement';
a.href = 'javascript:;';
a.className = 'announcement-close';
if (this.nocookie)
a.onclick = this.hide.bind(this);
else
a.onclick = this.markRead.bind(this);
$WH.ae(div, a);
g_addTooltip(a, LANG.close);
}
$WH.ae(div, $WH.ce('div', { style: { clear: 'both' } }));
$WH.ae(this.parentDiv, div);
this.setText(this.text);
setTimeout(this.show.bind(this), 500); // Delay to avoid visual lag
},
show: function()
{
// $(this.parentDiv).animate({
// opacity: 'show',
// height: 'show'
// },{
// duration: 333
// });
// aowow - animation fix - jQuery.animate hard snaps into place after half the time passed
this.parentDiv.style.opacity = '100';
this.parentDiv.style.height = (this.parentDiv.offsetHeight + 10) + 'px';
g_trackEvent('Announcements', 'Show', '' + this.name);
},
hide: function()
{
// $(this.parentDiv).animate({
// opacity: 'hide',
// height: 'hide'
// },{
// duration: 200
// });
// aowow - animation fix - jQuery.animate hard snaps into place after half the time passed
this.parentDiv.style.opacity = '0';
this.parentDiv.style.height = '0px';
setTimeout(function() {
this.parentDiv.style.display = 'none';
}.bind(this), 400);
},
markRead: function()
{
g_trackEvent('Announcements', 'Close', '' + this.name);
g_setWowheadCookie('announcement-' + this.id, 'closed');
this.hide();
},
setStyle: function(style)
{
this.style = style;
this.innerDiv.setAttribute('style', style);
},
setText: function(text)
{
this.text = text;
Markup.printHtml(this.text, this.parent + '-markup');
g_addAnalyticsToNode($WH.ge(this.parent + '-markup'), {
'category': 'Announcements',
'actions': {
'Follow link': function(node) { return true; }
}
}, this.id);
}
};

View File

@@ -0,0 +1,377 @@
var g_audiocontrols = {
__windowloaded: false,
};
var g_audioplaylist = {};
// aowow - why is window.JSON here, wedged between the audio controls. It's only used for SearchBrowseButtons (and sourced by Listview)
if (!window.JSON) {
window.JSON = {
parse: function (sJSON) {
return eval("(" + sJSON + ")");
},
stringify: function (obj) {
if (obj instanceof Object)
{
var str = '';
if (obj.constructor === Array)
{
for (var i = 0; i < obj.length; str += this.stringify(obj[i]) + ',', i++) {}
return '[' + str.substr(0, str.length - 1) + ']';
}
if (obj.toString !== Object.prototype.toString)
return '"' + obj.toString().replace(/"/g, '\\$&') + '"';
for (var e in obj)
str += '"' + e.replace(/"/g, '\\$&') + '":' + this.stringify(obj[e]) + ',';
return '{' + str.substr(0, str.length - 1) + '}';
}
return typeof obj === 'string' ? '"' + obj.replace(/"/g, '\\$&') + '"' : String(obj);
}
}
}
AudioControls = function ()
{
var fileIdx = -1;
var canPlay = false;
var looping = false;
var fullPlayer = false;
var autoStart = false;
var controls = {};
var playlist = [];
var url = '';
function updatePlayer(_self, itr, doPlay)
{
var elAudio = $WH.ce('audio');
elAudio.preload = 'none';
elAudio.controls = 'true';
$(elAudio).click(function (s) { s.stopPropagation() });
elAudio.style.marginTop = '5px';
controls.audio.parentNode.replaceChild(elAudio, controls.audio);
controls.audio = elAudio;
$WH.aE(controls.audio, 'ended', setNextTrack.bind(_self));
if (doPlay)
{
elAudio.preload = 'auto';
autoStart = true;
$WH.aE(controls.audio, 'canplaythrough', autoplay.bind(this));
}
if (!canPlay)
controls.table.style.visibility = 'visible';
var file;
do
{
fileIdx += itr;
if (fileIdx > playlist.length - 1)
{
fileIdx = 0;
if (!canPlay)
{
var div = $WH.ce('div');
// div.className = 'minibox'; Aowow custom
div.className = 'minibox minibox-left';
$WH.st(div, $WH.sprintf(LANG.message_browsernoaudio, file.type));
controls.table.parentNode.replaceChild(div, controls.table);
return
}
}
if (fileIdx < 0)
fileIdx = playlist.length - 1;
file = playlist[fileIdx];
}
while (controls.audio.canPlayType(file.type) == '');
var elSource = $WH.ce('source');
elSource.src = file.url;
elSource.type = file.type;
$WH.ae(controls.audio, elSource);
if (controls.hasOwnProperty('title'))
{
if (url)
{
$WH.ee(controls.title);
var a = $WH.ce('a');
a.href = url;
$WH.st(a, '"' + file.title + '"');
$WH.ae(controls.title, a);
}
else
$WH.st(controls.title, '"' + file.title + '"');
}
if (controls.hasOwnProperty('trackdisplay'))
$WH.st(controls.trackdisplay, '' + (fileIdx + 1) + ' / ' + playlist.length);
if (!canPlay)
{
canPlay = true;
for (var i = fileIdx + 1; i <= playlist.length - 1; i++)
{
if (controls.audio.canPlayType(playlist[i].type))
{
$(controls.controlsdiv).children('a').removeClass('button-red-disabled');
break;
}
}
}
if (controls.hasOwnProperty('addbutton'))
{
$(controls.addbutton).removeClass('button-red-disabled');
// $WH.st(controls.addbutton, LANG.add); Aowow: doesnt work with RedButtons
RedButton.setText(controls.addbutton, LANG.add);
}
}
function autoplay()
{
if (!autoStart)
return;
autoStart = false;
controls.audio.play();
}
this.init = function (files, parent, opt)
{
if (!$WH.is_array(files))
return;
if (files.length == 0)
return;
if ((parent.id == '') || g_audiocontrols.hasOwnProperty(parent.id))
{
var i = 0;
while (g_audiocontrols.hasOwnProperty('auto-audiocontrols-' + (++i))) {}
parent.id = 'auto-audiocontrols-' + i;
}
g_audiocontrols[parent.id] = this;
if (typeof opt == 'undefined')
opt = {};
looping = !!opt.loop;
if (opt.hasOwnProperty('url'))
url = opt.url;
playlist = files;
controls.div = parent;
if (!opt.listview)
{
var tbl = $WH.ce('table', { className: 'audio-controls' });
controls.table = tbl;
controls.table.style.visibility = 'hidden';
$WH.ae(controls.div, tbl);
var tr = $WH.ce('tr');
$WH.ae(tbl, tr);
var td = $WH.ce('td');
$WH.ae(tr, td);
controls.audio = $WH.ce('div');
$WH.ae(td, controls.audio);
controls.title = $WH.ce('div', { className: 'audio-controls-title' });
$WH.ae(td, controls.title);
controls.controlsdiv = $WH.ce('div', { className: 'audio-controls-pagination' });
$WH.ae(td, controls.controlsdiv);
var prevBtn = createButton(LANG.previous, true);
$WH.ae(controls.controlsdiv, prevBtn);
$WH.aE(prevBtn, 'click', this.btnPrevTrack.bind(this));
controls.trackdisplay = $WH.ce('div', { className: 'audio-controls-pagination-track' });
$WH.ae(controls.controlsdiv, controls.trackdisplay);
var nextBtn = createButton(LANG.next, true);
$WH.ae(controls.controlsdiv, nextBtn);
$WH.aE(nextBtn, 'click', this.btnNextTrack.bind(this))
}
else
{
fullPlayer = true;
var div = $WH.ce('div');
controls.table = div;
$WH.ae(controls.div, div);
controls.audio = $WH.ce('div');
$WH.ae(div, controls.audio);
controls.trackdisplay = opt.trackdisplay;
controls.controlsdiv = $WH.ce('span');
$WH.ae(div, controls.controlsdiv);
}
if (g_audioplaylist.isEnabled() && !opt.fromplaylist)
{
var addBtn = createButton(LANG.add);
$WH.ae(controls.controlsdiv, addBtn);
$WH.aE(addBtn, 'click', this.btnAddToPlaylist.bind(this, addBtn));
controls.addbutton = addBtn;
if (fullPlayer)
addBtn.style.verticalAlign = '50%';
}
if (g_audiocontrols.__windowloaded)
this.btnNextTrack();
};
function setNextTrack()
{
updatePlayer(this, 1, (looping || (fileIdx < (playlist.length - 1))));
}
this.btnNextTrack = function ()
{
updatePlayer(this, 1, (canPlay && (controls.audio.readyState > 1) && (!controls.audio.paused)));
};
this.btnPrevTrack = function ()
{
updatePlayer(this, -1, (canPlay && (controls.audio.readyState > 1) && (!controls.audio.paused)));
};
this.btnAddToPlaylist = function (_self)
{
if (fullPlayer)
{
for (var i = 0; i < playlist.length; i++)
g_audioplaylist.addSound(playlist[i]);
}
else
g_audioplaylist.addSound(playlist[fileIdx]);
_self.className += ' button-red-disabled';
// $WH.st(_self, LANG.added); // Aowow doesn't work with RedButtons
RedButton.setText(_self, LANG.added);
};
this.isPlaying = function ()
{
return !controls.audio.paused;
};
this.removeSelf = function ()
{
controls.table.parentNode.removeChild(controls.table);
delete g_audiocontrols[controls.div];
};
function createButton(text, disabled)
{
return $WH.g_createButton(text, null, {
disabled: disabled,
// 'float': false, Aowow - adapted style
// style: 'margin:0 12px; display:inline-block'
style: 'margin:0 12px; display:inline-block; float:inherit; '
});
}
};
$WH.aE(window, 'load', function ()
{
g_audiocontrols.__windowloaded = true;
for (var i in g_audiocontrols)
if (i.substr(0, 2) != '__')
g_audiocontrols[i].btnNextTrack();
});
AudioPlaylist = function ()
{
var enabled = false;
var playlist = [];
var player, container;
this.init = function ()
{
if (!$WH.localStorage.isSupported())
return;
enabled = true;
var tracks;
if (tracks = $WH.localStorage.get('AudioPlaylist'))
playlist = JSON.parse(tracks);
};
this.savePlaylist = function ()
{
if (!enabled)
return false;
$WH.localStorage.set('AudioPlaylist', JSON.stringify(playlist));
};
this.isEnabled = function ()
{
return enabled;
};
this.addSound = function (track)
{
if (!enabled)
return false;
this.init();
playlist.push(track);
this.savePlaylist();
};
this.deleteSound = function (idx)
{
if (idx < 0)
playlist = [];
else
playlist.splice(idx, 1);
this.savePlaylist();
if (!player.isPlaying())
{
player.removeSelf();
this.setAudioControls(container);
}
if (playlist.length == 0)
$WH.Tooltip.hide();
};
this.getList = function ()
{
var buf = [];
for (var i = 0; i < playlist.length; i++)
buf.push(playlist[i].title);
return buf;
};
this.setAudioControls = function (parent)
{
if (!enabled)
return false;
container = parent;
player = new AudioControls();
player.init(playlist, container, { loop: true, fromplaylist: true });
};
};
g_audioplaylist = (new AudioPlaylist);
g_audioplaylist.init();

View File

@@ -0,0 +1,122 @@
$WH.clickToCopy = function (el, textOrFn, opt)
{
opt = opt || {};
$WH.aE(el, 'click', $WH.clickToCopy.copy.bind(null, el, textOrFn, opt));
// $WH.preventSelectStart(el);
el.classList.add('click-to-copy');
if (opt.modifyTooltip)
{
el._fixTooltip = function (e) {
return e + '<br>' + $WH.ce('span', { className: 'q2', innerHTML: $WH.clickToCopy.getTooltip(false, opt) }).outerHTML;
};
opt.overrideOtherTooltips = false;
}
// aowow - fitted to old system
// $WH.Tooltips.attach(
$WH.Tooltip.simple(
el,
$WH.clickToCopy.getTooltip.bind(null, false, opt),
undefined,
// {
/* byCursor: */ !opt.attachToElement,
// stopPropagation: opt.overrideOtherTooltips
// }
);
};
$WH.clickToCopy.copy = function (el, textOrFn, opt, ev)
{
ev.preventDefault();
ev.stopPropagation();
if (textOrFn === undefined)
{
if (!el.childNodes[0] || !el.childNodes[0].textContent)
{
let text = 'Could not find text to copy.';
// $WH.error(text, el);
if (opt.attachToElement)
$WH.Tooltip.show(el, text, 'q10');
else
$WH.Tooltip.showAtCursor(ev, text, 'q10');
return;
}
textOrFn = el.childNodes[0].textContent;
}
else if (typeof textOrFn === 'function')
textOrFn = textOrFn();
$WH.copyToClipboard(textOrFn);
if (opt.attachToElement)
$WH.Tooltip.show(el, $WH.clickToCopy.getTooltip(true, opt));
else
$WH.Tooltip.showAtCursor(ev, $WH.clickToCopy.getTooltip(true, opt));
};
$WH.clickToCopy.getTooltip = function (clicked, opt)
{
let txt = '';
let attr = undefined;
if (clicked)
{
txt = ' ' + LANG.copied;
attr = { className: 'q1 icon-tick' };
}
else
txt = LANG.clickToCopy;
let tt = $WH.ce('div', attr, $WH.ct(txt));
if (opt.prefix)
{
tt.style.marginTop = '10px';
let prefix = typeof opt.prefix === 'function' ? opt.prefix() : opt.prefix;
return prefix + tt.outerHTML;
}
return tt.outerHTML;
};
$WH.copyToClipboard = function (text, t)
{
if (!$WH.copyToClipboard.hiddenInput)
{
$WH.copyToClipboard.hiddenInput = $WH.ce('textarea', { className: 'hidden-element' });
$WH.ae(document.body, $WH.copyToClipboard.hiddenInput);
}
$WH.copyToClipboard.hiddenInput.value = text;
let isEmpty = $WH.copyToClipboard.hiddenInput.value === '';
if (isEmpty)
$WH.copyToClipboard.hiddenInput.value = LANG.nothingToCopy_tip;
$WH.copyToClipboard.hiddenInput.focus();
$WH.copyToClipboard.hiddenInput.select();
if (!document.execCommand('copy'))
prompt(null, text);
$WH.copyToClipboard.hiddenInput.blur();
if (t)
{
if (isEmpty)
$WH.Tooltips.showFadingTooltipAtCursor(LANG.nothingToCopy_tip, t, 'q10');
else
{
let e = $WH.ce('span', { className: 'q1 icon-tick' }, $WH.ct(' ' + LANG.copied));
$WH.Tooltips.showFadingTooltipAtCursor(e.outerHTML, t);
}
}
};

View File

@@ -0,0 +1,459 @@
/* Note: comment replies are called "comments" because part of this code was taken from another project of mine. */
function SetupReplies(post, comment)
{
SetupAddEditComment(post, comment, false);
SetupShowMoreComments(post, comment);
post.find('.comment-reply-row').each(function () { SetupRepliesControls($(this), comment); });
post.find('.comment-reply-row').hover(function () { $(this).find('span').attr('data-hover', 'true'); }, function () { $(this).find('span').attr('data-hover', 'false'); });
}
function SetupAddEditComment(post, comment, edit)
{
/* Variables that will be set by Initialize() */
var Form = null;
var Body = null;
var AddButton = null;
var TextCounter = null;
var AjaxLoader = null;
var FormContainer = null;
var DialogTableRowContainer = null;
/* Constants */
var MIN_LENGTH = 15;
var MAX_LENGTH = 600;
/* State keeping booleans */
var Initialized = false;
var Active = false;
var Flashing = false;
var Submitting = false;
/* Shortcuts */
var CommentsTable = post.find('.comment-replies > table');
var AddCommentLink = post.find('.add-reply');
var CommentsCount = comment.replies.length;
if(edit)
Open();
else
AddCommentLink.click(function () { Open(); });
function Initialize()
{
if (Initialized)
return;
Initialized = true;
var row = $('<tr/>');
if(edit)
row.addClass('comment-reply-row').addClass('reply-edit-row');
row.html('<td style="width: 0"></td>' +
'<td class="comment-form"><form><table>' +
'<form>' +
'<table><tr>' +
'<td style="width: 600px">' +
'<textarea required="required" name="body" cols="68" rows="3"></textarea>' +
'</td>' +
'<td>' +
'<input type="submit" value="' + (edit ? LANG.save : LANG.addreply) + '" />' +
'<img src="' + g_staticUrl + '/images/icons/ajax.gif" class="ajax-loader" />' +
'</td>' +
'</tr>' +
'<tr><td colspan="2">' +
'<span class="text-counter">Text counter placeholder</span>' +
'</td></tr></table>' +
'</form>' +
'</td>');
/* Set up the various variables for the controls we just created */
Body = row.find('.comment-form textarea');
AddButton = row.find('.comment-form input[type=submit]');
TextCounter = row.find('.comment-form span.text-counter');
Form = row.find('.comment-form form');
AjaxLoader = row.find('.comment-form .ajax-loader');
FormContainer = row.find('.comment-form');
/* Intercept submits */
Form.submit(function () { Submit(); return false; });
UpdateTextCounter();
/* This is kinda a mess.. Every browser seems to implement keyup, keydown and keypress differently.
* - keyup: We need to use keyup to update the text counter for the simple reason we want to update it only when the user stops typing.
* - keydown: We need to use keydown to detect the ESC key because it's the only one that works in all browsers for ESC
* - keypress: We need to use keypress to detect Enter because it's the only one that 1) Works 2) Allows us to prevent a new line from being entered in the textarea
* I find it very funny that in each scenario there is only one of the 3 that works, and that that one is always different from the others.
*/
Body.keyup(function (e) { UpdateTextCounter(); });
Body.keydown(function (e) { if (e.keyCode == 27) { Close(); return false; } }); // ESC
Body.keypress(function (e) { if (e.keyCode == 13) { Submit(); return false; } }); // ENTER
if(edit)
{
post.after(row);
post.hide();
Form.find('textarea').text(comment.replies[post.attr('data-idx')].body);
}
else
CommentsTable.append(row);
DialogTableRowContainer = row;
Form.find('textarea').focus();
}
function Open()
{
if (!Initialized)
Initialize();
Active = true;
if(!edit)
{
AddCommentLink.hide();
post.find('.comment-replies').show();
FormContainer.show();
FormContainer.find('textarea').focus();
}
}
function Close()
{
Active = false;
if(edit)
{
if(DialogTableRowContainer)
DialogTableRowContainer.remove();
post.show();
return;
}
AddCommentLink.show();
FormContainer.hide();
if (CommentsCount == 0)
post.find('.comment-replies').hide();
}
function Submit()
{
if (!Active || Submitting)
return;
if (Body.val().length < MIN_LENGTH || Body.val().length > MAX_LENGTH)
{
/* Flash the char counter to attract the attention of the user. */
if (!Flashing)
{
Flashing = true;
TextCounter.animate({ opacity: '0.0' }, 150);
TextCounter.animate({ opacity: '1.0' }, 150, null, function() { Flashing = false; });
}
return false;
}
SetSubmitState();
$.ajax({
type: 'POST',
url: edit ? '?comment=edit-reply' : '?comment=add-reply',
data: { commentId: comment.id, replyId: (edit ? post.attr('data-replyid') : 0), body: Body.val() },
success: function (newReplies) { OnSubmitSuccess(newReplies); },
dataType: 'json',
error: function (jqXHR) { OnSubmitFailure(jqXHR.responseText); }
});
return true;
}
function SetSubmitState()
{
Submitting = true;
AjaxLoader.show();
AddButton.attr('disabled', 'disabled');
FormContainer.find('.message-box').remove();
}
function ClearSubmitState()
{
Submitting = false;
AjaxLoader.hide();
AddButton.removeAttr('disabled');
}
function OnSubmitSuccess(newReplies)
{
comment.replies = newReplies;
Listview.templates.comment.updateReplies(comment);
}
function OnSubmitFailure(error)
{
ClearSubmitState();
MessageBox(FormContainer, error);
}
function UpdateTextCounter()
{
var text = '(error)';
var cssClass = 'q0';
var chars = Body.val().replace(/(\s+)/g, ' ').replace(/^\s*/, '').replace(/\s*$/, '').length;
var charsLeft = MAX_LENGTH - chars;
if (chars == 0)
text = $WH.sprintf(LANG.replylength1_format, MIN_LENGTH);
else if (chars < MIN_LENGTH)
text = $WH.sprintf(LANG.replylength2_format, MIN_LENGTH - chars);
else
{
text = $WH.sprintf(charsLeft == 1 ? LANG.replylength4_format : LANG.replylength3_format, charsLeft);
if (charsLeft < 120)
cssClass = 'q10';
else if (charsLeft < 240)
cssClass = 'q5';
else if (charsLeft < 360)
cssClass = 'q11';
}
TextCounter.html(text).attr('class', cssClass);
}
}
function SetupShowMoreComments(post, comment)
{
var ShowMoreCommentsLink = post.find('.show-more-replies');
var CommentCell = post.find('.comment-replies');
ShowMoreCommentsLink.click(function () { ShowMoreComments(); });
function ShowMoreComments()
{
/* Replace link with ajax loader */
ShowMoreCommentsLink.hide();
CommentCell.append(CreateAjaxLoader());
$.ajax({
type: 'GET',
url: '?comment=show-replies',
data: { id: comment.id },
success: function (replies) { comment.replies = replies; Listview.templates.comment.updateReplies(comment); },
dataType: 'json',
error: function () { OnFetchFail(); }
});
}
function OnFetchFail()
{
ShowMoreCommentsLink.show();
CommentCell.find('.ajax-loader').remove();
MessageBox(CommentCell, "There was an error fetching the comments. Try refreshing the page.");
}
}
function SetupRepliesControls(post, comment)
{
var CommentId = post.attr('data-replyid');
var VoteUpControl = post.find('.reply-upvote');
var VoteDownControl = post.find('.reply-downvote');
var FlagControl = post.find('.reply-report');
var CommentScoreText = post.find('.reply-rating');
var CommentActions = post.find('.reply-controls');
var DeleteButton = post.find('.reply-delete');
var EditButton = post.find('.reply-edit');
var Voting = false;
var Deleting = false;
// aowow - detach functionality is custom
var Detaching = false;
var DetachButton = post.find('.reply-detach');
var Container = comment.repliesCell;
EditButton.click(function() {
SetupAddEditComment(post, comment, true);
});
FlagControl.click(function ()
{
if (Voting || !confirm(LANG.replyreportwarning_tip))
return;
Voting = true;
$.ajax({
type: 'POST',
url: '?comment=flag-reply',
data: { id: CommentId },
success: function () { OnFlagSuccessful(); },
error: function (jqXHR) { OnError(jqXHR.responseText); }
});
});
VoteUpControl.click(function ()
{
if (VoteUpControl.attr('data-hasvoted') == 'true' || VoteUpControl.attr('data-canvote') != 'true' || Voting)
return;
Voting = true;
$.ajax({
type: 'POST',
url: '?comment=upvote-reply',
data: { id: CommentId },
success: function () { OnVoteSuccessful(1); },
error: function (jqXHR) { OnError(jqXHR.responseText); }
});
});
VoteDownControl.click(function ()
{
if (VoteDownControl.attr('data-hasvoted') == 'true' || VoteDownControl.attr('data-canvote') != 'true' || Voting)
return;
Voting = true;
$.ajax({
type: 'POST',
url: '?comment=downvote-reply',
data: { id: CommentId },
success: function () { OnVoteSuccessful(-1); },
error: function (jqXHR) { OnError(jqXHR.responseText); }
});
});
DetachButton.click(function ()
{
if (Detaching) {
MessageBox(CommentActions, LANG.message_cantdetachcomment);
return;
}
if (!confirm(LANG.confirm_detachcomment)) {
return;
}
Detaching = true;
$.ajax({
type: 'POST',
url: '?comment=detach-reply',
data: { id: CommentId },
success: function () { OnDetachSuccessful(); },
error: function (jqXHR) { OnError(jqXHR.responseText); }
});
});
DeleteButton.click(function ()
{
if (Deleting)
return;
if (!confirm(LANG.deletereplyconfirmation_tip))
return;
Deleting = true;
$.ajax({
type: 'POST',
url: '?comment=delete-reply',
data: { id: CommentId },
success: function () { OnDeleteSuccessful(); },
error: function (jqXHR) { OnError(jqXHR.responseText); }
});
});
function OnVoteSuccessful(ratingChange)
{
var rating = parseInt(CommentScoreText.text());
rating += ratingChange;
CommentScoreText.text(rating);
if(ratingChange > 0)
VoteUpControl.attr('data-hasvoted', 'true');
else
VoteDownControl.attr('data-hasvoted', 'true');
VoteUpControl.attr('data-canvote', 'false');
VoteDownControl.attr('data-canvote', 'false');
if(ratingChange > 0)
FlagControl.remove();
Voting = false;
}
function OnFlagSuccessful()
{
Voting = false;
FlagControl.remove();
}
function OnDetachSuccessful()
{
post.remove();
MessageBox(Container, LANG.message_commentdetached);
Detaching = false;
}
function OnDeleteSuccessful()
{
post.remove();
Deleting = false;
}
function OnError(text)
{
Voting = false;
Deleting = false;
Detaching = false;
if (!text)
text = LANG.genericerror;
MessageBox(CommentActions, text);
}
}
/*
Global comment-related functions
*/
function co_addYourComment()
{
tabsContribute.focus(0);
var ta = $WH.gE(document.forms['addcomment'], 'textarea')[0];
ta.focus();
}
function co_validateForm(f)
{
var ta = $WH.gE(f, 'textarea')[0];
// prevent locale comments on guide pages
var locale = Locale.getId();
// aowow - disabled
// if(locale != LOCALE_ENUS && $(f).attr('action') && ($(f).attr('action').replace(/^.*type=([0-9]*).*$/i, '$1')) == 100)
if (false)
{
alert(LANG.message_cantpostlcomment_tip);
return false;
}
if (g_user.permissions & 1) {
return true;
}
if (Listview.funcBox.coValidate(ta)) {
return true;
}
return false;
}
// Display a warning if a user attempts to leave the page and he has started writing a message
$(document).ready(function()
{
g_setupChangeWarning($("form[name=addcomment]"), [$("textarea[name=commentbody]")], LANG.message_startedpost);
});

View File

@@ -0,0 +1,329 @@
/* aowow - custom: TrinityCore Conditions */
var ConditionList = new function() {
var self = this,
_conditions = null;
self.createCell = function(conditions)
{
if (!conditions)
return null;
_conditions = conditions;
return _createCell();
};
self.createTab = function(conditions)
{
if (!conditions)
return null;
_conditions = conditions;
return _createTab();
};
function _makeList(mask, src, tpl)
{
var arr = Listview.funcBox.assocBinFlags(mask, src).sort(),
buff = '';
for (var i = 0, len = arr.length; i < len; ++i)
{
if (len > 1 && i == len - 1)
buff += LANG.or;
else if (i > 0)
buff += LANG.comma;
buff += $WH.sprintf(tpl, arr[i], src[arr[i]]);
}
return buff;
}
function _parseEntry(entry, targets, target)
{
var str = '',
negate = false,
strIdx = 0,
param = [];
[strIdx, ...param] = entry;
negate = strIdx < 0;
strIdx = Math.abs(strIdx);
if (!g_conditions[strIdx])
return 'unknown condition index #' + strIdx;
switch (strIdx)
{
case 5:
var standings = {};
for (let i in g_reputation_standings)
standings[i * 1 + 1] = g_reputation_standings[i];
param[1] = _makeList(entry[2], standings, '$2');
break;
case 6:
if (entry[1] == 1)
param[0] = $WH.sprintf('[span class=icon-alliance]$1[/span]', g_sides[1]);
else if (entry[1] == 2)
param[0] = $WH.sprintf('[span class=icon-horde]$1[/span]', g_sides[2]);
else
param[0] = $WH.sprintf('[span class=icon-alliance]$1[/span]$2[span class=icon-horde]$3[/span]', g_sides[1], LANG.or, g_sides[2]);
break;
case 10:
param[0] = g_drunk_states[entry[1]] ?? 'UNK DRUNK STATE';
break;
case 13:
param[2] = g_instance_info[entry[3]] ?? 'UNK INSTANCE INFO';
break;
case 15:
param[0] = _makeList(entry[1], g_chr_classes, '[class=$1]');
break;
case 16:
param[0] = _makeList(entry[1], g_chr_races, '[race=$1]');
break;
case 20:
if (entry[1] == 0)
param[0] = $WH.sprintf('[span class=icon-$1]$2[/span]', g_file_genders[0], LANG.male);
else if (entry[1] == 1)
param[0] = $WH.sprintf('[span class=icon-$1]$2[/span]', g_file_genders[1], LANG.female);
else
param[0] = g_npc_types[10]; // not specified
break;
case 21:
var states = {};
for (let i in g_unit_states)
states[i * 1 + 1] = g_unit_states[i];
param[0] = _makeList(entry[1], states, '$2');
break;
case 22:
if (entry[2])
param[0] = '[zone=' + entry[2] + ']';
else
param[0] = g_zone_categories[entry[1]] ?? 'UNK ZONE';
break;
case 24:
param[0] = g_npc_types[entry[1]] ?? 'UNK NPC TYPE';
break;
case 26:
var idx = 0, buff = [];
while (entry[1] >= (1 << idx)) {
if (!(entry[1] & (1 << idx++)))
continue;
buff.push(idx);
}
param[0] = buff ? buff.join(LANG.comma) : '';
break;
case 27:
case 37:
case 38:
param[1] = g_operators[entry[2]];
break;
case 31:
if (entry[2] && entry[1] == 3)
param[0] = '[npc=' + entry[2] + ']';
else if (entry[2] && entry[1] == 5)
param[0] = '[object=' + entry[2] + ']';
else
param[0] = g_world_object_types[entry[1]] ?? 'UNK TYPEID';
break;
case 32:
var objectTypes = {};
for (let i in g_world_object_types)
objectTypes[i * 1 + 1] = g_world_object_types[i];
param[0] = _makeList(entry[1], objectTypes, '$2');
break;
case 33:
param[0] = targets[entry[1]];
param[1] = g_relation_types[entry[2]] ?? 'UNK RELATION';
param[2] = targets[target];
break;
case 34:
param[0] = targets[entry[1]];
var standings = {};
for (let i in g_reputation_standings)
standings[i * 1 + 1] = g_reputation_standings[i];
param[1] = _makeList(entry[2], standings, '$2');
break;
case 35:
param[0] = targets[entry[1]];
param[2] = g_operators[entry[3]];
break;
case 42:
if (!entry[1])
param[0] = g_stand_states[entry[2]] ?? 'UNK STAND_STATE';
else if (entry[1] == 1)
param[0] = g_stand_states[entry[2] ? 1 : 0];
else
param[0] = '';
break;
case 47:
var quest_states = {};
for (let i in g_quest_states)
quest_states[i * 1 + 1] = g_quest_states[i];
param[1] = _makeList(entry[2], quest_states, '$2');
break;
}
str = g_conditions[strIdx];
// fill in params
str = $WH.sprintfa(str, param[0], param[1], param[2]);
// resolve NegativeCondition
str = str.replace(/\$N([^:]*):([^;]*);/g, '$' + (negate > 0 ? 2 : 1));
// resolve vars
return str.replace(/\$C(\d+)([^:]*):([^;]*);/g, (_, i, y, n) => (i > 0 ? y : n));
}
function _createTab()
{
var buff = '';
// tabs for conditionsTypes
for (g in _conditions)
{
if (!g_condition_sources[g])
continue;
let k = 0;
for (h in _conditions[g])
{
var srcGroup, srcEntry, srcId, target,
targets, desc,
nGroups = Object.keys(_conditions[g][h]).length,
curGroup = 1;
[srcGroup, srcEntry, srcId, target] = h.split(':').map((x) => parseInt(x));
[targets, desc] = g_condition_sources[g];
// resolve targeting
let src = desc.replace(/\$T([^:]*):([^;]*);/, (_, t1, t2) => (target ? t2 : t1).replace('%', targets[target]));
let rand = $WH.rs();
buff += '[h3][toggler' + (k ? '=hidden' : '') + ' id=' + rand + ']' + $WH.sprintfa(src, srcGroup, srcEntry, srcId) + '[/toggler][/h3][div' + (k++ ? '=hidden' : '') + ' id=' + rand + ']';
if (nGroups > 1)
{
buff += LANG.note_condition_group + '[br][br]';
buff += '[table class=grid]';
}
// table for elseGroups
for (i in _conditions[g][h])
{
var group = _conditions[g][h][i],
nEntries = Object.keys(_conditions[g][h][i]).length;
if (nGroups <= 1 && nEntries > 1)
buff += '[div style="padding-left:15px"]' + LANG.note_condition + '[/div]';
if (nGroups > 1)
buff += '[tr][td width=70px valign=middle align=center]' + LANG.group + ' ' + (curGroup++) + LANG.colon + '[/td][td]';
// individual conditions
buff += '[ol]';
for (j in group)
buff += '[li]' + _parseEntry(group[j], targets, target) + '[/li]';
buff += '[/ol]';
if (nGroups > 1)
buff += '[/td][/tr]';
}
if (nGroups > 1)
buff += '[/tr][/table]';
buff += '[/div]';
}
}
return buff;
}
function _createCell()
{
var rows = [];
// tabs for conditionsTypes
for (let g in _conditions)
{
if (!g_condition_sources[g])
continue;
for (let h in _conditions[g])
{
var target, targets,
[, , , target] = h.split(':').map((x) => parseInt(x));
[targets, ] = g_condition_sources[g];
let nElseGroups = Object.keys(_conditions[g][h]).length
// table for elseGroups
for (let i in _conditions[g][h])
{
let subGroup = [],
group = _conditions[g][h][i],
nEntries = Object.keys(_conditions[g][h][i]).length
buff = '';
if (nElseGroups > 1)
{
let rand = $WH.rs();
buff += '[toggler' + (i > 0 ? '=hidden' : '') + ' id=cell-' + rand + ']' + (i > 0 ? LANG.cnd_or : LANG.cnd_either) + '[/toggler][div' + (i > 0 ? '=hidden' : '') + ' id=cell-' + rand + ']';
}
// individual conditions
for (let j in group)
subGroup.push(_parseEntry(group[j], targets, target));
for (j in subGroup)
{
if (nEntries > 1 && j > 0 && j == subGroup.length - 1)
buff += LANG.and + '[br]';
else if (nEntries > 1 && j > 0)
buff += ',[br]';
buff += subGroup[j];
}
if (nElseGroups > 1)
buff += '[/div]';
rows.push(buff);
}
}
}
return rows.length > 1 ? rows.join('[br]') : rows[0];
}
}
/* end custom */

View File

@@ -0,0 +1,550 @@
var ContactTool = new function()
{
this.general = 0;
this.comment = 1;
this.post = 2;
this.screenshot = 3;
this.character = 4;
this.video = 5;
this.guide = 6;
var _dialog;
var contexts = {
0: [ // general
[1, true], // General feedback
[2, true], // Bug report
[8, true], // Article misinformation
[3, true], // Typo/mistranslation
[4, true], // Advertise with us
[5, true], // Partnership opportunities
[6, true], // Press inquiry
[7, true] // Other
],
1: [ // comment
[15, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Advertising
[16, true], // Inaccurate
[17, true], // Out of date
[18, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Spam
[19, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[20, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }] // Other
],
2: [ // forum post
[30, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Advertising
[37, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && (post.roles & U_GROUP_MODERATOR) == 0 && g_users[post.user].avatar == 2); }], // Avatar
[31, true], // Inaccurate
[32, true], // Out of date
[33, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Spam
[34, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && post.op && !post.sticky); }], // Sticky request
[35, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[36, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);}] // Other
],
3: [ // screenshot
[45, true], // Inaccurate,
[46, true], // Out of date,
[47, function(screen) { return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[48, function(screen) { return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); }] // Other
],
4: [ // character
[60, true], // Inaccurate completion data
[61, true] // Other
],
5: [ // video
[45, true], // Inaccurate,
[46, true], // Out of date,
[47, function(video) { return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[48, function(video) { return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); }] // Other
],
6: [ // Guide
[45, true], // Inaccurate,
[46, true], // Out of date,
[48, true] // Other
]
};
var errors = {
1: LANG.ct_resp_error1,
2: LANG.ct_resp_error2,
3: LANG.ct_resp_error3,
7: LANG.ct_resp_error7
};
var oldHash = null;
this.displayError = function(field, message)
{
alert(message);
}
this.onShow = function()
{
if (location.hash && location.hash != '#contact')
oldHash = location.hash;
if (this.data.mode == 0)
location.replace('#contact');
}
this.onHide = function()
{
if (oldHash && (oldHash.indexOf('screenshots:') == -1 || oldHash.indexOf('videos:') == -1))
location.replace(oldHash);
else
location.replace('#.');
}
this.onSubmit = function(data, button, form)
{
if (data.submitting)
return false;
for (var i = 0; i < form.elements.length; ++i)
form.elements[i].disabled = true;
var params = [
'contact=1',
'mode=' + $WH.urlencode(data.mode),
'reason=' + $WH.urlencode(data.reason),
'desc=' + $WH.urlencode(data.description),
'ua=' + $WH.urlencode(navigator.userAgent),
'appname=' + $WH.urlencode(navigator.appName),
'page=' + $WH.urlencode(data.currenturl)
];
if (data.mode == 0) // contact us
{
if (data.relatedurl)
params.push('relatedurl=' + $WH.urlencode(data.relatedurl));
if (data.email)
params.push('email=' + $WH.urlencode(data.email));
}
else if (data.mode == 1) // comment
params.push('id=' + $WH.urlencode(data.comment.id));
else if (data.mode == 2) // forum post
params.push('id=' + $WH.urlencode(data.post.id));
else if (data.mode == 3) // screenshot
params.push('id=' + $WH.urlencode(data.screenshot.id));
else if (data.mode == 4) // character
params.push('id=' + $WH.urlencode(data.profile.source));
else if (data.mode == 5) // video
params.push('id=' + $WH.urlencode(data.video.id));
else if (data.mode == 6) // guide
params.push('id=' + $WH.urlencode(data.guide.id));
data.submitting = true;
var url = '?contactus';
new Ajax(url, {
method: 'POST',
params: params.join('&'),
onSuccess: function(xhr, opt) {
var resp = xhr.responseText;
if (resp == 0)
{
if (g_user.name)
alert($WH.sprintf(LANG.ct_dialog_thanks_user, g_user.name));
else
alert(LANG.ct_dialog_thanks);
Lightbox.hide();
}
else
{
if (errors[resp])
alert(errors[resp]);
else
alert('Error: ' + resp);
}
},
onFailure: function(xhr, opt) {
alert('Failure submitting contact request: ' + xhr.statusText);
},
onComplete: function(xhr, opt) {
for (var i = 0; i < form.elements.length; ++i)
form.elements[i].disabled = false;
data.submitting = false;
}
});
return false;
}
this.show = function(opt)
{
if (!opt)
opt = {};
var data = { mode: 0 };
$WH.cO(data, opt);
data.reasons = contexts[data.mode];
if (location.href.indexOf('#contact') != -1)
data.currenturl = location.href.substr(0, location.href.indexOf('#contact'));
else
data.currenturl = location.href;
var form = 'contactus';
if (data.mode != 0)
form = 'reportform';
if (!_dialog)
{
this.init();
}
_dialog.show(form, {
data: data,
onShow: this.onShow,
onHide: this.onHide,
onSubmit: this.onSubmit
})
}
this.checkPound = function()
{
if (location.hash && location.hash == '#contact')
{
ContactTool.show();
}
}
var dialog_contacttitle = LANG.ct_dialog_contactwowhead;
this.init = function()
{
_dialog = new Dialog();
Dialog.templates.contactus = {
title: dialog_contacttitle,
width: 550,
buttons: [['okay', LANG.ok], ['cancel', LANG.cancel]],
fields: [
{
id: 'reason',
type: 'select',
label: LANG.ct_dialog_reason,
required: 1,
options: [],
compute: function(field, value, form, td)
{
$WH.ee(field);
for (var i = 0; i < this.data.reasons.length; ++i)
{
var id = this.data.reasons[i][0];
var check = this.data.reasons[i][1];
var valid = false;
if (typeof check == 'function')
valid = check(this.extra);
else
valid = check;
if (!valid)
continue;
var o = $WH.ce('option');
o.value = id;
if (value && value == id)
o.selected = true;
$WH.ae(o, $WH.ct(g_contact_reasons[id]));
$WH.ae(field, o);
}
field.onchange = function()
{
if (this.value == 1 || this.value == 2 || this.value == 3)
{
form.currenturl.parentNode.parentNode.style.display = '';
form.relatedurl.parentNode.parentNode.style.display = '';
}
else
{
form.currenturl.parentNode.parentNode.style.display = 'none';
form.relatedurl.parentNode.parentNode.style.display = 'none';
}
}.bind(field);
td.style.width = '98%';
},
validate: function(newValue, data, form)
{
var error = '';
if (!newValue || newValue.length == 0)
error = LANG.ct_dialog_error_reason;
if (error == '')
return true;
ContactTool.displayError(form.reason, error);
form.reason.focus();
return false;
}
},
{
id: 'currenturl',
type: 'text',
disabled: true,
label: LANG.ct_dialog_currenturl,
size: 40
},
{
id: 'relatedurl',
type: 'text',
label: LANG.ct_dialog_relatedurl,
caption: LANG.ct_dialog_optional,
size: 40,
validate: function(newValue, data, form)
{
var error = '';
var urlRe = /^(http(s?)\:\/\/|\/)?([\w]+:\w+@)?([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((\/?\w+\/)+|\/?)(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?/;
newValue = newValue.trim();
if (newValue.length >= 250)
error = LANG.ct_dialog_error_relatedurl;
else if (newValue.length > 0 && !urlRe.test(newValue))
error = LANG.ct_dialog_error_invalidurl;
if (error == '')
return true;
ContactTool.displayError(form.relatedurl, error);
form.relatedurl.focus();
return false;
}
},
{
id: 'email',
type: 'text',
label: LANG.ct_dialog_email,
caption: LANG.ct_dialog_email_caption,
compute: function(field, value, form, td, tr)
{
if (g_user.email)
{
this.data.email = g_user.email;
tr.style.display = 'none';
}
else
{
var func = function()
{
$('#contact-emailwarn').css('display', g_isEmailValid($(form.email).val()) ? 'none' : '');
Lightbox.reveal();
};
$(field).keyup(func).blur(func);
}
},
validate: function(newValue, data, form)
{
var error = '';
newValue = newValue.trim();
if (newValue.length >= 100)
error = LANG.ct_dialog_error_emaillen;
else if (newValue.length > 0 && !g_isEmailValid(newValue))
error = LANG.ct_dialog_error_email;
if (error == '')
return true;
ContactTool.displayError(form.email, error);
form.email.focus();
return false;
}
},
{
id: 'description',
type: 'textarea',
caption: LANG.ct_dialog_desc_caption,
width: '98%',
required: 1,
size: [10, 30],
validate: function(newValue, data, form)
{
var error = '';
newValue = newValue.trim();
if (newValue.length == 0 || newValue.length > 10000)
error = LANG.ct_dialog_error_desc;
if (error == '')
return true;
ContactTool.displayError(form.description, error);
form.description.focus();
return false;
}
},
{
id: 'noemailwarning',
type: 'caption',
compute: function(field, value, form, td)
{
$(td).html('<span id="contact-emailwarn" class="q10"' + (g_user.email ? ' style="display: none"' : '') + '>' + LANG.ct_dialog_noemailwarning + '</span>').css('white-space', 'normal').css('padding', '0 4px');
}
}
],
onInit: function(form)
{
},
onShow: function(form)
{
if (this.data.focus && form[this.data.focus])
setTimeout(g_setCaretPosition.bind(null, form[this.data.focus], form[this.data.focus].value.length), 100);
else if (form['reason'] && !form.reason.value)
setTimeout($WH.bindfunc(form.reason.focus, form.reason), 10);
else if (form['relatedurl'] && !form.relatedurl.value)
setTimeout($WH.bindfunc(form.relatedurl.focus, form.relatedurl), 10);
else if (form['email'] && !form.email.value)
setTimeout($WH.bindfunc(form.email.focus, form.email), 10);
else if (form['description'] && !form.description.value)
setTimeout($WH.bindfunc(form.description.focus, form.description), 10);
setTimeout(Lightbox.reveal, 250);
}
}
Dialog.templates.reportform = {
title: LANG.ct_dialog_report,
width: 550,
// height: 360,
buttons: [['okay', LANG.ok], ['cancel', LANG.cancel]],
fields: [
{
id: 'reason',
type: 'select',
label: LANG.ct_dialog_reason,
options: [],
compute: function(field, value, form, td)
{
switch (this.data.mode)
{
case 1: // comment
form.firstChild.innerHTML = $WH.sprintf(LANG.ct_dialog_reportcomment, '<a href="?user=' + this.data.comment.user + '">' + this.data.comment.user + '</a>');
break;
case 2: // forum post
var rep = '<a href="?user=' + this.data.post.user + '">' + this.data.post.user + '</a>';
if (this.data.post.op)
form.firstChild.innerHTML = $WH.sprintf(LANG.ct_dialog_reporttopic, rep);
else
form.firstChild.innerHTML = $WH.sprintf(LANG.ct_dialog_reportpost, rep);
break;
case 3: // screenshot
form.firstChild.innerHTML = $WH.sprintf(LANG.ct_dialog_reportscreen, '<a href="?user=' + this.data.screenshot.user + '">' + this.data.screenshot.user + '</a>');
break;
case 4: // character
$WH.ee(form.firstChild);
$WH.ae(form.firstChild, $WH.ct(LANG.ct_dialog_reportchar));
break;
case 5: // video
form.firstChild.innerHTML = $WH.sprintf(LANG.ct_dialog_reportvideo, '<a href="?user=' + this.data.video.user + '">' + this.data.video.user + '</a>');
break;
case 6: // guide
form.firstChild.innerHTML = 'Report guide';
break;
}
form.firstChild.setAttribute('style', '');
$WH.ee(field);
var extra;
if (this.data.mode == 1)
extra = this.data.comment;
else if (this.data.mode == 2)
extra = this.data.post;
else if (this.data.mode == 3)
extra = this.data.screenshot;
else if (this.data.mode == 4)
extra = this.data.profile;
else if (this.data.mode == 5)
extra = this.data.video;
else if (this.data.mode == 6)
extra = this.data.guide;
$WH.ae(field, $WH.ce('option', { selected: (!value), value: -1 }));
for (var i = 0; i < this.data.reasons.length; ++i)
{
var id = this.data.reasons[i][0];
var check = this.data.reasons[i][1];
var valid = false;
if (typeof check == 'function')
valid = check(extra);
else
valid = check;
if (!valid)
continue;
var o = $WH.ce('option');
o.value = id;
if (value && value == id)
o.selected = true;
$WH.ae(o, $WH.ct(g_contact_reasons[id]));
$WH.ae(field, o);
}
td.style.width = '98%';
},
validate: function(newValue, data, form)
{
var error = '';
if (!newValue || newValue == -1 || newValue.length == 0)
error = LANG.ct_dialog_error_reason;
if (error == '')
return true;
ContactTool.displayError(form.reason, error);
form.reason.focus();
return false;
}
},
{
id: 'description',
type: 'textarea',
caption: LANG.ct_dialog_desc_caption,
width: '98%',
required: 1,
size: [10, 30],
validate: function(newValue, data, form)
{
var error = '';
newValue = newValue.trim();
if (newValue.length == 0 || newValue.length > 10000)
error = LANG.ct_dialog_error_desc;
if (error == '')
return true;
ContactTool.displayError(form.description, error);
form.description.focus();
return false;
}
}
],
onInit: function(form)
{
},
onShow: function(form)
{
/* Work-around for IE7 */
var reason = $(form).find("*[name=reason]")[0];
var description = $(form).find("*[name=description]")[0];
if (this.data.focus && form[this.data.focus])
setTimeout(g_setCaretPosition.bind(null, form[this.data.focus], form[this.data.focus].value.length), 100);
else if (!reason.value)
setTimeout($WH.bindfunc(reason.focus, reason), 10);
else if (!description.value)
setTimeout($WH.bindfunc(description.focus, description), 10);
}
}
}
$(document).ready(this.checkPound);
};

View File

@@ -0,0 +1,37 @@
// TODO: Create a "Cookies" object
function g_cookiesEnabled()
{
document.cookie = 'enabledTest';
return (document.cookie.indexOf("enabledTest") != -1) ? true : false;
}
function g_getWowheadCookie(name)
{
if (g_user.id > 0)
{
return g_user.cookies[name]; // no point checking if it exists, as undefined tests as false anyways
}
else
{
return $WH.gc(name); // plus gc does the same thing..
}
}
function g_setWowheadCookie(name, data, browser)
{
var temp = name.substr(0, 5) == 'temp_';
if (!browser && g_user.id > 0 && !temp) {
new Ajax('?cookie=' + name + '&' + name + '=' + $WH.urlencode(data), {
method: 'get',
onSuccess: function(xhr) {
if (xhr.responseText == 0)
g_user.cookies[name] = data;
}
});
}
else if (browser || g_user.id == 0)
{
$WH.sc(name, 14, data, null, location.hostname);
}
}

View File

@@ -0,0 +1,568 @@
var Dialog = function()
{
var
_self = this,
_template,
_onSubmit = null,
_templateName,
_funcs = {},
_data,
_inited = false,
_form = $WH.ce('form'),
_elements = {};
_form.onsubmit = function() {
_processForm();
return false
};
this.show = function(template, opt)
{
if (template)
{
_templateName = template;
_template = Dialog.templates[_templateName];
_self.template = _template;
}
else
return;
if (_template.onInit && !_inited)
(_template.onInit.bind(_self, _form, opt))();
if (opt.onBeforeShow)
_funcs.onBeforeShow = opt.onBeforeShow.bind(_self, _form);
if (_template.onBeforeShow)
_template.onBeforeShow = _template.onBeforeShow.bind(_self, _form);
if (opt.onShow)
_funcs.onShow = opt.onShow.bind(_self, _form);
if (_template.onShow)
_template.onShow = _template.onShow.bind(_self, _form);
if (opt.onHide)
_funcs.onHide = opt.onHide.bind(_self, _form);
if (_template.onHide)
_template.onHide = _template.onHide.bind(_self, _form);
if (opt.onSubmit)
_funcs.onSubmit = opt.onSubmit;
if (_template.onSubmit)
_onSubmit = _template.onSubmit.bind(_self, _form);
if (opt.data)
{
_inited = false;
_data = {};
$WH.cO(_data, opt.data);
}
_self.data = _data;
Lightbox.show('dialog-' + _templateName, {
onShow: _onShow,
onHide: _onHide
});
}
this.getValue = function(id)
{
return _getValue(id);
}
this.setValue = function(id, value)
{
_setValue(id, value);
}
this.getSelectedValue = function(id)
{
return _getSelectedValue(id);
}
this.getCheckedValue = function(id)
{
return _getCheckedValue(id);
}
function _onShow(dest, first)
{
if (first || !_inited)
_initForm(dest);
if (_template.onBeforeShow)
_template.onBeforeShow();
if (_funcs.onBeforeShow)
_funcs.onBeforeShow();
Lightbox.setSize(_template.width, _template.height);
dest.className = 'dialog';
_updateForm();
if (_template.onShow)
_template.onShow();
if (_funcs.onShow)
_funcs.onShow();
}
function _initForm(dest)
{
$WH.ee(dest);
$WH.ee(_form);
var container = $WH.ce('div');
container.className = 'text';
$WH.ae(dest, container);
$WH.ae(container, _form);
if (_template.title)
{
var h = $WH.ce('h1');
$WH.ae(h, $WH.ct(_template.title));
$WH.ae(_form, h);
}
var t = $WH.ce('table'),
tb = $WH.ce('tbody'),
mergeCell = false;
$WH.ae(t, tb);
$WH.ae(_form, t);
for (var i = 0, len = _template.fields.length; i < len; ++i)
{
var
field = _template.fields[i],
element;
if (!mergeCell)
{
tr = $WH.ce('tr');
th = $WH.ce('th');
td = $WH.ce('td');
}
field.__tr = tr;
if (_data[field.id] == null)
_data[field.id] = (field.value ? field.value : '');
var options;
if (field.options)
{
options = [];
if (field.optorder)
$WH.cO(options, field.optorder);
else
{
for (var j in field.options)
options.push(j);
}
if (field.sort)
options.sort(function(a, b) { return field.sort * $WH.strcmp(field.options[a], field.options[b]); });
}
switch (field.type)
{
case 'caption':
th.colSpan = 2;
th.style.textAlign = 'left';
th.style.padding = 0;
if (field.compute)
(field.compute.bind(_self, null, _data[field.id], _form, th, tr))();
else if (field.label)
$WH.ae(th, $WH.ct(field.label));
$WH.ae(tr, th);
$WH.ae(tb, tr);
continue;
break;
case 'textarea':
var f = element = $WH.ce('textarea');
f.name = field.id;
if (field.disabled)
f.disabled = true;
f.rows = field.size[0];
f.cols = field.size[1];
td.colSpan = 2;
if (field.label)
{
th.colSpan = 2;
th.style.textAlign = 'left';
th.style.padding = 0;
td.style.padding = 0;
$WH.ae(th, $WH.ct(field.label));
$WH.ae(tr, th);
$WH.ae(tb, tr);
tr = $WH.ce('tr');
}
$WH.ae(td, f);
break;
case 'select':
var f = element = $WH.ce('select');
f.name = field.id;
if (field.size)
f.size = field.size;
if (field.disabled)
f.disabled = true;
if (field.multiple)
f.multiple = true;
for (var j = 0, len2 = options.length; j < len2; ++j)
{
var o = $WH.ce('option');
o.value = options[j];
$WH.ae(o, $WH.ct(field.options[options[j]]));
$WH.ae(f, o)
}
$WH.ae(td, f);
break;
case 'dynamic':
td.colSpan = 2;
td.style.textAlign = 'left';
td.style.padding = 0;
if (field.compute)
(field.compute.bind(_self, null, _data[field.id], _form, td, tr))();
$WH.ae(tr, td);
$WH.ae(tb, tr);
element = td;
break;
case 'checkbox':
case 'radio':
var k = 0;
element = [];
for (var j = 0, len2 = options.length; j < len2; ++j)
{
var
s = $WH.ce('span'),
f,
l,
uniqueId = 'sdfler46' + field.id + '-' + options[j];
if (j > 0 && !field.noInputBr)
$WH.ae(td, $WH.ce('br'));
l = $WH.ce('label');
l.setAttribute('for', uniqueId);
l.onmousedown = $WH.rf;
f = $WH.ce('input', { name: field.id, value: options[j], id: uniqueId });
f.setAttribute('type', field.type);
if (field.disabled)
f.disabled = true;
if (field.submitOnDblClick)
l.ondblclick = f.ondblclick = function(e) { _processForm(); };
if (field.compute)
(field.compute.bind(_self, f, _data[field.id], _form, td, tr))();
$WH.ae(l, f);
$WH.ae(l, $WH.ct(field.options[options[j]]));
$WH.ae(td, l);
element.push(f);
}
break;
default: // Textbox
var f = element = $WH.ce('input');
f.name = field.id;
if (field.size)
f.size = field.size;
if (field.disabled)
f.disabled = true;
if (field.submitOnEnter)
{
f.onkeypress = function(e) {
e = $WH.$E(e);
if (e.keyCode == 13)
_processForm();
};
}
f.setAttribute('type', field.type);
$WH.ae(td, f);
break;
}
if (field.label)
{
if (field.type == 'textarea')
{
if (field.labelAlign)
td.style.textAlign = field.labelAlign;
td.colSpan = 2;
}
else
{
if (field.labelAlign)
th.style.textAlign = field.labelAlign;
$WH.ae(th, $WH.ct(field.label));
$WH.ae(tr, th);
}
}
if (field.placeholder)
f.placeholder = field.placeholder;
if (field.type != 'checkbox' && field.type != 'radio')
{
if (field.width)
f.style.width = field.width;
if (field.compute && field.type != 'caption' && field.type != 'dynamic')
(field.compute.bind(_self, f, _data[field.id], _form, td, tr))();
}
if (field.caption)
{
var s = $WH.ce('small');
if (field.type != 'textarea')
s.style.paddingLeft = '2px';
s.className = 'q0'; // commented in 5.0?
$WH.ae(s, $WH.ct(field.caption));
$WH.ae(td, s);
}
$WH.ae(tr, td);
$WH.ae(tb, tr);
mergeCell = field.mergeCell;
_elements[field.id] = element;
}
for (var i = _template.buttons.length; i > 0; --i)
{
var
button = _template.buttons[i - 1],
a = $WH.ce('a');
a.onclick = _processForm.bind(a, button[0]);
a.className = 'dialog-' + button[0];
a.href = 'javascript:;';
$WH.ae(a, $WH.ct(button[1]));
$WH.ae(dest, a);
}
var _ = $WH.ce('div');
_.className = 'clear';
$WH.ae(dest, _);
_inited = true;
}
function _updateForm()
{
for (var i = 0, len = _template.fields.length; i < len; ++i)
{
var
field = _template.fields[i],
f = _elements[field.id];
switch (field.type)
{
case 'caption': // Do nothing
break;
case 'select':
for (var j = 0, len2 = f.options.length; j < len2; j++)
f.options[j].selected = (f.options[j].value == _data[field.id] || $WH.in_array(_data[field.id], f.options[j].value) != -1);
break;
case 'checkbox':
case 'radio':
for (var j = 0, len2 = f.length; j < len2; j++)
f[j].checked = (f[j].value == _data[field.id] || $WH.in_array(_data[field.id], f[j].value) != -1);
break;
default:
f.value = _data[field.id];
break;
}
if (field.update)
(field.update.bind(_self, null, _data[field.id], _form, f))();
}
}
function _onHide()
{
if (_template.onHide)
_template.onHide();
if (_funcs.onHide)
_funcs.onHide();
}
function _processForm(button)
{
// if (button == 'x') // aowow - button naming differs
if (button == 'cancel') // Special case
return Lightbox.hide();
for (var i = 0, len = _template.fields.length; i < len; ++i)
{
var
field = _template.fields[i],
newValue;
switch (field.type)
{
case 'caption': // Do nothing
continue;
case 'select':
newValue = _getSelectedValue(field.id);
break;
case 'checkbox':
case 'radio':
newValue = _getCheckedValue(field.id);
break;
case 'dynamic':
if (field.getValue)
{
newValue = field.getValue(field, _data, _form);
break;
}
default:
newValue = _getValue(field.id);
break;
}
if (field.validate)
{
if (!field.validate(newValue, _data, _form))
return;
}
if (newValue && typeof newValue == 'string')
newValue = $WH.trim(newValue);
_data[field.id] = newValue;
}
_submitData(button);
}
function _submitData(button)
{
var ret;
if (_onSubmit)
ret = _onSubmit(_data, button, _form);
if (_funcs.onSubmit)
ret = _funcs.onSubmit(_data, button, _form);
if (ret === undefined || ret)
Lightbox.hide();
return false;
}
function _getValue(id)
{
return _elements[id].value;
}
function _setValue(id, value)
{
_elements[id].value = value;
}
function _getSelectedValue(id)
{
var
result = [],
f = _elements[id];
for (var i = 0, len = f.options.length; i < len; i++)
{
if (f.options[i].selected)
result.push(parseInt(f.options[i].value) == f.options[i].value ? parseInt(f.options[i].value) : f.options[i].value);
}
if (result.length == 1)
result = result[0];
return result;
}
function _getCheckedValue(id)
{
var
result = [],
f = _elements[id];
for (var i = 0, len = f.length; i < len; i++)
{
if (f[i].checked)
result.push(parseInt(f[i].value) == f[i].value ? parseInt(f[i].value) : f[i].value);
}
return result;
}
};
Dialog.templates = {};
Dialog.extraFields = {};

View File

@@ -0,0 +1,252 @@
/*
Global functions related to DOM manipulation, events & forms that jQuery doesn't already provide
*/
function g_addCss(css)
{
var style = $WH.ce('style');
style.type = 'text/css';
if (style.styleSheet) // ie
style.styleSheet.cssText = css;
else
$WH.ae(style, $WH.ct(css));
var head = $WH.gE(document, 'head')[0];
$WH.ae(head, style);
}
function g_setTextNodes(n, text)
{
if (n.nodeType == 3)
n.nodeValue = text;
else
{
for (var i = 0; i < n.childNodes.length; ++i)
g_setTextNodes(n.childNodes[i], text);
}
}
function g_setInnerHtml(n, text, nodeType)
{
if (n.nodeName.toLowerCase() == nodeType)
n.innerHTML = text;
else
{
for (var i = 0; i < n.childNodes.length; ++i)
g_setInnerHtml(n.childNodes[i], text, nodeType);
}
}
function g_getFirstTextContent(node)
{
for (var i = 0; i < node.childNodes.length; ++i)
{
if (node.childNodes[i].nodeName == '#text')
return node.childNodes[i].nodeValue;
var ret = g_getFirstTextContent(node.childNodes[i]);
if (ret)
return ret;
}
return false;
}
function g_getTextContent(el)
{
var txt = '';
for (var i = 0; i < el.childNodes.length; ++i)
{
if (el.childNodes[i].nodeValue)
txt += el.childNodes[i].nodeValue;
else if (el.childNodes[i].nodeName == 'BR')
txt += '\n';
txt += g_getTextContent(el.childNodes[i]);
}
return txt;
}
function g_toggleDisplay(el)
{
el = $(el);
el.toggle();
if (el.is(':visible'))
return true;
return false;
}
function g_enableScroll(enabled)
{
if (!enabled)
{
$WH.aE(document, 'mousewheel', g_enableScroll.F);
$WH.aE(window, 'DOMMouseScroll', g_enableScroll.F);
}
else
{
$WH.dE(document, 'mousewheel', g_enableScroll.F);
$WH.dE(window, 'DOMMouseScroll', g_enableScroll.F);
}
}
g_enableScroll.F = function(e)
{
if (e.stopPropagation)
e.stopPropagation();
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
e.cancelBubble = true;
return false;
};
// from http://blog.josh420.com/archives/2007/10/setting-cursor-position-in-a-textbox-or-textarea-with-javascript.aspx
function g_setCaretPosition(elem, caretPos)
{
if (!elem)
return;
if (elem.createTextRange)
{
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
}
else if (elem.selectionStart != undefined)
{
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else
elem.focus();
}
function g_insertTag(where, tagOpen, tagClose, repFunc)
{
var n = $WH.ge(where);
n.focus();
if (n.selectionStart != null)
{
var s = n.selectionStart,
e = n.selectionEnd,
sL = n.scrollLeft,
sT = n.scrollTop;
var selectedText = n.value.substring(s, e);
if (typeof repFunc == 'function')
selectedText = repFunc(selectedText);
n.value = n.value.substr(0, s) + tagOpen + selectedText + tagClose + n.value.substr(e);
n.selectionStart = n.selectionEnd = e + tagOpen.length;
n.scrollLeft = sL;
n.scrollTop = sT;
}
else if (document.selection && document.selection.createRange)
{
var range = document.selection.createRange();
if (range.parentElement() != n)
return;
var selectedText = range.text;
if (typeof repFunc == 'function')
selectedText = repFunc(selectedText);
range.text = tagOpen + selectedText + tagClose;
/*
range.moveEnd("character", -tagClose.length);
range.moveStart("character", range.text.length);
range.select();
*/
}
if (n.onkeyup)
n.onkeyup();
}
function g_onAfterTyping(input, func, delay)
{
var timerId;
var ldsgksdgnlk623 = function()
{
if (timerId)
{
clearTimeout(timerId);
timerId = null;
}
timerId = setTimeout(func, delay);
};
input.onkeyup = ldsgksdgnlk623;
}
function g_onClick(el, func)
{
var firstEvent = 0;
function rightClk(n)
{
if (firstEvent)
{
if (firstEvent != n)
return;
}
else
firstEvent = n;
func(true);
}
el.onclick = function(e)
{
e = $WH.$E(e);
if (e._button == 2) // middle click
return true;
return false;
}
el.oncontextmenu = function()
{
rightClk(1);
return false;
}
el.onmouseup = function(e)
{
e = $WH.$E(e);
if (e._button == 3 || e.shiftKey || e.ctrlKey) // Right/Shift/Ctrl
{
rightClk(2);
}
else if (e._button == 1) // Left
{
func(false);
}
return false;
}
}
function g_isLeftClick(e)
{
e = $WH.$E(e);
return (e && e._button == 1);
}
function g_preventEmptyFormSubmission() // Used on the homepage and in the top bar
{
if (!$.trim(this.elements[0].value))
return false;
}

View File

@@ -0,0 +1,262 @@
var Favorites = new function()
{
var _type = null;
var _typeId = null;
var _favIcon = null;
this.pageInit = function(h1, type, typeId)
{
if (typeof h1 == 'string')
{
if (!document.querySelector)
return;
h1 = document.querySelector(h1);
}
if (!h1 || typeof type != 'number' || typeof typeId != 'number')
return;
_type = type;
_typeId = typeId;
createIcon(h1);
}
function initFavIcon()
{
var h1 = typeof g_pageInfo == 'object' && typeof g_pageInfo.type == 'number' && typeof g_pageInfo.typeId == 'number' ? document.querySelector('#main-contents h1') : null;
if (!h1) {
if (document.readyState !== 'complete')
setTimeout(initFavIcon, 9);
return;
}
_type = g_pageInfo.type;
_typeId = g_pageInfo.typeId;
createIcon(h1);
}
this.hasFavorites = function()
{
return !!g_favorites.length
}
this.getMenu = function()
{
var favMenu = [];
var nGroups = 0;
var nEntries = 0;
for (var i = 0, favGroup; favGroup = g_favorites[i]; i++)
{
if (!favGroup.entities.length)
continue;
nGroups++;
var subMenu = [];
for (var j = 0, favEntry; favEntry = favGroup.entities[j]; j++)
{
subMenu.push([favEntry[0], favEntry[1], '?' + g_types[favGroup.id] + '=' + favEntry[0]]);
nEntries++
}
Menu.sort(subMenu);
favMenu.push([favGroup.id, LANG.types[favGroup.id][2], , subMenu])
}
Menu.sort(favMenu);
// display short favorites as 1-dim list
if ((nGroups == 1 && nEntries <= 45) || (nGroups == 2 && nGroups + nEntries <= 30) || (nGroups > 2 && nGroups + nEntries <= 15))
{
var list = [];
for (var i = 0; subMenu = favMenu[i]; i++)
{
list.push([, subMenu[MENU_IDX_NAME]]);
for (var j = 0, subEntry; subEntry = subMenu[MENU_IDX_SUB][j]; j++)
{
var listEntry = [subEntry[MENU_IDX_ID], subEntry[MENU_IDX_NAME], subEntry[MENU_IDX_URL]];
if (subEntry[MENU_IDX_OPT])
listEntry[MENU_IDX_OPT] = subEntry[MENU_IDX_OPT];
list.push(listEntry);
}
}
favMenu = list;
}
return favMenu;
}
this.refreshMenu = function()
{
var menuRoot = $('#toplinks-favorites');
if (!menuRoot.length)
return;
var favMenu = Favorites.getMenu();
if (!favMenu.length) {
menuRoot.hide();
return;
}
Menu.add(menuRoot, favMenu);
menuRoot.show();
}
function createIcon(heading)
{
_favIcon = $('<span/>', {
'class': 'fav-star',
mouseout: $WH.Tooltip.hide
}).appendTo(heading);
if (g_user.id)
{
_favIcon.addClass('fav-star' + (isFaved(_type, _typeId) ? '-1' : '-0')).click((function(type, typeId, name) {
toggleEntry(type, typeId, name);
updateIcon(type, typeId);
$WH.Tooltip.hide();
}).bind(null, _type, _typeId, heading.textContent.trim().replace(/(.+)<.*/, '$1')));
_favIcon.mouseover(function(event) {
var tt = this.className.match(/\bfav-star-0\b/) ? LANG.addtofavorites : LANG.removefromfavorites;
$WH.Tooltip.show(this, tt, false, false, 'q2');
});
}
else
{
_favIcon.addClass('fav-star-0').click(function() {
location.href = "?account=signin";
$WH.Tooltip.hide();
}).mouseover(function(event) {
$WH.Tooltip.show(this, LANG.favorites_login + '<div class="q2" style="margin-top:10px">' + LANG.clicktologin + '</span>');
});
}
}
function updateIcon(type, typeId)
{
if (_favIcon)
{
var rmv = 'fav-star-0';
var add = 'fav-star-1';
if (!isFaved(type, typeId))
{
rmv = 'fav-star-1';
add = 'fav-star-0';
}
_favIcon.removeClass(rmv).addClass(add);
}
}
function isFaved(type, typeId)
{
var idx = getIndex(type);
if (idx == -1)
return false;
for (var i = 0, j; j = g_favorites[idx].entities[i]; i++)
if (j[0] == typeId)
return true;
return false;
}
function toggleEntry(type, typeId, name)
{
if (isFaved(type, typeId))
removeEntry(type, typeId);
else
addEntry(type, typeId, name);
}
function addEntry(type, typeId, name)
{
var idx = getIndex(type, true);
if (idx == -1)
{
/* $WH. */ console.error("Invalid type when adding entity to favorites! Type was:", type);
return;
}
for (var i = 0, j; j = g_favorites[idx].entities[i]; i++)
{
if (j[0] == typeId)
{
alert(LANG.favorites_duplicate.replace('%s', LANG.types[type][1]));
return;
}
}
sendUpdate('add', type, typeId);
g_favorites[idx].entities.push([typeId, name]);
Favorites.refreshMenu();
}
function removeEntry(type, typeId)
{
var idx = getIndex(type);
if (idx == -1)
return;
for (var i = 0, j; j = g_favorites[idx].entities[i]; i++)
{
if (j[0] == typeId)
{
sendUpdate('remove', type, typeId);
g_favorites[idx].entities.splice(i, 1);
if (!g_favorites[idx].entities.length)
g_favorites.splice(idx, 1);
Favorites.refreshMenu();
return;
}
}
}
function getIndex(type, createNew)
{
if (!LANG.types[type])
return -1;
for (var i = 0, j; j = g_favorites[i]; i++)
if (j.id == type)
return i;
if (!createNew)
return -1;
g_favorites.push({ id: type, entities: [] });
g_favorites.sort(function(a, b) { return $WH.strcmp(LANG.types[a.id], LANG.types[b.id]) });
for (i = 0; j = g_favorites[i]; i++)
if (j.id == type)
return i;
return -1;
}
function sendUpdate(method, type, typeId)
{
var data = {
id: typeId,
// sessionKey: g_user.sessionKey
};
data[method] = type;
$.post('?account=favorites', data);
}
if (document.querySelector && $WH.localStorage.isSupported())
initFavIcon();
};

View File

@@ -0,0 +1,368 @@
var g_localTime = new Date();
/* This function is to get the stars for the vote control for the guides. */
function GetStars(stars, ratable, userRating, guideId)
{
var STARS_MAX = 5;
var averageRating = stars;
if (userRating)
stars = userRating;
stars = Math.round(stars*2)/2;
var starsRounded = Math.round(stars);
var ret = $("<span>").addClass('stars').addClass('max-' + STARS_MAX).addClass('stars-' + starsRounded);
if (!g_user.id)
ratable = false;
if (ratable)
ret.addClass('ratable');
if (userRating)
ret.addClass('rated');
/* This is kinda lame but oh well */
var contents = '<span>';
var wbr = '&#8203;';
var tmp = stars;
for (var i = 1; i <= STARS_MAX; ++i)
{
if (tmp < 1 && tmp > 0)
contents += '<b class="half">';
else
contents += '<b>';
--tmp;
contents += '<i class="clickable">' + wbr + '<i></i></i>';
}
for (var i = 1; i <= STARS_MAX; ++i)
contents += '</b>';
contents += '</span>';
ret.append(contents);
if (ratable)
{
var starNumber = 0;
ret.find('i.clickable').each(function() { var starId = ++starNumber; $(this).click(function() { VoteGuide(guideId, averageRating, starId); }); })
}
if (userRating)
{
var clear = $("<span>").addClass('clear').click(function() { VoteGuide(guideId, averageRating, 0); });
ret.append(clear);
}
if (stars >= 0)
ret.mouseover(function(event) {$WH.Tooltip.showAtCursor(event, 'Rating:&nbsp;' + stars + '&nbsp;/&nbsp;' + STARS_MAX, 0, 0, 'q');}).mousemove(function(event) {$WH.Tooltip.cursorUpdate(event)}).mouseout(function() {$WH.Tooltip.hide()});
return ret;
}
function VoteGuide(guideId, oldRating, newRating)
{
// Update stars display
$('#guiderating').html(GetStars(oldRating, true, newRating, guideId));
// Vote
$.ajax({cache: false, url: '?guide=vote', type: 'POST',
error: function() {
$('#guiderating').html(GetStars(oldRating, true, 0, guideId));
alert('Voting failed. Try again later.');
},
success: function(json) {
var data = eval('(' + json + ')');
$('#guiderating-value').text(data.rating);
$('#guiderating-votes').text(GetN5(data.nvotes));
},
data: { id: guideId, rating: newRating }
});
}
/* g_enhanceTextarea and createOptionsMenuWidget are only ever used by the article/guide editor. Why are they in global.js? */
function g_enhanceTextarea (ta, opt) {
if (!(ta instanceof jQuery))
ta = $(ta);
if (ta.data("wh-enhanced") || ta.prop("tagName") != "TEXTAREA")
return;
if (typeof opt != "object")
opt = {};
var canResize = (function(el) {
if (!el.dynamicResizeOption)
return true;
if ($WH.localStorage.get("dynamic-textarea-resizing") === "true")
return true;
if ($WH.localStorage.get("dynamic-textarea-resizing") === "false")
return false;
return !el.hasOwnProperty("dynamicSizing") || el.dynamicSizing;
}).bind(null, opt);
var height = ta.height() || 500;
var wrapper = $("<div/>", { "class": "enhanced-textarea-wrapper" }).insertBefore(ta).append(ta);
if (!opt.hasOwnProperty("color"))
wrapper.addClass("enhanced-textarea-dark");
else if (opt.color)
wrapper.addClass("enhanced-textarea-" + opt.color);
if (!opt.hasOwnProperty("dynamicSizing") || opt.dynamicSizing || opt.dynamicResizeOption) {
var expander = $("<div/>", { "class": "enhanced-textarea-expander" }).prependTo(wrapper);
var dynamicResize = function(textarea, exactHeight, canResizeFn) {
if (!canResizeFn())
return;
// E.css("height", E.siblings(".enhanced-textarea-expander").html($WH.htmlentities(E.val()).replace(/\n/g, "<br>") + "<br>").height() + (D ? 14 : 34) + "px");
textarea.css("height", textarea.siblings(".enhanced-textarea-expander").html($WH.htmlentities(textarea.val()) + "<br>").height() + (exactHeight ? 14 : 34) + "px");
};
ta.bind("keydown keyup change", dynamicResize.bind(this, ta, opt.exactLineHeights, canResize));
dynamicResize(ta, opt.exactLineHeights, canResize);
var setWidth = function(el) { el.css("width", el.parent().width() + "px"); };
setWidth(expander);
setTimeout(setWidth.bind(null, expander), 1);
if (!opt.dynamicResizeOption || (opt.dynamicResizeOption && canResize()))
wrapper.addClass("enhanced-textarea-dynamic-sizing");
}
if (!opt.hasOwnProperty("focusChanges") || opt.focusChanges)
wrapper.addClass("enhanced-textarea-focus-changes");
if (opt.markup) {
var _markupMenu = $("<div/>", { "class": "enhanced-textarea-markup-wrapper" }).prependTo(wrapper);
var _segments = $("<div/>", { "class": "enhanced-textarea-markup" }).appendTo(_markupMenu);
var _toolbar = $("<div/>", { "class": "enhanced-textarea-markup-segment" }).appendTo(_segments);
var _menu = $("<div/>", { "class": "enhanced-textarea-markup-segment" }).appendTo(_segments);
if (opt.markup == "inline")
ar_AddInlineToolbar(ta.get(0), _toolbar.get(0), _menu.get(0));
else
ar_AddToolbar(ta.get(0), _toolbar.get(0), _menu.get(0));
if (opt.dynamicResizeOption) {
var _dynResize = $("<div/>", { "class": "enhanced-textarea-markup-segment" }).appendTo(_segments);
var _lblDynResize = $("<label/>").appendTo(_dynResize);
var _iDynResize = $("<input/>", { type: "checkbox", checked: canResize() }).appendTo(_lblDynResize);
_iDynResize.change((function(_opt, taWrapper, textarea, resizable, areaHeight, dynResizeFn) {
var isChecked = this.is(":checked");
$WH.localStorage.set("dynamic-textarea-resizing", JSON.stringify(isChecked));
if (isChecked) {
taWrapper.addClass("enhanced-textarea-dynamic-sizing");
dynResizeFn(textarea, _opt.exactLineHeights, resizable);
}
else {
taWrapper.removeClass("enhanced-textarea-dynamic-sizing");
textarea.css("height", areaHeight + "px");
}
}).bind(_iDynResize, opt, wrapper, ta, canResize, height, dynamicResize));
$("<span/>", { text: LANG.autoresizetextbox }).appendTo(_lblDynResize);
}
if (opt.scrollingMarkup) {
if (g_enhanceTextarea.scrollerCount)
g_enhanceTextarea.scrollerCount++;
else
g_enhanceTextarea.scrollerCount = 1;
var cssClassA = "fixable-markup-controls-" + g_enhanceTextarea.scrollerCount;
var cssClassB = "fixed-markup-controls-" + g_enhanceTextarea.scrollerCount;
var getBGColor = function(el) {
var color = el.css("backgroundColor");
if (color == "rgba(0, 0, 0, 0)" || color == "transparent")
return getBGColor(el.parent());
else
return color;
};
var bgColor = getBGColor(_segments);
for (var css, i = 0; (css = window.document.styleSheets[i]) && css.href; i++) {}
if (!css) {
window.document.head.appendChild(document.createElement("style"));
css = window.document.styleSheets[i];
}
css.insertRule("." + cssClassB + " ." + cssClassA + " .enhanced-textarea-markup {background:" + bgColor + ";padding-bottom:5px;padding-top:10px;position:fixed;top:0;z-index:3}", css.cssRules.length);
css.insertRule(".touch-device ." + cssClassB + " ." + cssClassA + " .enhanced-textarea-markup {padding-top:50px}", css.cssRules.length);
_markupMenu.addClass(cssClassA);
var toggleFixedStyles = function(menuContainer, taContainer, cssClass, offset) {
var pageY = this.scrollY || this.pageYOffset || 0;
if (pageY > menuContainer.offset().top - 10 - offset && pageY < taContainer.offset().top + taContainer.height() - 100 - offset)
$("body").addClass(cssClass);
else
$("body").removeClass(cssClass);
};
$(window).scroll(toggleFixedStyles.bind(window, _markupMenu, wrapper, cssClassB, 0));
toggleFixedStyles.call(window, _markupMenu, wrapper, cssClassB, 0);
var setSize = (function(D, E) {
E.css("width", D.width() + "px");
D.css("height", E.height() + "px");
}).bind(null, _markupMenu, _segments);
setSize();
$(window).on("resize", setSize);
$(function() { setTimeout(setSize, 2000) })
}
}
ta.data("wh-enhanced", true);
};
$WH.createOptionsMenuWidget = function (id, txt, opt) {
var chevron = $WH.createOptionsMenuWidget.chevron;
if (opt.noChevron)
chevron = '';
var container = $WH.ce('span');
container.id = 'options-menu-widget-' + id;
container.className = 'options-menu-widget ' + container.id;
container.innerHTML = txt + chevron;
if (opt.id)
container.id = opt.id;
if (opt.className)
container.className += ' ' + opt.className;
if (opt.options instanceof Array) {
var widgetmenu = [];
for (var itr = 0, submenu; submenu = opt.options[itr]; itr++) {
var menu = [itr, submenu[MENU_IDX_NAME]];
if ((typeof opt.selected == 'number' || typeof opt.selected == 'string') && opt.selected == submenu[MENU_IDX_ID]) {
container.innerHTML = submenu[MENU_IDX_NAME] + chevron;
if (submenu[MENU_IDX_SUB]) {
switch (typeof submenu[MENU_IDX_SUB].className) {
case 'string':
$.data(container, 'options-menu-widget-class', submenu[MENU_IDX_SUB].className);
container.className += ' ' + submenu[MENU_IDX_SUB].className;
break;
case 'function':
$.data(container, 'options-menu-widget-class', submenu[MENU_IDX_SUB].className(submenu, true));
container.className += ' ' + submenu[MENU_IDX_SUB].className(submenu, true);
break;
}
}
}
if (submenu[MENU_IDX_URL]) {
menu.push(function (chevron, container, submenu, opt) {
switch (typeof submenu[MENU_IDX_URL]) {
case 'string':
window.location = submenu[MENU_IDX_URL];
break;
case 'function':
if (typeof opt.updateWidgetText == 'undefined' || opt.updateWidgetText) {
container.innerHTML = submenu[MENU_IDX_NAME] + chevron;
var o = $.data(container, 'options-menu-widget-class');
if (o)
container.className = container.className.replace(new RegExp(' *\\b' + o + '\\b'), '');
if (submenu[MENU_IDX_SUB]) {
switch (typeof submenu[MENU_IDX_SUB].className) {
case 'string':
$.data(container, 'options-menu-widget-class', submenu[MENU_IDX_SUB].className);
container.className += ' ' + submenu[MENU_IDX_SUB].className;
break;
case 'function':
$.data(container, 'options-menu-widget-class', submenu[MENU_IDX_SUB].className(submenu, true));
container.className += ' ' + submenu[MENU_IDX_SUB].className(submenu, true);
break;
}
}
}
submenu[MENU_IDX_URL](container, submenu);
break;
}
}.bind(null, chevron, Menu.add, submenu, opt))
}
else if (!submenu[MENU_IDX_SUB] || !submenu[MENU_IDX_SUB].menu)
menu[0] = null;
menu[MENU_IDX_OPT] = {};
if (submenu[MENU_IDX_SUB]) {
switch (typeof submenu[MENU_IDX_SUB].className) {
case 'string':
menu[MENU_IDX_OPT].className = submenu[MENU_IDX_SUB].className;
break;
case 'function':
menu[MENU_IDX_OPT].className = submenu[MENU_IDX_SUB].className.bind(null, submenu, false);
break;
}
switch (typeof submenu[MENU_IDX_SUB].column) {
case 'number':
case 'string':
menu[MENU_IDX_OPT].column = submenu[MENU_IDX_SUB].column;
break;
case 'function':
menu[MENU_IDX_OPT].column = submenu[MENU_IDX_SUB].column.bind(null, submenu);
break;
}
switch (typeof submenu[MENU_IDX_SUB].tinyIcon) {
case 'string':
menu[MENU_IDX_OPT].tinyIcon = submenu[MENU_IDX_SUB].tinyIcon;
break;
case 'function':
menu[MENU_IDX_OPT].tinyIcon = submenu[MENU_IDX_SUB].tinyIcon.bind(null, submenu);
break;
}
switch (typeof submenu[MENU_IDX_SUB].fontIcon) {
case 'string':
menu[MENU_IDX_OPT].fontIcon = submenu[MENU_IDX_SUB].fontIcon;
break;
case 'function':
menu[MENU_IDX_OPT].fontIcon = submenu[MENU_IDX_SUB].fontIcon.bind(null, submenu);
break;
}
if (typeof submenu[MENU_IDX_SUB].isChecked == 'function')
menu[MENU_IDX_OPT].checkedFunc = submenu[MENU_IDX_SUB].isChecked.bind(null, submenu);
if (typeof submenu[MENU_IDX_SUB].menu == 'object' && submenu[MENU_IDX_SUB].menu instanceof Array)
Menu.setSubmenu(menu, submenu[MENU_IDX_SUB].menu); // <-- n.d. !
}
widgetmenu.push(menu);
}
container.menu = widgetmenu;
if (opt.menuOnClick) {
container.onmousedown = $WH.rf;
Menu.add(container, widgetmenu, { showAtElement: true });
}
else
Menu.add(container, widgetmenu);
}
if (opt.target)
$(opt.target).append(container);
else
return container;
};
$WH.createOptionsMenuWidget.chevron = ' <i class="fa fa-chevron-down fa-color-gray">~</i>';

View File

@@ -0,0 +1,404 @@
var Icon = {
sizes: ['small', 'medium', 'large'],
sizes2: [18, 36, 56],
sizeIds: {
small: 0,
medium: 1,
large: 2
},
premiumOffsets: [[-56, -36], [-56, 0], [0, 0]],
premiumBorderClasses: ['-premium', '-gold', '', '-premiumred', '-red'],
STANDARD_BORDER: 2,
privilegeBorderClasses: {
uncommon: '-q2',
rare: '-q3',
epic: '-q4',
legendary: '-q5'
},
idLookupCache: {},
create: function(name, size, DELETEME, url, num, qty, noBorder, rel, span)
{
var
icon = $WH.ce(span ? 'span' : 'div'),
image = $WH.ce('ins'),
tile = $WH.ce('del');
if (size == null)
size = 1;
icon.className = 'icon' + Icon.sizes[size];
$WH.ae(icon, image);
if (!noBorder)
$WH.ae(icon, tile);
Icon.setTexture(icon, size, name);
if (url)
{
var a = $WH.ce('a');
a.href = url;
if (url.indexOf('wowhead.com') == -1 && url.substr(0, 5) == 'http:')
a.target = "_blank";
$WH.ae(icon, a);
}
else if (name)
{
var _ = icon.firstChild.style;
var avatarIcon = (_.backgroundImage.indexOf('/avatars/') != -1);
if (!avatarIcon)
{
icon.onclick = Icon.onClick;
if (url !== false)
{
var a = $WH.ce('a');
a.href = "javascript:;";
$WH.ae(icon, a);
}
}
}
if (rel && typeof a != 'undefined')
a.rel = rel;
Icon.setNumQty(icon, num, qty);
return icon;
},
createUser: function(avatar, avatarMore, size, url, premiumLevel, noBorder, reputationLevel)
{
if (avatar == 2)
avatarMore = g_staticUrl + '/uploads/avatars/' + avatarMore + '.jpg';
var icon = Icon.create(avatarMore, size, null, url, null, null, noBorder);
if ((premiumLevel != Icon.STANDARD_BORDER) && Icon.premiumBorderClasses[premiumLevel])
icon.className += ' ' + icon.className + Icon.premiumBorderClasses[premiumLevel];
else if (reputationLevel && Icon.privilegeBorderClasses.hasOwnProperty(reputationLevel))
icon.className += ' ' + icon.className + Icon.privilegeBorderClasses[reputationLevel];
if (avatar == 2)
Icon.moveTexture(icon, size, Icon.premiumOffsets[size][0], Icon.premiumOffsets[size][1], true);
return icon;
},
getIdFromName: function (name, fn)
{
if (Icon.idLookupCache.hasOwnProperty(name))
{
window.requestAnimationFrame((function () {
fn(Icon.idLookupCache[name] || undefined)
}));
return;
}
$.ajax({
url: '?icon=get-id-from-name',
data: { name: name },
dataType: 'json',
success: function (json) {
Icon.idLookupCache[name] = json;
fn(json || undefined);
}
})
},
getPrivilegeBorder: function(reputation)
{
var buff = false;
if (reputation >= CFG_REP_REQ_BORDER_UNCOMMON)
buff = 'uncommon';
if (reputation >= CFG_REP_REQ_BORDER_RARE)
buff = 'rare';
if (reputation >= CFG_REP_REQ_BORDER_EPIC)
buff = 'epic';
if (reputation >= CFG_REP_REQ_BORDER_LEGENDARY)
buff = 'legendary';
return buff;
},
setTexture: function(icon, size, name)
{
if (!name)
return;
var _ = icon.firstChild.style;
if (name.indexOf('/') != -1 || name.indexOf('?') != -1)
_.backgroundImage = 'url(' + name + ')';
else
{
_.backgroundImage = 'url(' + g_staticUrl + '/images/wow/icons/' + Icon.sizes[size] + '/' + name.toLowerCase() + '.jpg)';
}
Icon.moveTexture(icon, size, 0, 0);
},
moveTexture: function(icon, size, x, y, exact)
{
var _ = icon.firstChild.style;
if (x || y)
{
if (exact)
_.backgroundPosition = x + 'px ' + y + 'px';
else
_.backgroundPosition = (-x * Icon.sizes2[size]) + 'px ' + (-y * Icon.sizes2[size]) + 'px';
}
else if (_.backgroundPosition)
_.backgroundPosition = '';
},
setNumQty: function(icon, num, qty)
{
var _ = $WH.gE(icon, 'span');
for (var i = 0, len = _.length; i < len; ++i)
if (_[i])
$WH.de(_[i]);
if (num != null && ((num > 1 && num < 2147483647) || (num.length && num != '0' && num != '1')))
{
_ = g_createGlow(num, 'q1');
_.style.right = '0';
_.style.bottom = '0';
_.style.position = 'absolute';
$WH.ae(icon, _);
}
if (qty != null && qty > 0)
{
_ = g_createGlow('(' + qty + ')', 'q');
_.style.left = '0';
_.style.top = '0';
_.style.position = 'absolute';
$WH.ae(icon, _);
}
},
getLink: function(icon)
{
return $WH.gE(icon, 'a')[0];
},
showIconName: function(x)
{
if (x.firstChild)
{
var _ = x.firstChild.style;
if (_.backgroundImage.length && (_.backgroundImage.indexOf(g_staticUrl) >= 4 || g_staticUrl == ''))
{
var
start = _.backgroundImage.lastIndexOf('/'),
end = _.backgroundImage.indexOf('.jpg');
if (start != -1 && end != -1)
Icon.displayIcon(_.backgroundImage.substring(start + 1, end));
}
}
},
onClick: function()
{
Icon.showIconName(this);
},
displayIcon: function(icon)
{
if (!Dialog.templates.icondisplay)
{
var w = 364;
switch (Locale.getId())
{
case LOCALE_ESES:
w = 380;
break;
case LOCALE_RURU:
w = 384;
break;
}
Dialog.templates.icondisplay = {
title: LANG.icon,
width: w,
buttons: [['arrow', LANG.original], ['cancel', LANG.close]],
fields:
[
{
id: 'icon',
label: LANG.dialog_imagename,
required: 1,
type: 'text',
labelAlign: 'left',
compute: function(field, value, form, td)
{
var wrapper = $WH.ce('div');
td.style.width = '300px';
wrapper.style.position = 'relative';
wrapper.style.cssFloat = 'left';
wrapper.style.paddingRight = '6px';
field.style.width = '200px';
var divIcon = this.iconDiv = $WH.ce('div');
divIcon.style.position = 'absolute';
divIcon.style.top = '-12px';
divIcon.style.right = '-70px';
divIcon.update = function() {
setTimeout(function() {
field.focus();
field.select();
}, 10);
$WH.ee(divIcon);
$WH.ae(divIcon, Icon.create(field.value, 2));
};
$WH.ae(divIcon, Icon.create(value, 2));
$WH.ae(wrapper, divIcon);
$WH.ae(wrapper, field);
$WH.ae(td, wrapper);
}
},
{
id: 'iconId',
label: 'ID' + LANG.colon,
type: 'text',
labelAlign: 'left',
compute: function (field, value, form, td)
{
// td.classList.add('icon-dialog-content'); // aowow - style not yet defined
field.style.width = '200px'; // replace with hard value
field.value = '';
this.iconIdField = field;
}
},
{
id: 'location',
label: " ",
required: 1,
type: 'caption',
compute: function(field, value, form, th, tr)
{
$WH.ee(th);
th.style.padding = '3px 3px 0 3px';
th.style.lineHeight = '17px';
th.style.whiteSpace = 'normal';
var wrapper = $WH.ce('div');
wrapper.style.position = 'relative';
wrapper.style.width = '250px';
var span = $WH.ce('span');
var text = LANG.dialog_seeallusingicon;
text = text.replace('$1', '<a href="?items&filter=cr=142;crs=0;crv=' + this.data.icon + '">' + LANG.types[3][3] + '</a>');
text = text.replace('$2', '<a href="?spells&filter=cr=15;crs=0;crv=' + this.data.icon + '">' + LANG.types[6][3] + '</a>');
text = text.replace('$3', '<a href="?achievements&filter=cr=10;crs=0;crv=' + this.data.icon + '">' + LANG.types[10][3] + '</a>');
span.innerHTML = text;
$WH.ae(wrapper, span);
$WH.ae(th, wrapper);
}
}
],
onInit: function(form)
{
this.updateIcon = this.template.updateIcon.bind(this, form);
},
onShow: function(form)
{
this.updateIcon();
if (location.hash && location.hash.indexOf('#icon') == -1)
this.oldHash = location.hash;
else
this.oldHash = '';
var hash = '#icon';
// Add icon name on all pages but item, spell and achievement pages (where the name is already available).
var nameDisabled = ($WH.isset('g_pageInfo') && g_pageInfo.type && $WH.in_array([3, 6, 10], g_pageInfo.type) == -1);
if (!nameDisabled)
hash += ':' + this.data.icon;
location.hash = hash;
},
onHide: function(form)
{
if (this.oldHash)
location.hash = this.oldHash;
else
location.hash = '#.';
},
updateIcon: function(form)
{
this.iconDiv.update();
var i = this.iconIdField;
Icon.getIdFromName(form.icon.value, (function (x) { i.value = x || ''; }));
},
onSubmit: function(unused, data, button, form)
{
if (button == 'arrow')
{
var win = window.open(g_staticUrl + '/images/wow/icons/large/' + data.icon.toLowerCase() + '.jpg', '_blank');
win.focus();
return false;
}
return true;
}
};
}
if (!Icon.icDialog)
Icon.icDialog = new Dialog();
Icon.icDialog.show('icondisplay', { data: { icon: icon } });
},
checkPound: function()
{
if (location.hash && location.hash.indexOf('#icon') == 0)
{
var parts = location.hash.split(':');
var icon = false;
if (parts.length == 2)
{
icon = parts[1];
}
else if (parts.length == 1 && $WH.isset('g_pageInfo'))
{
switch (g_pageInfo.type)
{
case 3: // Item
icon = g_items[g_pageInfo.typeId].icon.toLowerCase();
break;
case 6: // Spell
icon = g_spells[g_pageInfo.typeId].icon.toLowerCase();
break;
case 10: // Achievement
icon = g_achievements[g_pageInfo.typeId].icon.toLowerCase();
break;
}
}
if (icon)
Icon.displayIcon(icon);
}
}
};
$(document).ready(Icon.checkPound);

View File

@@ -0,0 +1,161 @@
var Lightbox = new function()
{
var overlay,
outer,
inner,
divs = {},
funcs = {},
prepared,
lastId;
function hookEvents()
{
$WH.aE(overlay, 'click', hide);
$WH.aE(document, 'keydown', onKeyDown);
$WH.aE(window, 'resize', onResize);
}
function unhookEvents()
{
$WH.dE(overlay, 'click', hide);
$WH.dE(document, 'keydown', onKeyDown);
$WH.dE(window, 'resize', onResize);
}
function prepare()
{
if (prepared)
return;
prepared = 1;
var dest = document.body;
overlay = $WH.ce('div');
overlay.className = 'lightbox-overlay';
outer = $WH.ce('div');
outer.className = 'lightbox-outer';
inner = $WH.ce('div');
inner.className = 'lightbox-inner';
overlay.style.display = outer.style.display = 'none';
$WH.ae(dest, overlay);
$WH.ae(outer, inner);
$WH.ae(dest, outer);
}
function onKeyDown(e)
{
e = $WH.$E(e);
switch (e.keyCode)
{
case 27: // Escape
hide();
break;
}
}
function onResize(fake)
{
if (fake != 1234)
{
if (funcs.onResize)
funcs.onResize();
}
overlay.style.height = document.body.offsetHeight + 'px';
}
function hide()
{
if (!prepared)
return;
unhookEvents();
if (funcs.onHide)
funcs.onHide();
overlay.style.display = outer.style.display = 'none';
g_enableScroll(true);
}
function reveal()
{
overlay.style.display = outer.style.display = divs[lastId].style.display = '';
Lightbox.setSize(inner.offsetWidth, inner.offsetHeight, 1);
}
this.setSize = function(w, h, auto)
{
inner.style.visibility = 'hidden';
if (!auto)
{
inner.style.width = w + 'px';
if (h)
inner.style.height = h + 'px';
}
inner.style.left = -parseInt(w / 2) + 'px';
if (h)
inner.style.top = -parseInt(h / 2) + 'px';
inner.style.visibility = 'visible';
}
this.show = function(id, _funcs, opt) {
funcs = _funcs || {};
prepare();
hookEvents();
if (lastId != id && divs[lastId] != null)
divs[lastId].style.display = 'none';
lastId = id;
var first = 0,
d;
if (divs[id] == null)
{
first = 1;
d = $WH.ce('div');
$WH.ae(inner, d);
divs[id] = d;
}
else
d = divs[id];
if (funcs.onShow)
funcs.onShow(d, first, opt);
onResize(1234);
reveal();
g_enableScroll(false);
}
this.reveal = function()
{
reveal();
}
this.hide = function()
{
hide();
}
this.isVisible = function()
{
return (overlay && overlay.style.display != 'none');
}
};

View File

@@ -0,0 +1,38 @@
function Line(x1, y1, x2, y2, type)
{
var left = Math.min(x1, x2),
right = Math.max(x1, x2),
top = Math.min(y1, y2),
bottom = Math.max(y1, y2),
width = (right - left),
height = (bottom - top),
length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
radian = Math.atan2(height, width),
sinTheta = Math.sin(radian),
cosTheta = Math.cos(radian);
var $line = $WH.ce('span');
$line.className = 'line';
$line.style.top = top.toFixed(2) + 'px';
$line.style.left = left.toFixed(2) + 'px';
$line.style.width = width.toFixed(2) + 'px';
$line.style.height = height.toFixed(2) + 'px';
var v = $WH.ce('var');
v.style.width = length.toFixed(2) + 'px';
v.style.OTransform = 'rotate(' + radian + 'rad)';
v.style.MozTransform = 'rotate(' + radian + 'rad)';
v.style.webkitTransform = 'rotate(' + radian + 'rad)';
v.style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=" + cosTheta + ', M12=' + (-1 * sinTheta) + ', M21=' + sinTheta + ', M22=' + cosTheta + ')';
$WH.ae($line, v);
if (!(x1 == left && y1 == top) && !(x2 == left && y2 == top))
$line.className += ' flipped';
if (type != null)
$line.className += ' line-' + type;
return $line;
}

View File

@@ -0,0 +1,138 @@
var Links = new function()
{
var dialog = null;
var oldHash = null;
/* aowow - official armory is gone
* var validArmoryTypes = {
* item: 1
* };
*/
var extraTypes = {
29: 'icondb'
};
this.onShow = function()
{
if (location.hash && location.hash != '#links')
oldHash = location.hash;
location.replace('#links');
}
this.onHide = function()
{
if (oldHash && (oldHash.indexOf('screenshots:') == -1 || oldHash.indexOf('videos:') == -1))
location.replace(oldHash);
else
location.replace('#.');
}
this.show = function(opt)
{
if (!opt || !opt.type || !opt.typeId)
return;
var type = g_types[opt.type];
if (!dialog)
this.init();
/* aowow - the official wow armory ... good times
* if (validArmoryTypes[type] && Dialog.templates.links.fields[1].id != 'armoryurl')
* {
* Dialog.templates.links.fields.splice(1, 0, {
* id: 'armoryurl',
* type: 'text',
* label: 'Armory URL',
* size: 40
* });
* }
*/
var link = '';
if (opt.linkColor && opt.linkId && opt.linkName)
{
link = g_getIngameLink(opt.linkColor, opt.linkId, opt.linkName);
if (opt.sound)
link = '/script PlaySoundFile("' + opt.sound + '", "master")';
// link = '/script PlaySoundKitID(' + opt.sound + ')'; aowow: lua fn not available in 3.3.5
if (Dialog.templates.links.fields[Dialog.templates.links.fields.length - 2].id != 'ingamelink')
{
Dialog.templates.links.fields.splice(Dialog.templates.links.fields.length - 1, 0, {
id: 'ingamelink',
type: 'text',
label: 'Ingame Link',
size: 40
});
}
}
var data = {
'wowheadurl': g_host +'/?' + type + '=' + opt.typeId,
// 'armoryurl': 'http://us.battle.net/wow/en/' + type + '/' + opt.typeId,
'ingamelink': link,
'markuptag': '[' + (extraTypes[opt.type] || type) + '=' + opt.typeId + ']'
};
dialog.show('links', {
data: data,
onShow: this.onShow,
onHide: this.onHide,
onSubmit: function() { return false; }
});
}
this.checkPound = function()
{
if (location.hash && location.hash == '#links')
{
$('#open-links-button').click();
}
}
this.init = function()
{
dialog = new Dialog();
Dialog.templates.links = {
title: LANG.pr_menu_links || 'Links',
width: 425,
buttons: [['cancel', LANG.close]],
fields:
[
{
id: 'wowheadurl',
type: 'text',
label: 'Aowow URL',
size: 40
},
{
id: 'markuptag',
type: 'text',
label: 'Markup Tag',
size: 40
}
],
onInit: function(form)
{
},
onShow: function(form)
{
setTimeout(function() {
$(form.ingamelink).select();
}, 50);
setTimeout(Lightbox.reveal, 100);
}
};
};
$(document).ready(this.checkPound);
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,368 @@
var LiveSearch = new function()
{
var currentTextbox,
lastSearch = {},
lastDiv,
timer,
prepared,
container,
cancelNext,
hasData,
summary,
selection,
LIVESEARCH_DELAY = 500; // In milliseconds;
function setText(textbox, txt)
{
textbox.value = txt;
textbox.selectionStart = textbox.selectionEnd = txt.length;
}
function colorDiv(div, fromOver)
{
if (lastDiv)
lastDiv.className = lastDiv.className.replace('live-search-selected', '');
lastDiv = div;
lastDiv.className += ' live-search-selected';
selection = div.i;
if (!fromOver)
{
show();
setTimeout(setText.bind(0, currentTextbox, g_getTextContent(div.firstChild.firstChild.childNodes[1])), 1);
cancelNext = 1;
}
}
function aOver()
{
colorDiv(this.parentNode.parentNode, 1);
}
function isVisible()
{
if (!container)
return false;
return container.style.display != 'none';
}
function adjust(fromResize)
{
if (fromResize == 1 && !isVisible())
return;
if (currentTextbox == null)
return;
var c = $WH.ac(currentTextbox);
container.style.left = (c[0] - 2) + 'px';
container.style.top = (c[1] + currentTextbox.offsetHeight + 1) + 'px';
container.style.width = currentTextbox.offsetWidth + 'px';
}
function prepare()
{
if (prepared)
return;
prepared = 1;
container = $WH.ce('div');
container.className = 'live-search';
container.style.display = 'none';
$WH.ae($WH.ge('layers'), container);
$WH.aE(window, 'resize', adjust.bind(0, 1));
$WH.aE(document, 'click', hide);
}
function show()
{
if (container && !isVisible())
{
adjust();
// Same animation as in Menu.js
$(container).css({ opacity: '0' })
.show()
.animate({ opacity: '1' }, 'fast', null, doneShowing);
}
}
function doneShowing(a)
{
$(this).css('opacity', ''); // Remove opacity once animation is over to prevent a bug in IE8
}
function hide(e)
{
if (e && !g_isLeftClick(e))
return;
if (container)
container.style.display = 'none';
}
function highlight(match, $1)
{
// $1 containts % in matches with %s, which we don't want to replace
return ($1 ? '<b><u>' + match + '</u></b>' : match);
// aowow - why was the ternary reversed? Also how can it not match .. we explicitly searched for it.
// return ($1 ? match : '<b><u>' + match + '</u></b>');
}
function display(textbox, search, suggz, dataz)
{
prepare();
show();
lastA = null;
hasData = 1;
selection = null;
while (container.firstChild)
$WH.de(container.firstChild);
search = search.replace(/[^a-z0-9\-]/gi, ' ');
search = $WH.trim(search.replace(/\s+/g, ' '));
var regex = g_createOrRegex(search, (search == 's' ? '[%]' : null));
for (var i = 0, len = suggz.length; i < len; ++i)
{
var pos = suggz[i].lastIndexOf('(');
if (pos != -1)
suggz[i] = suggz[i].substr(0, pos - 1);
var type = dataz[i][0],
typeId = dataz[i][1],
param1 = dataz[i][2],
param2 = dataz[i][3],
a = $WH.ce('a'),
sp = $WH.ce('i'),
sp2 = $WH.ce('span'),
div = $WH.ce('div'),
div2 = $WH.ce('div');
div.i = i;
a.onmouseover = aOver;
a.href = '?' + g_types[type] + '=' + typeId;
// aowow - so statistic is an actual dbtype..?
// a.href = '/' + (type == 10 && param2 ? 'statistic' : g_types[type]) + '=' + typeId;
if (textbox._append)
a.rel += textbox._append;
if (type == 1 && param1 != null)
div.className += ' live-search-icon-boss';
else if (type == 3 && param2 != null)
a.className += ' q' + param2;
else if (type == 4 && param1 != null)
a.className += ' q' + param1;
else if (type == 13)
a.className += ' c' + typeId;
if ((type == 3 || type == 6 || type == 9 || type == 10 || type == 13 || type == 14 || type == 15 || type == 17) && param1)
{
div.className += ' live-search-icon';
div.style.backgroundImage = 'url(' + g_staticUrl + '/images/wow/icons/small/' + param1.toLowerCase() + '.jpg)';
}
else if ((type == 5 || type == 11) && param1 >= 1 && param1 <= 2)
{
div.className += ' live-search-icon-quest-' + (param1 == 1 ? 'alliance' : 'horde');
}
$WH.ae(sp, $WH.ct(LANG.types[type][0]));
$WH.ae(a, sp);
var buffer = suggz[i];
buffer = buffer.replace(regex, highlight);
if (type == 11)
buffer = buffer.replace('%s', '<span class="q0">&lt;'+ LANG.name + '&gt;</span>');
sp2.innerHTML = buffer;
$WH.ae(a, sp2);
if (type == 6 && param2)
$WH.ae(a, $WH.ct(' (' + param2 + ')'));
$WH.ae(div2, a);
$WH.ae(div, div2);
$WH.ae(container, div);
}
}
function receive(xhr, opt)
{
var text = xhr.responseText;
if (text.charAt(0) != '[' || text.charAt(text.length - 1) != ']')
return;
var a = eval(text);
var search = a[0];
if (search == opt.search)
{
if (a.length == 8)
display(opt.textbox, search, a[1], a[7]);
else
hide();
}
}
function fetch(textbox, search)
{
var url = '?search=' + $WH.urlencode(search);
if (textbox._type)
url += '&json&type=' + textbox._type;
else
url += '&opensearch';
new Ajax(url, {
onSuccess: receive,
textbox: textbox,
search: search
});
}
function preFetch(textbox, search)
{
if (cancelNext)
{
cancelNext = 0;
return;
}
hasData = 0;
if (timer > 0)
{
clearTimeout(timer);
timer = 0;
}
timer = setTimeout(fetch.bind(0, textbox, search), LIVESEARCH_DELAY);
}
function cycle(dir)
{
if (!isVisible())
{
if (hasData)
show();
return;
}
var firstNode = (container.childNodes[0].nodeName == 'EM' ? container.childNodes[3] : container.firstChild);
var bakDiv = dir ? firstNode : container.lastChild;
if (lastDiv == null)
colorDiv(bakDiv);
else
{
var div = dir ? lastDiv.nextSibling : lastDiv.previousSibling;
if (div)
{
if (div.nodeName == 'STRONG')
div = container.lastChild;
colorDiv(div);
}
else
{
colorDiv(bakDiv);
}
}
}
function onKeyUp(e)
{
e = $WH.$E(e);
var textbox = e._target;
var search = $WH.trim(textbox.value.replace(/\s+/g, ' '));
if (search == lastSearch[textbox.id])
return;
lastSearch[textbox.id] = search;
if (search.length)
preFetch(textbox, search);
else
hide();
}
function onKeyDown(e)
{
e = $WH.$E(e);
var textbox = e._target;
switch (e.keyCode)
{
case 27: // Escape
hide();
break;
case 38: // Up
cycle(0);
break;
case 40: // Down
cycle(1);
break;
}
}
function onFocus(e)
{
e = $WH.$E(e);
var textbox = e._target;
if (textbox != document)
currentTextbox = textbox;
}
this.attach = function(textbox)
{
textbox = $(textbox);
if (!textbox.length)
return;
textbox = textbox[0];
if (textbox.getAttribute('autocomplete') == 'off')
return;
textbox.setAttribute('autocomplete', 'off');
$WH.aE(textbox, 'focus', onFocus);
$WH.aE(textbox, 'keyup', onKeyUp);
$WH.aE(textbox, 'keydown', onKeyDown);
};
this.reset = function(textbox)
{
lastSearch[textbox.id] = null;
textbox.value = '';
hasData = 0;
hide();
};
this.hide = function()
{
hide();
};
};

View File

@@ -16,43 +16,51 @@ var Locale = {
// All
locales: /*setup:locales*/,
getAll: function() {
getAll: function()
{
var result = [];
for (var id in Locale.locales) {
for (var id in Locale.locales)
{
result.push(Locale.locales[id]);
}
return result;
},
getAllByName: function() {
getAllByName: function()
{
var result = Locale.getAll();
result.sort(function(a, b) {
result.sort(function(a, b)
{
return $WH.strcmp(a.description, b.description);
});
return result;
},
getId: function() {
getId: function()
{
return Locale.current.id;
},
getName: function() {
getName: function()
{
var localeId = Locale.getId();
return Locale.locales[localeId].name;
},
get: function() {
get: function()
{
var localeId = Locale.getId();
return Locale.locales[localeId];
},
set: function(localeId) {
set: function(localeId)
{
$.extend(Locale.current, Locale.locales[localeId]);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,293 @@
var MapViewer = new function()
{
var imgWidth,
imgHeight,
scale,
desiredScale,
mapper,
oldOnClick,
oldOnUpdate,
oldParent,
oldSibling,
tempParent,
placeholder,
container,
screen,
imgDiv,
aCover;
function computeDimensions()
{
var availHeight = Math.max(50, Math.min(618, $WH.g_getWindowSize().h - 72));
desiredScale = 1;
scale = 1;//Math.min(1, availHeight / 515);
// no scaling because it doesnt work with background images
if (desiredScale > 1)
desiredScale = 1;
if (scale > 1)
scale = 1;
imgWidth = Math.round(scale * 772);
imgHeight = Math.round(scale * 515);
var lbWidth = Math.max(480, imgWidth);
Lightbox.setSize(lbWidth + 20, imgHeight + 52);
}
function getPound(extra)
{
var extraBits = function(map, s)
{
s += ':' + map.zone;
if (map.level)
s += '.' + map.level;
return s;
};
var buff = '#map';
if (tempParent)
buff += '=' + mapper.getLink();
else if (Mapper.zoneDefaultLevel[mapper.zone])
{
if (Mapper.zoneDefaultLevel[mapper.zone] != mapper.level)
buff = extraBits(mapper, buff);
}
else if (mapper.level != 0)
buff = extraBits(mapper, buff);
else if ((!$WH.isset('g_mapperData') || !g_mapperData[mapper.zone]) && (!$WH.isset('g_mapper_data') || !g_mapper_data[mapper.zone]))
buff = extraBits(mapper, buff);
return buff;
}
function onUpdate()
{
if (oldOnUpdate)
oldOnUpdate(mapper);
location.replace(getPound(true));
}
function render(resizing)
{
if (resizing && (scale == desiredScale) && $WH.g_getWindowSize().h > container.offsetHeight)
return;
container.style.visibility = 'hidden';
computeDimensions(0);
if (!resizing)
{
if (!placeholder)
{
placeholder = $WH.ce('div');
placeholder.style.height = '325px';
placeholder.style.padding = '3px';
placeholder.style.marginTop = '10px';
}
mapper.parent.style.borderWidth = '0px';
mapper.parent.style.marginTop = '0px';
mapper.span.style.cursor = 'pointer';
if (mapper.span.onclick)
oldOnClick = mapper.span.onclick;
mapper.span.onclick = Lightbox.hide;
mapper.span.onmouseover = function() { aCover.style.display = 'block'; };
mapper.span.onmouseout = function() { setTimeout(function() { if (!aCover.hasMouse) aCover.style.display = 'none'; }, 10); };
if (mapper.onMapUpdate)
oldOnUpdate = mapper.onMapUpdate;
mapper.onMapUpdate = onUpdate;
if (!tempParent)
{
oldParent = mapper.parent.parentNode;
oldSibling = mapper.parent.nextSibling;
oldParent.insertBefore(placeholder, mapper.parent);
$WH.de(mapper.parent);
$WH.ae(mapDiv, mapper.parent);
}
else
{
$WH.de(tempParent);
$WH.ae(mapDiv, tempParent);
}
if (location.hash.indexOf('#show') == -1)
location.replace(getPound(false));
else if ($WH.isset('mapShower'))
mapShower.onExpand();
}
Lightbox.reveal();
container.style.visibility = 'visible';
}
function onResize()
{
render(1);
}
function onHide()
{
if (oldOnClick)
mapper.span.onclick = oldOnClick;
else
mapper.span.onclick = null;
oldOnClick = null;
if (oldOnUpdate)
mapper.onMapUpdate = oldOnUpdate
else
mapper.onMapUpdate = null;
oldOnUpdate = null;
mapper.span.style.cursor = '';
mapper.span.onmouseover = null;
mapper.span.onmouseout = null;
if (!tempParent)
{
$WH.de(placeholder);
$WH.de(mapper.parent);
mapper.parent.style.borderWidth = '';
mapper.parent.style.marginTop = '';
if (oldSibling)
oldParent.insertBefore(mapper.parent, oldSibling);
else
$WH.ae(oldParent, mapper.parent);
oldParent = oldSibling = null;
}
else
{
$WH.de(tempParent);
tempParent = null;
}
mapper.toggleZoom();
if (location.hash.indexOf('#show') == -1)
location.replace('#.');
else if ($WH.isset('mapShower'))
mapShower.onCollapse();
}
function onShow(dest, first, opt)
{
mapper = opt.mapper;
container = dest;
if (first)
{
dest.className = 'mapviewer';
screen = $WH.ce('div');
screen.style.width = '772px';
screen.style.height = '515px';
screen.className = 'mapviewer-screen';
aCover = $WH.ce('a');
aCover.className = 'mapviewer-cover';
aCover.href = 'javascript:;';
aCover.onclick = Lightbox.hide;
aCover.onmouseover = function() { aCover.hasMouse = true; };
aCover.onmouseout = function() { aCover.hasMouse = false; };
var foo = $WH.ce('span');
var b = $WH.ce('b');
$WH.ae(b, $WH.ct(LANG.close));
$WH.ae(foo, b);
$WH.ae(aCover, foo);
$WH.ae(screen, aCover);
mapDiv = $WH.ce('div');
$WH.ae(screen, mapDiv);
$WH.ae(dest, screen);
var aClose = $WH.ce('a');
// aClose.className = 'dialog-x'; aowow - button not yet renamed
aClose.className = 'dialog-cancel';
aClose.href = 'javascript:;';
aClose.onclick = Lightbox.hide;
$WH.ae(aClose, $WH.ct(LANG.close));
$WH.ae(dest, aClose);
var d = $WH.ce('div');
d.className = 'clear';
$WH.ae(dest, d);
}
onRender();
}
function onRender()
{
render();
}
this.checkPound = function()
{
if (location.hash && location.hash.indexOf('#map') == 0)
{
var parts = location.hash.split('=');
if (parts.length == 2)
{
var link = parts[1];
if (link)
{
/*tempParent = $WH.ce('div');
tempParent.id = 'fewuiojfdksl';
$WH.ae(document.body, tempParent);
var map = new Mapper({ parent: tempParent.id });
map.setLink(link, true);
map.toggleZoom();*/
MapViewer.show({ link: link });
}
}
else
{
parts = location.hash.split(':');
var map = $WH.ge('sjdhfkljawelis');
if (map)
map.onclick();
if (parts.length == 2)
{
if (!map)
MapViewer.show({ link: parts[1]});
var subparts = parts[1].split('.');
var opts = { zone: subparts[0] };
if (subparts.length == 2)
opts.level = parseInt(subparts[1])+1;
mapper.update(opts);
//if (Mapper.multiLevelZones[mapper.zone])
// mapper.setMap(Mapper.multiLevelZones[mapper.zone][floor], floor, true);
}
}
}
}
this.show = function(opt)
{
if (opt.link)
{
tempParent = $WH.ce('div');
tempParent.id = 'fewuiojfdksl';
$WH.aef(document.body, tempParent); // aowow - aef() insteead of ae() - rather scroll page to top instead of bottom
var map = new Mapper({ parent: tempParent.id });
map.setLink(opt.link, true);
map.toggleZoom();
}
else
Lightbox.show('mapviewer', { onShow: onShow, onHide: onHide, onResize: onResize }, opt);
}
$(document).ready(this.checkPound);
};

View File

@@ -101,7 +101,8 @@ var Markup = {
var UNK_INITED = false;
Markup.youtube.readyTimeout = undefined;
Markup.youtube.APIIsReady = true;
for (var i in Markup.youtube.players) {
for (var i in Markup.youtube.players)
{
if (!Markup.youtube.players.hasOwnProperty(i))
continue;
@@ -355,12 +356,12 @@ var Markup = {
},
allowedClass: MARKUP_CLASS_STAFF,
toHtml: function (attr) {
var e = '<a id="revealtoggle-changelog" class="revealtoggle changelog" href="javascript:;" onclick="Markup.toggleReveal(\'changelog\');">Show Changelog</a>';
var c = "display: none";
if (attr.open == "true") {
e = c = "";
}
return ['<div style="margin: 1em 0" id="guide-changelog"><div id="reveal-changelog" style="' + c + '"><h3 class="heading-size-3">Changelog</h3>', "</div>" + e + "</div>"];
var anchor = '<a id="revealtoggle-changelog" class="revealtoggle changelog" href="javascript:;" onclick="Markup.toggleReveal(\'changelog\');">Show Changelog</a>';
var style = 'display: none';
if (attr.open == 'true')
anchor = style = '';
return ['<div style="margin: 1em 0" id="guide-changelog"><div id="reveal-changelog" style="' + style + '"><h3 class="heading-size-3">Changelog</h3>', "</div>" + anchor + "</div>"];
}
},
'class':
@@ -3395,7 +3396,8 @@ var Markup = {
{
var width = attr.width ? attr.width : 640;
var height = attr.height ? attr.height : 385;
if (window.outerWidth && window.outerWidth - 20 < width) {
if (window.outerWidth && window.outerWidth - 20 < width)
{
width = window.outerWidth - 20;
height = Math.floor(width * 0.6015625);
}

View File

@@ -0,0 +1,987 @@
/*
Menu class
*/
var MENU_IDX_ID = 0; // ID: A number or string; null makes the menu item a separator
var MENU_IDX_NAME = 1; // Name: A string
var MENU_IDX_URL = 2; // URL: A string for the URL, or a function to call when the menu item is clicked
var MENU_IDX_SUB = 3; // Submenu: Child menu
var MENU_IDX_OPT = 4; // Options: JSON array with additional options
var Menu = new function()
{
var self = this;
/***********/
/* PUBLIC */
/**********/
self.add = function(node, menu, opt) // Add a menu to a DOM element
{
if(!opt) opt = $.noop;
var $node = $(node);
$node.data('menu', menu);
if(opt.showAtCursor)
{
$node.click(rootNodeClick);
}
else
{
$node
.mouseover(rootNodeOver)
.mouseout(rootNodeOut);
}
};
self.remove = function(node) // Remove menu from DOM element
{
$(node)
.data('menu', null)
.unbind('click', rootNodeClick)
.unbind('mouseover', rootNodeOver)
.unbind('mouseout', rootNodeOut);
};
self.show = function(menu, node)
{
var $node = $(node);
show(menu, $node);
}
self.showAtCursor = function(menu, event) // {event} must have been normalized by jQuery
{
showAtXY(menu, event.pageX, event.pageY);
}
self.showAtXY = function(menu, x, y)
{
showAtXY(menu, x, y);
}
self.hide = function()
{
rootNodeOut();
}
self.addButtons = function(dest, menu) // Create a set of menu buttons (as seen on the homepage or in the top bar)
{
var $dest = $(dest);
if(!$dest.length)
return;
var $buttons = $('<span class="menu-buttons"></span>');
$.each(menu, function(idx, menuItem)
{
if(isSeparator(menuItem)) return;
var $a = $('<a></a>')
var $span = $('<span></span>', {
text: menuItem[MENU_IDX_NAME]
}).appendTo($a);
self.linkifyItem(menuItem, $a);
if(hasSubmenu(menuItem))
{
$span.addClass('hassubmenu');
self.add($a, menuItem[MENU_IDX_SUB]);
}
$buttons.append($a);
});
$dest.append($buttons);
};
self.linkifyItem = function(menuItem, $a) // Also used by PageTemplate when generating the top tabs
{
var opt = self.getItemOpt(menuItem);
if(!menuItem[MENU_IDX_URL]) // Unlinked
{
$a.attr('href', 'javascript:;');
$a.addClass('unlinked');
return;
}
if(typeof menuItem[MENU_IDX_URL] == 'function') // Function
{
$a.attr('href', 'javascript:;');
$a.click(hide);
$a.click(menuItem[MENU_IDX_URL]);
}
else // URL
{
var url = self.getItemUrl(menuItem);
$a.attr('href', url);
if(opt.newWindow || g_isExternalUrl(url))
$a.attr('target', '_blank');
if(opt.rel)
$a.attr('rel', opt.rel);
}
if(typeof menuItem[MENU_IDX_OPT] == 'object' && menuItem[MENU_IDX_OPT].className)
$a.addClass(menuItem[MENU_IDX_OPT].className);
};
self.updateItem = function(menuItem) // Also used by PageTemplate when the breadcrumb changes
{
var $a = menuItem.$a;
if(!$a)
return;
var opt = self.getItemOpt(menuItem);
$a.removeClass('checked tinyicon icon');
$a.css('background-image', '');
if(menuItem.checked)
{
$a.addClass('checked');
}
else if(opt.tinyIcon)
{
$a.addClass('tinyicon');
$a.css('background-image', 'url(' + (opt.tinyIcon.indexOf('/') != -1 ? opt.tinyIcon : g_staticUrl + '/images/wow/icons/tiny/' + opt.tinyIcon.toLowerCase() + '.gif') + ')');
}
else if(opt.icon)
{
$a.addClass('icon');
$a.css('background-image', 'url(' + opt.icon + ')');
}
else if(opt.socketColor && g_file_gems[opt.socketColor])
{
$a.addClass('socket-' + g_file_gems[opt.socketColor]);
}
var className = (opt['class'] || opt.className);
if(className)
$a.addClass(className);
};
// MENU UTILITY FUNCTIONS
self.hasMenu = function(node)
{
var $node = $(node);
return $node.data('menu') != null;
}
self.modifyUrl = function(menuItem, params, opt)
{
var json = { params: params, opt: opt };
traverseMenuItem(menuItem, function(x)
{
x.modifyUrl = json;
});
PageTemplate.updateBreadcrumb();
};
self.fixUrls = function(menu, url, opt)
{
opt = opt || {};
opt.hash = (opt.hash ? '#' + opt.hash : '');
fixUrls(menu, url, opt, 0);
};
self.sort = function(menu) // Sort a specific menu
{
if(hasSeparators(menu))
sortSeparatedMenu(menu);
else
sortMenu(menu);
};
self.sortSubmenus = function(menu, paths) // Sort the submenus of {menu} specified by {paths}
{
$.each(paths, function(idx, path)
{
var submenu = self.findItem(menu, path);
if(submenu && submenu[MENU_IDX_SUB])
self.sort(submenu[MENU_IDX_SUB]);
});
};
self.implode = function(menu, opt) // Return a new menu where items preceded by a heading are merged into a single item w/ a submenu
{
if(!opt) opt = $.noop;
var result = [];
var groupedMenu;
if(opt.createHeadinglessGroup)
{
groupedMenu = [];
result.push([0, '', null, groupedMenu]);
}
$.each(menu, function(idx, menuItem)
{
if(isSeparator(menuItem))
{
groupedMenu = [];
result.push([0, menuItem[MENU_IDX_NAME], null, groupedMenu]);
}
else
{
if(groupedMenu)
groupedMenu.push(menuItem);
else
result.push(menuItem);
}
});
return result;
};
self.findItem = function(menu, path) // Return the menu item specified by {path} in {menu}
{
return self.getFullPath(menu, path).pop();
};
self.getFullPath = function(menu, path) // Return an array with all the menu items specified by {path} in {menu}
{
var result = [];
for(var i = 0; i < path.length; ++i)
{
var pos = findItemPosById(menu, path[i]);
if(pos != -1)
{
var menuItem = menu[pos];
menuItem.parentMenu = menu;
menu = menuItem[MENU_IDX_SUB];
result.push(menuItem);
}
}
return result;
};
self.getItemUrl = function(menuItem)
{
var url = menuItem[MENU_IDX_URL];
if(!url)
return null;
var opt = self.getItemOpt(menuItem);
if(menuItem.modifyUrl)
url = g_modifyUrl(url, menuItem.modifyUrl.params, menuItem.modifyUrl.opt);
return url;
};
self.getItemOpt = function(menuItem)
{
if(!menuItem[MENU_IDX_OPT])
menuItem[MENU_IDX_OPT] = {};
return menuItem[MENU_IDX_OPT];
};
self.removeItemById = function(menu, id)
{
var pos = findItemPosById(menu, id);
if(pos != -1)
menu.splice(pos, 1);
};
self.setSubmenu = function (menuItem, submenu)
{
menuItem[MENU_IDX_SUB] = submenu;
};
/***********/
/* PRIVATE */
/***********/
var DELAY_BEFORESHOW = 25;
var DELAY_BEFOREHIDE = 333;
var MAX_COLUMNS = 4;
// Should match the styles used in Menu.css
var SIZE_SHADOW_WIDTH = 6;
var SIZE_SHADOW_HEIGHT = 6;
var SIZE_BORDER_HEIGHT = 3;
var SIZE_MENUITEM_HEIGHT = 26;
var inited = false;
var timer;
var $rootNode;
var visibleMenus = {};
var openLinks = {};
var divCache = {};
var menuItemsCache = {};
var nextUniqueId = 0;
function init()
{
if(inited) return;
inited = true;
// Run a test to get the height of a menu item (in case it's different in some browser/OS combos)
var $div = $('<div class="menu"><a href="#"><span>ohai</span></a></div>').css({left: '-1000px', top: '-1000px'}).appendTo(document.body);
var height = $div.children('a').outerHeight();
$div.remove();
if(height > 15) // Safety
SIZE_MENUITEM_HEIGHT = height;
}
function show(menu, $node)
{
if($rootNode)
$rootNode.removeClass('open');
$rootNode = $node;
$rootNode.addClass('open');
displayFirstMenu(menu);
}
function hide()
{
if($rootNode)
{
$rootNode.removeClass('open');
$rootNode = null;
}
hideMenus(0);
}
function showAtXY(menu, x, y)
{
clearTimeout(timer);
displayFirstMenu(menu, x, y);
}
function displayFirstMenu(menu, x, y)
{
closeLinks(0);
displayMenu(menu, 0, x, y);
hideMenus(1);
}
function displayMenu(menu, depth, x, y)
{
init();
beforeShowMenu(menu);
var $div = createDiv(depth);
var $menuItems = createMenuItems(menu);
var $menu = createMenu($menuItems, depth);
$div.append($menu);
var animated = !isMenuVisible(depth);
visibleMenus[depth] = $div;
var pos = getMenuPosition($div, depth, x, y);
$div.css({
left: pos.x + 'px',
top: pos.y + 'px'
});
revealDiv($div, animated);
}
function createDiv(depth)
{
if(divCache[depth])
{
var $div = divCache[depth];
$div.children().detach(); // Similar to $div.empty(), except custom data is preserved.
return $div;
}
var $div = $('<div class="menu"></div>')
.mouseover(menuDivOver)
.mouseleave(menuDivOut)
.delegate('a', 'mouseenter', { depth: depth }, menuItemOver)
.delegate('a', 'click', menuItemClick);
$div.appendTo(document.body);
divCache[depth] = $div;
return $div;
}
function createMenuItems(menu)
{
var uid = getUniqueId(menu);
if(menuItemsCache[uid])
return menuItemsCache[uid];
var nextSeparator; // Used to make sure a separator is always followed by a visible item
var menuItems = [];
$.each(menu, function(idx, menuItem)
{
if(!isItemVisible(menuItem)) return;
$a = createMenuItem(menuItem);
if(isSeparator(menuItem))
{
nextSeparator = $a;
return;
}
if(nextSeparator)
{
menuItems.push(nextSeparator);
nextSeparator = null;
}
menuItems.push($a);
});
var $menuItems = $(menuItems);
menuItemsCache[menu] = $menuItems;
return $menuItems;
}
function createMenuItem(menuItem)
{
beforeCreateMenuItem(menuItem);
var $a = $('<a></a>');
menuItem.$a = $a;
$a.data('menuItem', menuItem);
self.linkifyItem(menuItem, $a);
self.updateItem(menuItem);
// Separator
if(isSeparator(menuItem))
{
$a.addClass('separator');
$a.text(menuItem[MENU_IDX_NAME]);
return $a;
}
var $span = $('<span></span>');
$span.text(menuItem[MENU_IDX_NAME]);
$span.appendTo($a);
// Submenu
if(hasSubmenu(menuItem))
$span.addClass('hassubmenu');
return $a;
}
function createMenu($menuItems, depth)
{
var $a = $rootNode;
var $w = $(window);
var nItems = $menuItems.length;
var availableHeight = $w.height() - (SIZE_BORDER_HEIGHT * 2) - SIZE_SHADOW_HEIGHT;
var nItemsThatCanFit = Math.floor(Math.max(0, availableHeight) / SIZE_MENUITEM_HEIGHT);
// 1 column
if(nItemsThatCanFit >= nItems)
{
var $outerDiv = $('<div class="menu-outer"></div>');
var $innerDiv = $('<div class="menu-inner"></div>');
$menuItems.each(function () { $innerDiv.append(this) });
$outerDiv.append($innerDiv);
$outerDiv.contextmenu($WH.rf); // aowow custom: prevent browser context menu when right clicking to get our context menu as it placed under the mouse cursor
return $outerDiv;
}
// Multiple columns
var nColumns = Math.min(MAX_COLUMNS, Math.ceil(nItems / nItemsThatCanFit));
var nItemsPerColumn = Math.ceil(nItems / nColumns);
var nItemsAdded = 0;
var nItemsRemaining = nItems;
var $holder = $('<div></div>');
while(nItemsRemaining > 0)
{
var $outerDiv = $('<div class="menu-outer"></div>');
var $innerDiv = $('<div class="menu-inner"></div>');
var nItemsToAdd = Math.min(nItemsRemaining, nItemsPerColumn);
var start = nItemsAdded;
var end = start + nItemsToAdd;
$menuItems.slice(start, end).each(function() { $innerDiv.append(this) });
$outerDiv.append($innerDiv);
$holder.append($outerDiv);
nItemsAdded += nItemsToAdd;
nItemsRemaining -= nItemsToAdd;
}
return $holder;
}
function getMenuPosition($div, depth, x, y)
{
if(depth == 0)
return getFirstMenuPosition($div, depth, x, y);
return getSubmenuPosition($div, depth);
}
function getFirstMenuPosition($div, depth, x, y)
{
var viewport = g_getViewport();
var menuWidth = $div.width();
var menuHeight = $div.height();
var menuWidthShadow = menuWidth + SIZE_SHADOW_WIDTH;
var menuHeightShadow = menuHeight + SIZE_SHADOW_HEIGHT;
var showingAtCursor = (x != null && y != null);
if(showingAtCursor)
{
if(y + menuHeightShadow > viewport.b) // Make sure menu doesn't overflow vertically
y = Math.max(viewport.t, viewport.b - menuHeightShadow); // Place along the bottom edge if it does
}
else
{
var $a = $rootNode;
var offset = $a.offset();
// Place underneath the root node by default
x = offset.left
y = offset.top + $a.outerHeight();
// Show menu upwards if it's going to be outside the viewport otherwise (only if there's room)
if(y + menuHeightShadow > viewport.b && offset.top >= menuHeightShadow)
y = offset.top - menuHeightShadow;
}
if(x + menuWidthShadow > viewport.r) // Make sure menu doesn't overflow horizontally
x = Math.max(viewport.l, viewport.r - menuWidthShadow); // Place along the right edge if it does
return {x: x, y: y};
}
function getSubmenuPosition($div, depth)
{
var viewport = g_getViewport();
var menuWidth = $div.width();
var menuHeight = $div.height();
var menuWidthShadow = menuWidth + SIZE_SHADOW_WIDTH;
var menuHeightShadow = menuHeight + SIZE_SHADOW_HEIGHT;
var $a = openLinks[depth - 1];
var offset = $a.offset();
var openToTheLeft = false;
// Show to the right of the menu item
x = offset.left + $a.outerWidth() - 5;
y = offset.top - 2;
if(x + menuWidthShadow > viewport.r) // Make sure menu doesn't overflow horizontally
openToTheLeft = true;
if(openToTheLeft)
x = Math.max(viewport.l, offset.left - menuWidth);
if(y + menuHeightShadow > viewport.b) // Make sure menu doesn't overflow vertically
y = Math.max(viewport.t, viewport.b - menuHeightShadow); // Place along the bottom edge if it does
return {x: x, y: y};
}
function revealDiv($div, animated)
{
if(animated)
{
$div.css({
opacity: '0'
})
.show()
.animate({
opacity: '1'
}, 'fast', null, doneRevealing);
}
else
$div.show();
}
function doneRevealing(a)
{
$(this).css('opacity', ''); // Remove opacity once animation is over to prevent a bug in IE8
}
function hideMenus(depth)
{
while(visibleMenus[depth])
{
visibleMenus[depth].stop().hide();
visibleMenus[depth] = null;
++depth;
}
}
function closeLinks(depth)
{
while(openLinks[depth])
{
openLinks[depth].removeClass('open');
openLinks[depth] = null;
++depth;
}
}
function isMenuVisible(depth)
{
return visibleMenus[depth || 0] != null;
}
// MENU UTILITY FUNCTIONS
function getItemId(menuItem)
{
return menuItem[MENU_IDX_ID];
}
function isSeparator(menuItem)
{
return menuItem[MENU_IDX_ID] == null; // Separators don't have an ID
}
function hasSeparators(menu)
{
return $WH.in_array(menu, true, isSeparator) != -1;
}
function hasSubmenu(menuItem)
{
return menuItem[MENU_IDX_SUB] != null;
}
function findItemPosById(menu, id)
{
return $WH.in_array(menu, id, getItemId);
}
function hasPermissions(menuItem)
{
var opt = self.getItemOpt(menuItem);
if(opt.requiredAccess && !User.hasPermissions(opt.requiredAccess))
return false;
return true;
}
function isItemVisible(menuItem)
{
if(!hasPermissions(menuItem))
return false;
if(hasSubmenu(menuItem))
{
if(!hasVisibleItems(menuItem[MENU_IDX_SUB]))
return false;
}
return true;
}
function hasVisibleItems(menu)
{
return $WH.in_array(menu, true, isSubitemVisible) != -1;
}
function isSubitemVisible(menuItem)
{
return !isSeparator(menuItem) && hasPermissions(menuItem);
}
function getUniqueId(menu)
{
if(menu.uniqueId == null)
menu.uniqueId = nextUniqueId++;
return menu.uniqueId;
}
function traverseMenu(menu, func)
{
$.each(menu, function(idx, menuItem)
{
traverseMenuItem(menuItem, func);
});
}
function traverseMenuItem(menuItem, func)
{
func(menuItem);
if(hasSubmenu(menuItem))
traverseMenu(menuItem[MENU_IDX_SUB], func);
}
function fixUrls(menu, url, opt, depth)
{
$.each(menu, function(idx, menuItem)
{
if(menuItem === undefined) return;
if(isSeparator(menuItem)) return;
if(menuItem[MENU_IDX_URL] == null) // Don't override if already set
menuItem[MENU_IDX_URL] = url + menuItem[MENU_IDX_ID] + opt.hash;
if(hasSubmenu(menuItem))
{
var accumulate = true;
if(opt.useSimpleIds)
accumulate = false;
else if(opt.useSimpleIdsAfter != null && depth >= opt.useSimpleIdsAfter)
accumulate = false;
var nextUrl = url;
if(accumulate)
nextUrl += menuItem[MENU_IDX_ID] + '.';
fixUrls(menuItem[MENU_IDX_SUB], nextUrl, opt, depth + 1);
}
});
}
function sortMenu(menu)
{
menu.sort(function(a, b)
{
return $WH.strcmp(a[MENU_IDX_NAME], b[MENU_IDX_NAME]);
});
}
function sortSeparatedMenu(menu)
{
// Sort each group separately so headings stay where they are.
var implodedMenu = self.implode(menu, { createHeadinglessGroup: true });
$.each(implodedMenu, function(idx, submenu)
{
sortMenu(submenu[MENU_IDX_SUB]);
});
explodeInto(menu, implodedMenu);
};
function explodeInto(menu, implodedMenu) // Reverse of implode
{
menu.splice(0, menu.length); // Clear menu
$.each(implodedMenu, function(idx, menuItem)
{
if(menuItem[MENU_IDX_NAME])
menu.push([, menuItem[MENU_IDX_NAME]]); // Heading
$.each(menuItem[MENU_IDX_SUB], function(idx, menuItem)
{
menu.push(menuItem);
});
});
}
// EVENTS
function beforeCreateMenuItem(menuItem)
{
var opt = self.getItemOpt(menuItem);
if(opt.checkedUrl && location.href.match(opt.checkedUrl))
menuItem.checked = true;
}
function beforeShowMenu(menu)
{
if(menu.onBeforeShow)
menu.onBeforeShow(menu);
$.each(menu, function(idx, menuItem)
{
var opt = self.getItemOpt(menuItem);
if(opt.onBeforeShow)
opt.onBeforeShow(menuItem);
});
}
function rootNodeOver(event)
{
clearTimeout(timer);
var $node = $(this);
if(!isMenuVisible())
{
// Use a small delay the 1st time to prevent undesired appearances
timer = setTimeout(show.bind(null, $node.data('menu'), $node), DELAY_BEFORESHOW);
return;
}
show($node.data('menu'), $node);
}
function rootNodeOut(event)
{
clearTimeout(timer);
if(isMenuVisible())
timer = setTimeout(hide, DELAY_BEFOREHIDE);
}
function rootNodeClick(event)
{
clearTimeout(timer);
self.showAtCursor($(this).data('menu'), event);
}
function menuDivOver(event)
{
clearTimeout(timer);
}
function menuDivOut(event)
{
clearTimeout(timer);
timer = setTimeout(hide, DELAY_BEFOREHIDE);
}
function menuItemOver(event)
{
clearTimeout(timer);
var $a = $(this);
var depth = event.data.depth;
closeLinks(depth);
var menuItem = $a.data('menuItem');
var deepestDepth = depth;
if(menuItem && hasSubmenu(menuItem))
{
$a.addClass('open');
openLinks[depth] = $a;
displayMenu(menuItem[MENU_IDX_SUB], depth + 1);
++deepestDepth;
}
hideMenus(deepestDepth + 1);
}
function menuItemClick(event)
{
var $a = $(this);
var menuItem = $a.data('menuItem');
if(!menuItem)
return;
var opt = self.getItemOpt(menuItem);
if(opt.onClick)
opt.onClick();
}
};
Menu.fixUrls(mn_achievements, '?achievements=');
Menu.fixUrls(mn_classes, '?class=');
Menu.fixUrls(mn_currencies, '?currencies=');
Menu.fixUrls(mn_factions, '?factions=');
Menu.fixUrls(mn_items, '?items=');
Menu.fixUrls(mn_itemSets, '?itemsets&filter=cl=', { hash: '0-2+1' });
Menu.fixUrls(mn_npcs, '?npcs=');
Menu.fixUrls(mn_objects, '?objects=');
Menu.fixUrls(mn_petCalc, '?petcalc=');
Menu.fixUrls(mn_pets, '?pets=');
Menu.fixUrls(mn_quests, '?quests=');
Menu.fixUrls(mn_races, '?race=');
Menu.fixUrls(mn_spells, '?spells=');
Menu.fixUrls(mn_titles, '?titles=');
Menu.fixUrls(mn_zones, '?zones=');
$(document).ready(function() // Locale is only known later
{
// if(Locale.getId() == LOCALE_ENUS)
// return;
Menu.sort(mn_classes);
Menu.sort(mn_database);
Menu.sortSubmenus(mn_items,
[
[4, 1], // Armor > Cloth
[4, 2], // Armor > Leather
[4, 3], // Armor > Mail
[4, 4], // Armor > Plate
[1], // Containers
[0], // Consumables
[16], // Glyphs
[7], // Trade Goods
[6], // Projectiles
[9] // Recipes
]);
Menu.sort(mn_itemSets);
Menu.sort(mn_npcs);
Menu.sort(mn_objects);
Menu.sort(mn_talentCalc);
Menu.sort(mn_petCalc);
Menu.sort(mn_pets);
Menu.sort(mn_races);
Menu.sort(mn_skills);
Menu.sortSubmenus(mn_spells,
[
[7], // Abilities
[-2], // Talents
[-3], // Pet Abilities
[11], // Professions
[9] // Secondary Skills
]);
// aowow - why wasn't this already sorted..?
Menu.sortSubmenus(mn_quests,
[
[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9],
[10]
]);
});

View File

@@ -0,0 +1,16 @@
function MessageBox(parent, text) {
parent.find(".message-box").remove();
var box = $("<div></div>");
box.hide();
box.addClass("message-box");
box.html('<p class="message">' + text + '</p><p class="close">(Click on this box to close it)</p>');
box.click(function () { $(this).fadeOut(); });
box.click(function (e) {
$WH.sp(e); // aowow - custom: without this, the comment-header would also register the click
$(this).fadeOut();
});
parent.append(box[0]);
box.fadeIn();
}

View File

@@ -0,0 +1,676 @@
/*
public static const MT_ITEM:int = 1;
public static const MT_HELM:int = 2;
public static const MT_SHOULDER:int = 4;
public static const MT_NPC:int = 8;
public static const MT_CHAR:int = 16;
public static const MT_HUMAN:int = 32; // .sis file
public static const MT_OBJECT:int = 64;
public static const MT_ARMOR:int = 128;
public static const IT_HEAD:int = 1;
public static const IT_SHOULDER:int = 3;
public static const IT_SHIRT:int = 4;
public static const IT_CHEST:int = 5;
public static const IT_BELT:int = 6;
public static const IT_PANTS:int = 7;
public static const IT_BOOTS:int = 8;
public static const IT_BRACERS:int = 9;
public static const IT_GLOVES:int = 10;
public static const IT_ONEHAND:int = 13; //14
public static const IT_SHIELD:int = 14; //13
public static const IT_BOW:int = 15; //14
public static const IT_CAPE:int = 16;
public static const IT_TWOHAND:int = 17; //14
public static const IT_TABARD:int = 19;
public static const IT_ROBE:int = 20; //5
public static const IT_RIGHTHAND:int = 21; //14
public static const IT_LEFTHAND:int = 22; //13
public static const IT_OFFHAND:int = 23; //13
public static const IT_THROWN:int = 25; //14
*/
var ModelViewer = new function()
{
this.validSlots = [1, 3, 4, 5, 6, 7, 8, 9, 10, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 25, 26];
this.slotMap = {1: 1, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 13: 21, 14: 22, 15: 22, 16: 16, 17: 21, 19: 19, 20: 5, 21: 21, 22: 22, 23: 22, 25: 21, 26: 21};
var model,
modelType,
equipList = [],
displayLink,
displayLabel,
optBak,
flashDiv,
modelDiv,
screenDiv,
animDiv,
raceSel1,
raceSel2,
sexSel,
oldHash,
mode,
opts,
readExtraPound,
animsLoaded = false,
races = [
{ id: 10, name: g_chr_races[10], model: 'bloodelf' },
{ id: 11, name: g_chr_races[11], model: 'draenei' },
{ id: 3, name: g_chr_races[ 3], model: 'dwarf' },
{ id: 7, name: g_chr_races[ 7], model: 'gnome' },
{ id: 1, name: g_chr_races[ 1], model: 'human' },
{ id: 4, name: g_chr_races[ 4], model: 'nightelf' },
{ id: 2, name: g_chr_races[ 2], model: 'orc' },
{ id: 6, name: g_chr_races[ 6], model: 'tauren' },
{ id: 8, name: g_chr_races[ 8], model: 'troll' },
{ id: 5, name: g_chr_races[ 5], model: 'scourge' }
],
sexes = [
{ id: 0, name: LANG.male, model: 'male' },
{ id: 1, name: LANG.female, model: 'female' }
];
function clear()
{
}
function getRaceSex()
{
var race,
sex;
if (raceSel1.is(':visible'))
race = (raceSel1[0].selectedIndex >= 0 ? raceSel1.val() : '');
else
race = (raceSel2[0].selectedIndex >= 0 ? raceSel2.val() : '');
sex = (sexSel[0].selectedIndex >= 0 ? sexSel.val() : 0);
return { r: race, s: sex };
}
function isRaceSexValid(race, sex)
{
return (!isNaN(race) && race > 0 && $WH.in_array(races, race, function(x) { return x.id; }) != -1 &&
!isNaN(sex) && sex >= 0 && sex <= 1);
}
function render()
{
screenDiv.css('width', '600px');
var flashVars = {
model: model,
modelType: modelType,
// contentPath: 'http://static.wowhead.com/modelviewer/'
contentPath: g_staticUrl + '/modelviewer/'
};
var params = {
quality: 'high',
allowscriptaccess: 'always',
allowfullscreen: true,
menu: false,
bgcolor: '#181818',
wmode: 'direct'
};
var attributes = { };
if (modelType == 16 && equipList.length)
flashVars.equipList = equipList.join(',');
if (displayLink)
flashVars.link = displayLink;
if (displayLabel)
flashVars.label = displayLabel;
// swfobject.embedSWF('http://static.wowhead.com/modelviewer/ZAMviewerfp11.swf', 'modelviewer-generic', '600', '400', "11.0.0", 'http://static.wowhead.com/modelviewer/expressInstall.swf', flashVars, params, attributes);
swfobject.embedSWF(g_staticUrl + '/modelviewer/ZAMviewerfp11.swf', 'modelviewer-generic', '600', '400', "11.0.0", g_staticUrl + '/modelviewer/expressInstall.swf', flashVars, params, attributes);
var foo = getRaceSex(),
race = foo.r,
sex = foo.s;
if (!optBak.noPound)
{
var url = '#modelviewer';
var foo = $WH.ge('view3D-button');
if (!foo)
{
switch (optBak.type)
{
case 1: // npc
url += ':1:' + optBak.displayId + ':' + (optBak.humanoid | 0);
break;
case 2: // object
url += ':2:' + optBak.displayId;
break;
case 3: // item
url += ':3:' + optBak.displayId + ':' + (optBak.slot | 0);
break;
case 4: // item set
url += ':4:' + equipList.join(';');
break;
}
}
if (race && sex)
url += ':' + race + '+' + sex;
else
url += ':';
if (optBak.extraPound != null)
url += ':' + optBak.extraPound;
animsLoaded = false;
location.replace($WH.rtrim(url, ':'));
}
}
function onSelChange()
{
var foo = getRaceSex(),
race = foo.r,
sex = foo.s;
if (!race)
{
if (!sexSel.is(':visible'))
return;
sexSel.hide();
model = equipList[1];
switch (optBak.slot)
{
case 1:
modelType = 2; // Helm
break;
case 3:
modelType = 4; // Shoulder
break;
default:
modelType = 1; // Item
}
}
else
{
if (!sexSel.is(':visible'))
sexSel.show();
var foo = function(x) { return x.id; };
var raceIndex = $WH.in_array(races, race, foo);
var sexIndex = $WH.in_array(sexes, sex, foo);
if (raceIndex != -1 && sexIndex != -1)
{
model = races[raceIndex].model + sexes[sexIndex].model;
modelType = 16;
}
g_setWowheadCookie('temp_default_3dmodel', race + ',' + sex);
}
clear();
render();
}
function onAnimationChange()
{
var viewer = $('#modelviewer-generic');
if (viewer.length == 0)
return;
viewer = viewer[0];
var animList = $('select', animDiv);
if (animList.val() && viewer.isLoaded && viewer.isLoaded())
viewer.setAnimation(animList.val());
}
function onAnimationMouseover()
{
if (animsLoaded)
return;
var viewer = $('#modelviewer-generic');
if (viewer.length == 0)
return;
viewer = viewer[0];
var animList = $('select', animDiv);
animList.empty();
if (!viewer.isLoaded || !viewer.isLoaded())
{
animList.append($('<option/>', { text: LANG.tooltip_loading, val: 0 }));
return;
}
var anims = {};
var numAnims = viewer.getNumAnimations();
for (var i = 0; i < numAnims; ++i)
{
var a = viewer.getAnimation(i);
if (a && a != 'EmoteUseStanding')
anims[a] = 1;
}
var animArray = [];
for (var a in anims)
animArray.push(a);
animArray.sort();
for (var i = 0; i < animArray.length; ++i)
animList.append($('<option/>', { text: animArray[i], val: animArray[i] }));
animsLoaded = true;
}
function initRaceSex(allowNoRace, opt)
{
var race = -1,
sex = -1,
sel,
offset;
if (opt.race != null && opt.sex != null)
{
race = opt.race;
sex = opt.sex;
modelDiv.hide();
allowNoRace = 0;
}
else
modelDiv.show();
if (race == -1 && sex == -1)
{
if (location.hash)
{
var matches = location.hash.match(/modelviewer:.*?([0-9]+)\+([0-9]+)/);
if (matches != null)
{
if (isRaceSexValid(matches[1], matches[2]))
{
race = matches[1];
sex = matches[2];
sexSel.show();
}
}
}
}
if (allowNoRace)
{
sel = raceSel1;
offset = 1;
raceSel1.show();
raceSel1[0].selectedIndex = -1;
raceSel2.hide();
if (sex == -1)
sexSel.hide();
}
else
{
if (race == -1 && sex == -1)
{
var cooRace = 1,
cooSex = 0;
if (g_user && g_user.cookies['default_3dmodel'])
{
var sp = g_user.cookies['default_3dmodel'].split(',');
if (sp.length == 2)
{
cooRace = sp[0];
cooSex = sp[1] - 1;
}
}
else
{
var cookie = g_getWowheadCookie('temp_default_3dmodel');
if (cookie)
{
var sp = cookie.split(',');
if (sp.length == 2)
{
cooRace = sp[0];
cooSex = sp[1];
}
}
}
if (isRaceSexValid(cooRace, cooSex))
{
race = cooRace;
sex = cooSex;
}
else
{
// Default
race = 1; // Human
sex = 0; // Male
}
}
sel = raceSel2;
offset = 0;
raceSel1.hide();
raceSel2.show();
sexSel.show();
}
if (sex != -1)
sexSel[0].selectedIndex = sex;
if (race != -1 && sex != -1)
{
var foo = function(x) { return x.id; };
var raceIndex = $WH.in_array(races, race, foo);
var sexIndex = $WH.in_array(sexes, sex, foo);
if (raceIndex != -1 && sexIndex != -1)
{
model = races[raceIndex].model + sexes[sexIndex].model;
modelType = 16;
raceIndex += offset;
sel[0].selectedIndex = raceIndex;
sexSel[0].selectedIndex = sexIndex;
}
}
}
function onHide()
{
if (!optBak.noPound)
{
if (!optBak.fromTag && oldHash && oldHash.indexOf('modelviewer') == -1)
location.replace(oldHash);
else
location.replace('#.');
}
if (optBak.onHide)
optBak.onHide();
}
function onShow(dest, first, opt)
{
var a1,
a2;
opts = opt;
Lightbox.setSize(620, 452);
if (first)
{
dest = $(dest);
dest.addClass('modelviewer');
var screen = $('<div/>', { 'class': 'modelviewer-screen' });
flashDiv = $('<div/>');
flashDiv.append($('<div/>', { id: 'modelviewer-generic' }));
screen.append(flashDiv);
var screenbg = $('<div/>', { css: { 'background-color': '#181818', margin: '0' } });
screenbg.append(screen);
dest.append(screenbg);
screenDiv = screen;
var rightDiv = $('<div/>', { css: { 'float': 'right' } });
var leftDiv = $('<div/>', { css: { 'float': 'left' } });
animDiv = $('<div/>', { 'class': 'modelviewer-animation' });
var v = $('<var/>', { text: LANG.animation });
animDiv.append(v);
var select = $('<select/>', { change: onAnimationChange, mouseenter: onAnimationMouseover });
select.append($('<option/>', { text: LANG.dialog_mouseovertoload }));
animDiv.append(select);
rightDiv.append(animDiv);
var a1 = $('<a/>', { 'class': 'modelviewer-help', href: '?help=modelviewer', target: '_blank', text: LANG.help }),
a2 = $('<a/>', { 'class': 'modelviewer-close', href: 'javascript:;', click: Lightbox.hide, text: LANG.close });
rightDiv.append(a2);
rightDiv.append(a1);
dest.append(rightDiv);
var sp = $('<span/>');
sp.append('<small>Drag to rotate<br />Control (Windows) / Cmd (Mac) + drag to pan</small>');
leftDiv.append(sp);
modelDiv = $('<div/>', { 'class': 'modelviewer-model' });
var foo = function(a, b) { return $WH.strcmp(a.name, b.name); };
races.sort(foo);
sexes.sort(foo);
raceSel1 = $('<select/>', { change: onSelChange });
raceSel2 = $('<select/>', { change: onSelChange });
sexSel = $('<select/>', { change: onSelChange });
raceSel1.append($('<option/>'));
for (var i = 0, len = races.length; i < len; ++i)
{
var o = $('<option/>', { val: races[i].id, text: races[i].name });
raceSel1.append(o);
}
for (var i = 0, len = races.length; i < len; ++i)
{
var o = $('<option/>', { val: races[i].id, text: races[i].name });
raceSel2.append(o);
}
for (var i = 0, len = sexes.length; i < len; ++i)
{
var o = $('<option/>', { val: sexes[i].id, text: sexes[i].name });
sexSel.append(o);
}
sexSel.hide();
var v = $('<var/>', { text: LANG.model });
modelDiv.append(v);
modelDiv.append(raceSel1);
modelDiv.append(raceSel2);
modelDiv.append(sexSel);
leftDiv.append(modelDiv);
dest.append(leftDiv);
d = $('<div/>', { 'class': 'clear' });
dest.append(d);
d = $('<div/>', { id: 'modelviewer-msg', 'class': 'sub', css: { display: 'none', 'margin-top': '-6px', color: '#ccc', 'font-size': '11px' } });
dest.append(d);
}
switch (opt.type)
{
case 1: // NPC
modelDiv.hide();
if (opt.humanoid)
modelType = 32; // Humanoid NPC
else
modelType = 8; // NPC
model = opt.displayId;
break;
case 2: // Object
modelDiv.hide();
modelType = 64; // Object
model = opt.displayId;
break;
case 3: // Item
case 4: // Item Set
if (opt.type == 3)
equipList = [opt.slot, opt.displayId];
else
equipList = opt.equipList;
if ($WH.in_array([4, 5, 6, 7, 8, 9, 10, 16, 19, 20], equipList[0]) != -1)
{
initRaceSex(0, opt);
}
else
{
switch (equipList[0])
{
case 1:
modelType = 2; // Helm
break;
case 3:
modelType = 4; // Shoulder
break;
default:
modelType = 1; // Item
}
model = equipList[1];
initRaceSex(1, opt);
}
break;
}
clear();
setTimeout(render, 1);
var msg = $('#modelviewer-msg');
if (opt.message && msg.length > 0)
{
msg.html(opt.message);
msg.show();
}
else
msg.hide();
if (opt.link)
displayLink = opt.link;
if (opt.label)
displayLabel = opt.label;
var trackCode = '';
if (opt.fromTag)
{
trackCode += 'Custom ';
switch (opt.type)
{
case 1: // npc
trackCode += 'NPC ' + opt.displayId + (opt.humanoid ? ' humanoid' : ''); break;
case 2: // object
trackCode += 'Object ' + opt.displayId; break;
case 3: // item
trackCode += 'Item ' + opt.displayId + ' Slot ' + (opt.slot | 0); break;
case 4: // item set
trackCode += 'Item set ' + equipList.join('.'); break;
}
}
else
{
switch (opt.type)
{
case 1: // npc
trackCode += 'NPC ' + (opt.typeId ? opt.typeId : ' DisplayID ' + opt.displayId); break;
case 2: // object
trackCode += 'Object ' + opt.typeId; break;
case 3: // item
trackCode += 'Item ' + opt.typeId; break;
case 4: // item set
trackCode += 'Item set ' + equipList.join('.'); break;
}
}
g_trackEvent('Model Viewer', 'Show', g_urlize(trackCode));
oldHash = location.hash;
}
this.checkPound = function()
{
if (location.hash && location.hash.indexOf('#modelviewer') == 0)
{
var parts = location.hash.split(':');
if (parts.length >= 3)
{
parts.shift(); // - #modelviewer
var type = parseInt(parts.shift());
var opt = { type: type };
switch (type)
{
case 1: // npc
opt.displayId = parseInt(parts.shift());
var humanoid = parseInt(parts.shift());
if (humanoid == 1)
opt.humanoid = 1;
break;
case 2: // object
opt.displayId = parseInt(parts.shift());
break;
case 3: // item
opt.displayId = parseInt(parts.shift());
opt.slot = parseInt(parts.shift());
break;
case 4: // item set
var list = parts.shift();
opt.equipList = list.split(';');
break;
}
if (opt.displayId || opt.equipList) {
ModelViewer.show(opt);
}
if (readExtraPound != null)
{
if (parts.length > 0 && parts[parts.length - 1])
readExtraPound(parts[parts.length - 1]);
}
}
else if (readExtraPound != null && parts.length == 2 && parts[1])
readExtraPound(parts[1]);
else
{
var foo = $WH.ge('view3D-button');
if (foo)
foo.onclick();
}
}
}
this.addExtraPound = function(func)
{
readExtraPound = func;
}
this.show = function(opt)
{
optBak = opt;
Lightbox.show('modelviewer', {
onShow: onShow,
onHide: onHide
}, opt);
}
$(document).ready(this.checkPound);
};

View File

@@ -0,0 +1,630 @@
var PageTemplate = new function()
{
var self = this;
/**********/
/* PUBLIC */
/**********/
self.init = function()
{
// Top links
initFavorites();
initUserMenu();
initFeedbackLink();
initLanguageMenu();
initFilterDisclosure(); // aowow: custom (visibility toggle for filters was removed at some point)
// UI before page contents
initFloatingStuff();
initTopTabs();
initTopBar();
initBreadcrumb();
inited = true;
}
self.get = function(name)
{
return opt[name];
}
self.set = function(options)
{
if (!options)
return;
var old = {};
$.extend(old, opt);
$.extend(opt, options);
opt.activeTab = parseInt(opt.activeTab);
if (inited) // Update UI on the fly if already created
{
if (opt.activeTab != old.activeTab)
{
updateTopTabs();
updateTopBar();
}
if (opt.breadcrumb != old.breadcrumb)
{
updateBreadcrumb();
}
}
}
self.getBreadcrumb = function()
{
return $bread;
}
self.updateBreadcrumb = function()
{
updateBreadcrumb();
}
self.expandBreadcrumb = function()
{
return expandBreadcrumb();
}
/***********/
/* PRIVATE */
/***********/
var inited = false;
var opt = {};
var $bread;
var $tabs;
var checkedMenuItems = [];
function construct()
{
createDomElements(); // Create nodes for which getters are available
addBrowserClasses();
}
function createDomElements()
{
$bread = $('<div class="breadcrumb"></div>');
}
function addBrowserClasses()
{
// This is done before the <body> tag is loaded, so class names are added to the <html> tag instead
}
function initFavorites()
{
var favMenu = $('#toplinks-favorites > a');
favMenu.text(LANG.favorites);
if (!Favorites.hasFavorites())
favMenu.parent().hide();
Favorites.refreshMenu()
}
function initUserMenu()
{
var $link = $('#toplinks-user');
if (!$link.length)
return;
$link.attr('href', '?user=' + g_user.name);
var menu = [];
// User Page
var userPage = ['user-page', LANG.userpage, '?user=' + g_user.name, null, {checkedUrl: new RegExp('user=' + g_user.name + '$', 'i')}];
menu.push(userPage);
// Settings
// var settings = ['settings', LANG.settings, 'http://' + window.location.hostname + '?account', null, {icon: g_staticUrl + '/images/icons/cog.gif', checkedUrl: /account/i}];
var settings = ['settings', LANG.settings, '?account', null, {icon: g_staticUrl + '/images/icons/cog.gif', checkedUrl: /account/i}];
menu.push(settings);
// Reputation
var reputation = ['reputation', LANG.reputation, '?reputation'];
menu.push(reputation);
// Guides
// var guides = ['guides', 'My Guides', '?my-guides'];
var guides = ['guides', LANG.myguides, '?my-guides', null, {onBeforeShow: generateGuidesSubmenu} ];
menu.push(guides);
addCharactersMenu(menu);
addProfilesMenu(menu);
// Premium Upgrade
var premiumUpgrade;
if (!g_user.premium)
{
premiumUpgrade = ['premium-upgrade', LANG.premiumupgrade, '?premium', null, {className: 'q7', checkedUrl: /premium/i}];
menu.push(premiumUpgrade);
}
// Sign Out
menu.push(['sign-out', LANG.signout, '?account=signout']);
menu.push(['sign-out-global', LANG.logOutEverywhere, '?account=signout&global']);
Menu.add($link, menu);
$link.addClass('hassubmenu');
}
function addCharactersMenu(userMenu)
{
if (!g_user.characters || !g_user.characters.length)
return;
// Menu will be generated on the fly
var characters = ['characters', LANG.tab_characters, '?user=' + g_user.name + '#characters', null, {onBeforeShow: generateCharactersSubmenu} ];
userMenu.push(characters);
}
function addProfilesMenu(userMenu)
{
if (!g_user.profiles || !g_user.profiles.length)
return;
// Menu will be generated on the fly
var profiles = ['profiles', LANG.tab_profiles, '?user=' + g_user.name + '#profiles', null, {onBeforeShow: generateProfilesSubmenu} ];
userMenu.push(profiles);
}
function generateCharactersSubmenu(menuItem)
{
var submenu = [];
// Sort by realm, region, name
g_user.characters.sort(function(a, b)
{
return $WH.strcmp(a.realmname, b.realmname) || $WH.strcmp(a.region, b.region) || $WH.strcmp(a.name, b.name);
});
var lastKey;
$.each(g_user.characters, function(idx, character)
{
if (!character.region || !character.realm || !character.name)
return;
// Group by realm+region
var key = character.region + character.realm;
if (key != lastKey)
{
var heading = [, character.realmname + ' (' + character.region.toUpperCase() + ')', g_getProfileRealmUrl(character)];
submenu.push(heading);
lastKey = key;
}
var menuItem = [character.id, character.name, g_getProfileUrl(character), null,
{
className: (character.pinned ? 'icon-star-right ' : '') + 'c' + character.classs,
// tinyIcon: $WH.g_getProfileIcon(character.race, character.classs, character.gender, character.level, character.id, 'tiny')
// aowow - see profile=avatar endpoint for explanation
tinyIcon: $WH.g_getProfileIcon(character.race, character.classs, character.gender, character.level, 0, 'tiny')
}];
submenu.push(menuItem);
});
menuItem[MENU_IDX_SUB] = submenu;
}
function generateProfilesSubmenu(menuItem)
{
var submenu = [];
// Sort by name
g_user.profiles.sort(function(a, b)
{
return $WH.strcmp(a.name, b.name);
});
$.each(g_user.profiles, function(idx, profile)
{
var menuItem = [profile.id, profile.name, g_getProfileUrl(profile), null,
{
className: 'c' + profile.classs,
tinyIcon: $WH.g_getProfileIcon(profile.race, profile.classs, profile.gender, profile.level, profile.icon, 'tiny')
}];
submenu.push(menuItem);
});
submenu.push([0, LANG.menu_newprofile, '?profile&new', null, {tinyIcon: 'inv_misc_questionmark'}]);
menuItem[MENU_IDX_SUB] = submenu;
}
// aowow- custom
function generateGuidesSubmenu(menuItem)
{
var submenu = [];
if (!g_user.guides || !g_user.guides.length)
return;
// Sort by name
g_user.guides.sort(function(a, b)
{
return $WH.strcmp(a.title, b.title);
});
$.each(g_user.guides, function(idx, guide)
{
var menuItem = [guide.id, guide.title, guide.url, [[guide.id, LANG.button_edit, '?guide=edit&id=' + guide.id]]];
submenu.push(menuItem);
});
if (g_user.id)
submenu.push([0, LANG.createnewguide, '?guide=new']);
menuItem[MENU_IDX_SUB] = submenu;
}
function initFeedbackLink()
{
$('#toplinks-feedback')
.attr('href', 'javascript:;')
.click(function()
{
ContactTool.show();
});
}
function initLanguageMenu()
{
var linkBefore = 'http://';
var linkAfter = location.pathname + location.search + location.hash;
var localeId = Locale.getId();
var menu = [];
var currentLocale;
$.each(Locale.getAllByName(), function(idx, locale)
{
var menuItem = [
locale.id,
locale.description,
g_host + '/?locale=' + locale.id, // aowow: edited for unsupported subdomains # linkBefore + locale.domain + linkAfter
null, // more custom
null // also custom
];
if (typeof g_pageInfo != 'undefined' && g_pageInfo.type && g_types[g_pageInfo.type])
menuItem[4] = {rel: g_types[g_pageInfo.type] + '=' + g_pageInfo.typeId + " domain=" + locale.domain};
if (locale.id == localeId)
{
menuItem.checked = true;
currentLocale = locale;
}
menu.push(menuItem);
});
setLanguageMenu($('#toplinks-language'), menu, currentLocale);
$(document).ready(function()
{
setLanguageMenu($('#footer-links-language'), menu, currentLocale);
});
}
function setLanguageMenu($node, menu, locale)
{
$node.attr('href', 'javascript:;');
// $node.text(locale.description);
$node.addClass('hassubmenu');
Menu.add($node, menu);
}
function initFloatingStuff()
{
// Expand button
$('#header-expandsite')
.attr('href', 'javascript:;')
.click(expandButtonClick);
}
function initTopTabs()
{
var $topTabs = $('#toptabs');
if (!$topTabs.length)
return;
$tabs = $('<dl/>');
$.each(mn_path, function(idx, menuItem)
{
var $dt = $('<dt><a><ins><big>' + menuItem[MENU_IDX_NAME].charAt(0) + '</big>' + menuItem[MENU_IDX_NAME].substr(1) + '</ins><span></span></a></dt>');
var $a = $dt.children('a');
Menu.linkifyItem(menuItem, $a);
$dt.appendTo($tabs);
});
updateTopTabs();
$tabs.appendTo($topTabs);
}
function initTopBar()
{
var $topBar = $('#topbar');
if (!$topBar.length)
return;
// Search
var $search = $('div.topbar-search', $topBar);
// aowow: custom start
$('#livesearch-generic').attr('placeholder', LANG.searchdb);
// aowow: custom end
// Icon
var $icon = $('<a></a>').attr('href', 'javascript:;');
$icon.click(searchIconClick)
.appendTo($search);
$('form', $search).submit(g_preventEmptyFormSubmission);
LiveSearch.attach($('input', $search));
var windowSize = $WH.g_getWindowSize();
if (windowSize.w && windowSize.w < 1024)
$('div.topbar-search input').css('width', '180px');
updateTopBar();
}
function initBreadcrumb()
{
// (Already created)
updateBreadcrumb();
$bread.appendTo($('#main-precontents'));
}
function initFilterDisclosure()
{
if (opt.filter == null)
return;
var _ = $WH.ge('main-precontents'),
d = $WH.ce('div'),
a = $WH.ce('a');
d.className = 'path-right';
a.href = 'javascript:;';
a.id = 'fi_toggle';
$WH.ns(a);
a.onclick = fi_toggle;
if (opt.filter)
{
a.className = 'disclosure-on';
$WH.ae(a, $WH.ct(LANG.fihide));
}
else
{
a.className = 'disclosure-off';
$WH.ae(a, $WH.ct(LANG.fishow));
}
$WH.ae(d, a);
$WH.ae(_, d);
}
function updateTopTabs()
{
if (!$tabs)
return;
var $as = $('a', $tabs);
$.each(mn_path, function(idx, menuItem)
{
var $a = $($as.get(idx));
var isActiveTab = (menuItem[MENU_IDX_ID] == opt.activeTab);
if (isActiveTab)
{
$a.addClass('active');
Menu.remove($a);
}
else
{
$a.removeClass('active');
if (menuItem[MENU_IDX_SUB])
Menu.add($a, menuItem[MENU_IDX_SUB]);
}
});
}
function updateTopBar()
{
var $buttons = $('#topbar div.topbar-buttons');
if (!$buttons.length)
return;
$buttons.empty();
switch(opt.activeTab)
{
case 0: // Database
Menu.addButtons($buttons,[
[0, LANG.menu_browse, null, mn_database], // Browse
Menu.findItem(mn_tools, [8]), // Utilities
Menu.findItem(mn_tools, [8, 4]) // Random Page
]);
break;
case 1: // Tools
// Create "Calculators" group to decrease width used
var calculators = [
[, LANG.calculators],
Menu.findItem(mn_tools, [0]), // Talent Calculator
Menu.findItem(mn_tools, [2]), // Hunter Pet Calculator
Menu.findItem(mn_tools, [3]) // Item Comparison
];
// MoP link
if (mn_tools[2][0] == 10) {
var tmp = calculators[3];
calculators[3] = Menu.findItem(mn_tools, [10]);
calculators[4] = tmp;
Menu.addButtons($buttons, Menu.implode(calculators));
Menu.addButtons($buttons, Menu.implode(mn_tools.slice(4))); // Skip first 4 menu items
} else {
Menu.addButtons($buttons, Menu.implode(calculators));
Menu.addButtons($buttons, Menu.implode(mn_tools.slice(3))); // Skip first 4 menu items
}
break;
case 2: // More
Menu.addButtons($buttons, Menu.implode(mn_more));
break;
case 3: // Community
Menu.addButtons($buttons, Menu.implode(mn_community));
Menu.addButtons($buttons, [
Menu.findItem(mn_tools, [8]) // Utilities
]);
break;
case 4: // Staff
Menu.addButtons($buttons, Menu.implode(mn_staff));
break;
case 5: // News
Menu.addButtons($buttons, Menu.implode(mn_news));
break;
case 6: // Guides // aowow - localization added
// var entries = [ [ 1, 'List of guides', '/guides' ], [ 2, 'Write new guide', '/guide=new' ] ];
var entries = [ [ 1, LANG.listguides, '?guides', mn_guides ], [ 2, LANG.createnewguide, '?guide=new' ] ];
if (g_user.id)
entries.push([ 3, LANG.myguides, '?my-guides' ]);
// entries.push([ 3, 'My guides', '/my-guides' ]);
Menu.addButtons($buttons, entries);
break;
}
}
function updateBreadcrumb()
{
if (!opt.breadcrumb || !opt.breadcrumb.length) // Empty
{
$bread.hide();
return;
}
$bread.empty();
// Uncheck previously checked menu items, if any
if (checkedMenuItems.length)
{
$.each(checkedMenuItems, function() {this.checked = false;Menu.updateItem(this)});
checkedMenuItems = [];
}
var path = Menu.getFullPath(mn_path, opt.breadcrumb);
if (!path.length)
return;
var lastIdx = (path.length - 1);
$.each(path, function(idx, menuItem)
{
var menuOpt = Menu.getItemOpt(menuItem);
menuItem.checked = true;
checkedMenuItems.push(menuItem);
Menu.updateItem(menuItem);
var $span = expandBreadcrumb();
var $textHolder = $span;
if (menuItem[MENU_IDX_URL])
{
$textHolder = $('<a/>', {
href: Menu.getItemUrl(menuItem)
}).appendTo($span);
}
if (menuOpt.breadcrumb)
$textHolder.text(menuOpt.breadcrumb);
else
$textHolder.text(menuItem[MENU_IDX_NAME]);
Menu.add($textHolder, menuItem.parentMenu);
$span.appendTo($bread);
// Add ellipsis as appropriate
if (idx == lastIdx && menuItem[MENU_IDX_SUB])
{
$span.addClass('breadcrumb-arrow');
var $ellipsis = $('<span class="breadcrumb-ellipsis">...</span>');
Menu.add($ellipsis, menuItem[MENU_IDX_SUB]);
$ellipsis.appendTo($bread);
}
});
$bread.trigger('update'); // Some features rely on this event to add stuff to the breadcrumb
$bread.show();
}
function expandBreadcrumb()
{
$bread.children('span').last().addClass('breadcrumb-arrow');
return $('<span/>').appendTo($bread);
}
// EVENTS
function expandButtonClick()
{
$('#sidebar, #header-expandsite').remove();
if ($('#layout').hasClass('nosidebar'))
return;
// Free room allocated for the sidebar
$('#wrapper').animate(
{'margin-right': '10px'},
333,
null,
function()
{
$('#wrapper').css('margin-right', '0px');
$('#layout').addClass('nosidebar');
}
);
}
function searchIconClick()
{
$(this).prev('form').submit().children('input').focus();
}
construct();
}

View File

@@ -0,0 +1,10 @@
/*
Global utility functions related to positioning
*/
function g_getViewport()
{
var win = $(window);
return new Rectangle(win.scrollLeft(), win.scrollTop(), win.width(), win.height());
}

View File

@@ -0,0 +1,19 @@
/*
Global Profiler-related functions
*/
function g_cleanCharacterName(name) {
return (name.match && name.match(/^[A-Z]/) ? name.charAt(0).toLowerCase() + name.substr(1) : name);
}
function g_getProfileUrl(profile) {
if (profile.region) // Armory character
return '?profile=' + profile.region + '.' + profile.realm + '.' + g_cleanCharacterName(profile.name) + (profile.renameItr ? '-' + profile.renameItr : '');
// return '?profile=' + profile.region + '.' + profile.realm + '.' + g_cleanCharacterName(profile.name); // aowow custom
else // Custom profile
return '?profile=' + profile.id;
}
function g_getProfileRealmUrl(profile) {
return '?profiles=' + profile.region + '.' + profile.realm;
}

View File

@@ -0,0 +1,122 @@
var ProgressBar = function(opt)
{
this.opts = {
text: '',
hoverText: '',
color: 'rep6',
width: 0,
progress: 0
};
this.elements = {
text: null,
hoverText: null,
textContainer: null,
progress: null,
container: null
};
$WH.cO(this.opts, opt);
this.build();
};
ProgressBar.prototype.build = function()
{
var el = $('<a/>', { 'class': 'progressbar', href: 'javascript:;' });
if(this.opts.width > 0)
el.css('width', this.opts.width + 'px');
else
el.css('width', 'auto');
var textDiv = $('<div/>', { 'class': 'progressbar-text' });
if(this.opts.text)
{
this.elements.text = $('<del/>', { text: this.opts.text });
textDiv.append(this.elements.text);
}
if(this.opts.hoverText)
{
this.elements.hoverText = $('<ins/>', { text: this.opts.hoverText });
textDiv.append(this.elements.hoverText);
}
el.append(textDiv);
var div = $('<div/>', { 'class': 'progressbar-' + this.opts.color, css: { width: this.opts.progress + '%' }, text: String.fromCharCode(160) });
el.append(div);
if(this.opts.text)
textDiv.append($('<div/>', { 'class': 'progressbar-text progressbar-hidden', text: this.opts.text }));
this.elements.container = el;
this.elements.progress = div;
this.elements.textContainer = textDiv;
return el;
};
ProgressBar.prototype.setText = function(text)
{
this.opts.text = text;
if(this.elements.text)
this.elements.text.text(this.opts.text);
else
{
this.elements.text = $('<del/>', { text: this.opts.text });
if(this.opts.hoverText)
this.opts.hoverText.before(this.elements.text);
else
this.elements.textContainer.append(this.elements.text);
}
};
ProgressBar.prototype.setHoverText = function(text)
{
this.opts.hoverText = text;
if(this.elements.hoverText)
this.elements.hoverText.text(this.opts.hoverText);
else
{
this.elements.hoverText = $('<ins/>', { text: this.opts.hoverText });
this.elements.textContainer.append(this.elements.hoverText);
}
};
ProgressBar.prototype.setProgress = function(percent)
{
this.opts.progress = percent;
this.elements.progress.css('width', this.opts.progress + '%');
};
ProgressBar.prototype.setWidth = function(width)
{
this.opts.width = width;
if(this.opts.width > 0)
this.elements.container.css('width', this.opts.width + 'px');
else
this.elements.container.css('width', 'auto');
};
ProgressBar.prototype.getText = function()
{
return this.opts.text;
};
ProgressBar.prototype.getHoverText = function()
{
return this.opts.hoverText;
};
ProgressBar.prototype.getWidth = function()
{
return this.opts.width;
};
ProgressBar.prototype.getContainer = function()
{
return this.elements.container;
};

View File

@@ -0,0 +1,35 @@
function Rectangle(left, top, width, height)
{
this.l = left;
this.t = top;
this.r = left + width;
this.b = top + height;
}
Rectangle.prototype = {
intersectWith: function(rect)
{
var result = !(
this.l >= rect.r || rect.l >= this.r ||
this.t >= rect.b || rect.t >= this.b
);
return result;
},
contains: function(rect)
{
var result = (
this.l <= rect.l && this.t <= rect.t &&
this.r >= rect.r && this.b >= rect.b
);
return result;
},
containedIn: function(rect)
{
return rect.contains(this);
}
};

View File

@@ -0,0 +1,48 @@
var RedButton = {
create: function(text, enabled, func)
{
var
a = $WH.ce('a'),
em = $WH.ce('em'),
b = $WH.ce('b'),
i = $WH.ce('i'),
span = $WH.ce('span');
a.href = 'javascript:;';
a.className = 'button-red';
$WH.ae(b, i);
$WH.ae(em, b);
$WH.ae(em, span);
$WH.ae(a, em);
RedButton.setText(a, text);
RedButton.enable(a, enabled);
RedButton.setFunc(a, func);
return a;
},
setText: function(button, text)
{
$WH.st(button.firstChild.childNodes[0].firstChild, text); // em, b, i
$WH.st(button.firstChild.childNodes[1], text); // em, span
},
enable: function(button, enabled)
{
if (enabled || enabled == null)
{
button.className = button.className.replace('button-red-disabled', '');
}
else if (button.className.indexOf('button-red-disabled') == -1)
button.className += ' button-red-disabled';
},
setFunc: function(button, func)
{
$(button).unbind();
if(func)
$(button).click(func);
}
};

View File

@@ -0,0 +1,624 @@
/*
Global screenshot-related functions
*/
function ss_submitAScreenshot()
{
tabsContribute.focus(1);
}
function ss_validateForm(f)
{
if (!f.elements['screenshotfile'].value.length)
{
alert(LANG.message_noscreenshot);
return false;
}
return true;
}
function ss_appendSticky()
{
var _ = $WH.ge('infobox-sticky-ss');
var type = g_pageInfo.type;
var typeId = g_pageInfo.typeId;
var pos = $WH.in_array(lv_screenshots, 1, function(x) { return x.sticky; });
if (pos != -1)
{
var screenshot = lv_screenshots[pos];
var a = $WH.ce('a');
a.href = '#screenshots:id=' + screenshot.id;
a.onclick = function(e) {
ScreenshotViewer.show({ screenshots: lv_screenshots, pos: pos });
return $WH.rf2(e);
};
var size = (lv_videos && lv_videos.length ? [120, 90] : [150, 150]);
var img = $WH.ce('img'),
scale = Math.min(size[0] / screenshot.width, size[1] / screenshot.height);
img.src = g_staticUrl + '/uploads/screenshots/thumb/' + screenshot.id + '.jpg';
img.width = Math.round(scale * screenshot.width);
img.height = Math.round(scale * screenshot.height);
img.className = 'border';
$WH.ae(a, img);
$WH.ae(_, a);
var th = $WH.ge('infobox-screenshots');
var a = $WH.ce('a');
if (!th)
{
var sections = $('th', _.parentNode);
th = sections[sections.length - (lv_videos && lv_videos.length ? 2 : 1)];
}
$WH.ae(a, $WH.ct(th.textContent + ' (' + lv_screenshots.length + ')'));
a.href = '#screenshots'
a.title = $WH.sprintf(LANG.infobox_showall, lv_screenshots.length);
a.onclick = function() {
tabsRelated.focus((lv_videos && lv_videos.length) || (g_user && g_user.roles & (U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_VIDEO)) ? -2 : -1);
return false;
};
$WH.ee(th);
$WH.ae(th, a);
}
else
{
var a;
if (g_user.id > 0)
a = '<a href="javascript:;" onclick="ss_submitAScreenshot(); return false">';
else
a = '<a href="?account=signin">';
_.innerHTML = $WH.sprintf(LANG.infobox_noneyet, a + LANG.infobox_submitone + '</a>');
}
}
var g_screenshots = {};
var ScreenshotViewer = new function()
{
var screenshots,
pos,
imgWidth,
imgHeight,
scale,
desiredScale,
oldHash,
mode = 0,
collectionId,
container,
screen,
imgDiv,
aPrev,
aNext,
aCover,
aOriginal,
divFrom,
divCaption,
loadingImage,
lightboxComponents;
function computeDimensions(captionExtraHeight)
{
var screenshot = screenshots[pos];
var availHeight = Math.max(50, Math.min(618, $WH.g_getWindowSize().h - 72 - captionExtraHeight));
if (mode != 1 || screenshot.id || screenshot.resize)
{
desiredScale = Math.min(772 / screenshot.width, 618 / screenshot.height);
scale = Math.min(772 / screenshot.width, availHeight / screenshot.height);
}
else
{
desiredScale = scale = 1;
}
if (desiredScale > 1)
desiredScale = 1;
if (scale > 1)
scale = 1;
imgWidth = Math.round(scale * screenshot.width);
imgHeight = Math.round(scale * screenshot.height);
var lbWidth = Math.max(480, imgWidth);
Lightbox.setSize(lbWidth + 20, imgHeight + 52 + captionExtraHeight);
if (captionExtraHeight)
{
imgDiv.firstChild.width = imgWidth;
imgDiv.firstChild.height = imgHeight;
}
}
function getPound(pos)
{
var screenshot = screenshots[pos],
buff = '#screenshots:';
if (mode == 0)
buff += 'id=' + screenshot.id;
else
buff += collectionId + ':' + (pos + 1);
return buff;
}
function render(resizing)
{
if (resizing && (scale == desiredScale) && $WH.g_getWindowSize().h > container.offsetHeight)
return;
container.style.visibility = 'hidden';
var screenshot = screenshots[pos],
resized = (screenshot.width > 772 || screenshot.height > 618);
computeDimensions(0);
var url = (screenshot.url ? screenshot.url : g_staticUrl + '/uploads/screenshots/' + (resized ? 'resized/' : 'normal/') + screenshot.id + '.jpg');
var html =
'<img src="' + url + '"'
+ ' width="' + imgWidth + '"'
+ ' height="' + imgHeight + '"'
+ '>';
imgDiv.innerHTML = html;
if (!resizing)
{
g_trackEvent('Screenshots', 'Show', screenshot.id + ( (screenshot.caption && screenshot.caption.length) ? ' (' + screenshot.caption + ')' : ''));
// ORIGINAL
if (screenshot.url)
aOriginal.href = url;
else
aOriginal.href = g_staticUrl + '/uploads/screenshots/normal/' + screenshot.id + '.jpg';
// FROM
if (!screenshot.user && typeof g_pageInfo == 'object')
screenshot.user = g_pageInfo.username;
var hasFrom1 = (screenshot.date && screenshot.user),
hasFrom2 = (screenshots.length > 1);
if (hasFrom1)
{
var postedOn = new Date(screenshot.date),
elapsed = (g_serverTime - postedOn) / 1000;
var a = divFrom.firstChild.childNodes[1];
a.href = '?user=' + screenshot.user;
a.innerHTML = screenshot.user;
var s = divFrom.firstChild.childNodes[3];
$WH.ee(s);
g_formatDate(s, elapsed, postedOn);
divFrom.firstChild.style.display = '';
}
else
divFrom.firstChild.style.display = 'none';
var s = divFrom.childNodes[1];
$WH.ee(s);
if (screenshot.user)
{
if (hasFrom1)
$WH.ae(s, $WH.ct(' ' + LANG.dash + ' '));
var a = $WH.ce('a');
a.href = 'javascript:;';
a.onclick = ContactTool.show.bind(ContactTool, {
mode: 3,
screenshot: screenshot
});
a.className = 'icon-report';
g_addTooltip(a, LANG.report_tooltip, 'q2');
$WH.ae(a, $WH.ct(LANG.report));
$WH.ae(s, a);
}
s = divFrom.childNodes[2];
if (hasFrom2)
{
var buff = '';
if (screenshot.user)
buff = LANG.dash;
buff += (pos + 1) + LANG.lvpage_of + screenshots.length;
s.innerHTML = buff;
s.style.display = '';
}
else
s.style.display = 'none';
divFrom.style.display = (hasFrom1 || hasFrom2 ? '' : 'none');
// CAPTION
// aowow - be locale agnostic
// if (Locale.getId() != LOCALE_ENUS && screenshot.caption)
// screenshot.caption = '';
var hasCaption = (screenshot.caption != null && screenshot.caption.length);
var hasSubject = (screenshot.subject != null && screenshot.subject.length && screenshot.type && screenshot.typeId);
if (hasCaption || hasSubject)
{
var html = '';
if (hasSubject)
{
html += LANG.types[screenshot.type][0] + LANG.colon;
html += '<a href="?' + g_types[screenshot.type] + '=' + screenshot.typeId + '">';
html += screenshot.subject;
html += '</a>';
}
if (hasCaption)
{
if (hasSubject)
html += LANG.dash;
html += (screenshot.noMarkup ? screenshot.caption : Markup.toHtml(screenshot.caption, { mode: Markup.MODE_SIGNATURE }));
}
divCaption.innerHTML = html;
divCaption.style.display = '';
}
else
divCaption.style.display = 'none';
// URLS
if (screenshots.length > 1)
{
aPrev.href = getPound(peekPos(-1));
aNext.href = getPound(peekPos( 1));
aPrev.style.display = aNext.style.display = '';
aCover.style.display = 'none';
}
else
{
aPrev.style.display = aNext.style.display = 'none';
aCover.style.display = '';
}
location.replace(getPound(pos));
}
Lightbox.reveal();
if (divCaption.offsetHeight > 18)
computeDimensions(divCaption.offsetHeight - 18);
container.style.visibility = 'visible';
}
function peekPos(change)
{
var foo = pos;
foo += change;
if (foo < 0)
foo = screenshots.length - 1;
else if (foo >= screenshots.length)
foo = 0;
return foo;
}
function prevScreenshot()
{
pos = peekPos(-1);
onRender();
return false;
}
function nextScreenshot()
{
pos = peekPos(1);
onRender();
return false;
}
function onKeyUp(e)
{
e = $WH.$E(e);
switch (e.keyCode)
{
case 37: // Left
prevScreenshot();
break;
case 39: // Right
nextScreenshot();
break;
}
}
function onResize()
{
render(1);
}
function onHide()
{
cancelImageLoading();
if (screenshots.length > 1)
$WH.dE(document, 'keyup', onKeyUp);
if (oldHash && mode == 0)
{
if (oldHash.indexOf(':id=') != -1)
oldHash = '#screenshots';
location.replace(oldHash);
}
else
location.replace('#.');
}
function onShow(dest, first, opt)
{
if (typeof opt.screenshots == 'string')
{
screenshots = g_screenshots[opt.screenshots];
mode = 1;
collectionId = opt.screenshots;
}
else
{
screenshots = opt.screenshots;
mode = 0;
collectionId = null;
}
container = dest;
pos = 0;
if (opt.pos && opt.pos >= 0 && opt.pos < screenshots.length)
pos = opt.pos;
if (first)
{
dest.className = 'screenshotviewer';
screen = $WH.ce('div');
screen.className = 'screenshotviewer-screen';
aPrev = $WH.ce('a');
aNext = $WH.ce('a');
aPrev.className = 'screenshotviewer-prev';
aNext.className = 'screenshotviewer-next';
aPrev.href = 'javascript:;';
aNext.href = 'javascript:;';
var foo = $WH.ce('span');
var b = $WH.ce('b');
// $WH.ae(b, $WH.ct(LANG.previous));
$WH.ae(foo, b);
$WH.ae(aPrev, foo);
var foo = $WH.ce('span');
var b = $WH.ce('b');
// $WH.ae(b, $WH.ct(LANG.next));
$WH.ae(foo, b);
$WH.ae(aNext, foo);
aPrev.onclick = prevScreenshot;
aNext.onclick = nextScreenshot;
aCover = $WH.ce('a');
aCover.className = 'screenshotviewer-cover';
aCover.href = 'javascript:;';
aCover.onclick = Lightbox.hide;
var foo = $WH.ce('span');
var b = $WH.ce('b');
// $WH.ae(b, $WH.ct(LANG.close));
$WH.ae(foo, b);
$WH.ae(aCover, foo);
$WH.ae(screen, aPrev);
$WH.ae(screen, aNext);
$WH.ae(screen, aCover);
imgDiv = $WH.ce('div');
$WH.ae(screen, imgDiv);
$WH.ae(dest, screen);
var aClose = $WH.ce('a');
aClose.className = 'screenshotviewer-close';
// aClose.className = 'dialog-x';
aClose.href = 'javascript:;';
aClose.onclick = Lightbox.hide;
$WH.ae(aClose, $WH.ce('span')); // aowow - 'close' from texture atlas
// $WH.ae(aClose, $WH.ct(LANG.close));
$WH.ae(dest, aClose);
aOriginal = $WH.ce('a');
aOriginal.className = 'screenshotviewer-original';
// aOriginal.className = 'dialog-arrow';
aOriginal.href = 'javascript:;';
aOriginal.target = '_blank';
$WH.ae(aOriginal, $WH.ce('span')); // aowow - 'original' from texture atlas
// $WH.ae(aOriginal, $WH.ct(LANG.original));
$WH.ae(dest, aOriginal);
divFrom = $WH.ce('div');
divFrom.className = 'screenshotviewer-from';
var sp = $WH.ce('span');
$WH.ae(sp, $WH.ct(LANG.lvscreenshot_from));
$WH.ae(sp, $WH.ce('a'));
$WH.ae(sp, $WH.ct(' '));
$WH.ae(sp, $WH.ce('span'));
$WH.ae(divFrom, sp);
$WH.ae(divFrom, $WH.ce('span'));
$WH.ae(divFrom, $WH.ce('span'));
$WH.ae(dest, divFrom);
divCaption = $WH.ce('div');
divCaption.className = 'screenshotviewer-caption';
$WH.ae(dest, divCaption);
var d = $WH.ce('div');
d.className = 'clear';
$WH.ae(dest, d);
}
oldHash = location.hash;
if (screenshots.length > 1)
$WH.aE(document, 'keyup', onKeyUp);
onRender();
}
function onRender()
{
var screenshot = screenshots[pos];
if (!screenshot.width || !screenshot.height)
{
if (loadingImage)
{
loadingImage.onload = null;
loadingImage.onerror = null;
}
else
{
container.className = '';
lightboxComponents = [];
while (container.firstChild)
{
lightboxComponents.push(container.firstChild);
$WH.de(container.firstChild);
}
}
var lightboxTimer = setTimeout(function() {
screenshot.width = 126;
screenshot.height = 22;
computeDimensions(0);
screenshot.width = null;
screenshot.height = null;
var div = $WH.ce('div');
div.style.margin = '0 auto';
div.style.width = '126px';
var img = $WH.ce('img');
img.src = g_staticUrl + '/images/ui/misc/progress-anim.gif';
img.width = 126;
img.height = 22;
$WH.ae(div, img);
$WH.ae(container, div);
Lightbox.reveal();
container.style.visiblity = 'visible';
}, 150);
loadingImage = new Image();
loadingImage.onload = (function(screen, timer) {
clearTimeout(timer);
screen.width = this.width;
screen.height = this.height;
loadingImage = null;
restoreLightbox();
render();
}).bind(loadingImage, screenshot, lightboxTimer);
loadingImage.onerror = (function(timer) {
clearTimeout(timer);
loadingImage = null;
Lightbox.hide();
restoreLightbox();
}).bind(loadingImage, lightboxTimer);
loadingImage.src = (screenshot.url ? screenshot.url : g_staticUrl + '/uploads/screenshots/normal/' + screenshot.id + '.jpg');
}
else
render();
}
function cancelImageLoading()
{
if (!loadingImage)
return;
loadingImage.onload = null;
loadingImage.onerror = null;
loadingImage = null;
restoreLightbox();
}
function restoreLightbox()
{
if (!lightboxComponents)
return;
$WH.ee(container);
container.className = 'screenshotviewer';
for (var i = 0; i < lightboxComponents.length; ++i)
$WH.ae(container, lightboxComponents[i]);
lightboxComponents = null;
}
this.checkPound = function()
{
if (location.hash && location.hash.indexOf('#screenshots') == 0)
{
if (!g_listviews['screenshots']) // Standalone screenshot viewer
{
var parts = location.hash.split(':');
if (parts.length == 3)
{
var collection = g_screenshots[parts[1]],
p = parseInt(parts[2]);
if (collection && p >= 1 && p <= collection.length)
{
ScreenshotViewer.show({
screenshots: parts[1],
pos: p - 1
});
}
}
}
}
}
this.show = function(opt)
{
Lightbox.show('screenshotviewer', {
onShow: onShow,
onHide: onHide,
onResize: onResize
}, opt);
}
$(document).ready(this.checkPound);
};

View File

@@ -0,0 +1,84 @@
$WH.aE(window, 'load', function ()
{
if (!(window.JSON && $WH.localStorage.isSupported()))
return;
var lv = $WH.localStorage.get('lvBrowse');
if (!lv)
return;
lv = window.JSON.parse(lv);
if (!lv)
return;
var pattern = /^\?[-a-z]+=\d+/i;
// var path = pattern.exec(location.pathname);
var path = pattern.exec(location.search);
if (!path)
return;
path = path[0];
var makeButton = function (text, url)
{
var a = $WH.ce('a');
a.className = 'button-red' + (url ? ' button-red-disabled' : '');
var em = $WH.ce('em');
$WH.ae(a, em);
var b = $WH.ce('b');
$WH.ae(em, b);
var i = $WH.ce('i');
$WH.ae(b, i);
$WH.st(i, text);
var sp = $WH.ce('span');
$WH.ae(em, sp);
$WH.st(sp, text);
return a;
};
for (var i = 0; i < lv.length; i++)
{
var urls = lv[i].urls;
for (var j = 0; j < urls.length; j++)
{
if (urls[j] == path)
{
var prevUrl = j > 0 ? urls[j - 1] : false;
var nextUrl = (j + 1) < urls.length ? urls[j + 1] : false;
var upUrl = lv[i].path + lv[i].hash;
var el = $WH.ge('topbar-browse');
if (!el)
return;
var button;
button = makeButton('>', !nextUrl);
if (nextUrl)
button.href = nextUrl;
$WH.ae(el, button);
button = makeButton(LANG.up, !upUrl);
if (upUrl)
button.href = upUrl;
$WH.ae(el, button);
button = makeButton('<', !prevUrl);
if (prevUrl)
button.href = prevUrl;
$WH.ae(el, button);
return;
}
}
}
});

View File

@@ -0,0 +1,5 @@
/*
- aowow -
ShowOnMap expectd as part of global.js,
but only used for zone and quest endpoint, so kept as separate include
*/

View File

@@ -0,0 +1,289 @@
var Slider = new function()
{
var
start,
handleObj,
timer;
function onMouseDown(e)
{
e = $WH.$E(e);
handleObj = this;
start = $WH.g_getCursorPos(e);
$WH.aE(document, 'mousemove', onMouseMove);
$WH.aE(document, 'mouseup', onMouseUp);
return false;
}
function onMouseMove(e)
{
e = $WH.$E(e);
if (!start || !handleObj)
return;
var
cursor = $WH.g_getCursorPos(e),
delta = cursor[handleObj._dir] - start[handleObj._dir],
outside = setPosition(handleObj, handleObj._pos + delta),
current = getCurrentPosition(handleObj);
if (current && handleObj.input)
handleObj.input.value = current.value;
if (!outside)
start = cursor;
if (handleObj.onMove)
handleObj.onMove(e, handleObj, current);
}
function onMouseUp(e)
{
e = $WH.$E(e);
if (handleObj.onMove)
handleObj.onMove(e, handleObj, getCurrentPosition(handleObj));
handleObj = null;
start = null;
$WH.dE(document, 'mousemove', onMouseMove);
$WH.dE(document, 'mouseup', onMouseUp);
return false;
}
function onClick(obj, e)
{
e = $WH.$E(e);
handleObj = obj;
start = $WH.g_getCursorPos(e);
var
offset = $WH.ac(handleObj.parentNode),
center = Math.floor(getHandleWidth(handleObj) / 2);
setPosition(handleObj, start[handleObj._dir] - offset[handleObj._dir] - center);
var current = getCurrentPosition(handleObj);
if (current && handleObj.input)
handleObj.input.value = current.value;
if (handleObj.onMove)
handleObj.onMove(e, handleObj, current);
$WH.aE(document, 'mousemove', onMouseMove);
$WH.aE(document, 'mouseup', onMouseUp);
return false;
}
function onKeyPress(obj, e)
{
if (timer)
clearTimeout(timer);
if (e.type == 'change' || e.type == 'keypress' && e.which == 13)
onInput(obj, e);
else
timer = setTimeout(onInput.bind(0, obj, e), 1000);
}
function onInput(obj, e)
{
var
value = obj.input.value,
current = getCurrentPosition(obj);
if (isNaN(value))
value = current.value;
if (value > obj._max)
value = obj._max;
if (value < obj._min)
value = obj._min;
Slider.setValue(obj, value);
if (obj.onMove)
obj.onMove(e, obj, getCurrentPosition(obj));
}
function setPosition(obj, offset)
{
var outside = false;
if (offset < 0)
{
offset = 0;
outside = true;
}
else if (offset > getMaxPosition(obj))
{
offset = getMaxPosition(obj);
outside = true;
}
obj.style[(obj._dir == 'y' ? 'top' : 'left')] = offset + 'px';
obj._pos = offset;
return outside;
}
function getMaxPosition(obj)
{
return getTrackerWidth(obj) - getHandleWidth(obj) + 2;
}
function getCurrentPosition(obj)
{
var
percent = obj._pos / getMaxPosition(obj),
value = Math.round((percent * (obj._max - obj._min)) + obj._min),
result = [percent, value];
result.percent = percent;
result.value = value;
return result;
}
function getTrackerWidth(obj) {
if (obj._tsz > 0) {
return obj._tsz;
}
if (obj._dir == 'y') {
return obj.parentNode.offsetHeight;
}
return obj.parentNode.offsetWidth;
}
function getHandleWidth(obj) {
if (obj._hsz > 0)
return obj._hsz;
if (obj._dir == 'y')
return obj.offsetHeight;
return obj.offsetWidth;
}
this.setPercent = function(obj, percent)
{
setPosition(obj, parseInt(percent * getMaxPosition(obj)));
}
this.setValue = function(obj, value)
{
if (value < obj._min)
value = obj._min;
else if (value > obj._max)
value = obj._max;
if (obj.input)
obj.input.value = value;
this.setPercent(obj, (value - obj._min) / (obj._max - obj._min));
}
this.setSize = function(obj, length)
{
var
current = getCurrentPosition(obj),
resized = getMaxPosition(obj);
obj.parentNode.style[(obj._dir == 'y' ? 'height' : 'width')] = length + 'px';
if (resized != getMaxPosition(obj))
this.setValue(obj, current.value);
}
this.init = function(container, opt)
{
var obj = $WH.ce('a');
obj.href = 'javascript:;';
obj.onmousedown = onMouseDown;
obj.className = 'handle';
var track = $WH.ce('a');
track.href = 'javascript:;';
track.onmousedown = onClick.bind(0, obj);
track.className = 'track';
$WH.ae(container, $WH.ce('span'));
$WH.ae(container, track);
$WH.ae(container, obj);
obj._dir = 'x';
obj._min = 1;
obj._max = 100;
obj._pos = 0;
obj._tsz = 0;
obj._hsz = 0;
if (opt != null)
{
// Orientation
if (opt.direction == 'y')
obj._dir = 'y';
// Values
if (opt.minValue)
obj._min = opt.minValue;
if (opt.maxValue)
obj._max = opt.maxValue;
// Functions
if (opt.onMove)
obj.onMove = opt.onMove;
if (opt.trackSize)
obj._tsz = opt.trackSize;
if (opt.handleSize)
obj._hsz = opt.handleSize;
// Labels
if (opt.showLabels !== false)
{
var label = $WH.ce('div');
label.innerHTML = obj._min;
label.className = 'label min';
$WH.ae(container, label);
label = $WH.ce('div');
label.innerHTML = obj._max;
label.className = 'label max';
$WH.ae(container, label);
obj.input = $WH.ce('input');
$(obj.input).attr({ value: obj._max, type: 'text' })
.bind('click', function () { this.select(); })
.keypress(function (e) {
var allowed = [];
var usedKey = e.which;
for (i = 48; i < 58; i++)
allowed.push(i);
if (!($WH.in_array(allowed, usedKey) >= 0) && usedKey != 13)
e.preventDefault();
})
.bind('keyup keydown change', onKeyPress.bind(0, obj));
obj.input.className = 'input';
$WH.ae(container, obj.input);
}
}
container.className = 'slider-' + obj._dir + (opt == null || opt.showLabels !== false ? ' has-labels' : '');
return obj;
}
};

View File

@@ -0,0 +1,78 @@
/*
Global functions related to the Summary class (item comparison, item set summary)
*/
var suDialog;
function su_addToSaved(items, nItems, newWindow, level)
{
if (!items)
return;
if (!suDialog)
suDialog = new Dialog();
var doCompare = function(data)
{
var saved = g_getWowheadCookie('compare_groups'),
url = '?compare';
if (data.action > 1) // Save
{
if (saved)
items = saved + ';' + items;
g_setWowheadCookie('compare_groups', items, true);
if (level)
g_setWowheadCookie('compare_level', level, true);
}
else // Don't save
url += '=' + items + (level ? '&l=' + level : '');
if (data.action < 3) // View now
{
if (newWindow)
window.open(url);
else
location.href = url;
}
};
suDialog.show('docompare', {
data: { selecteditems: nItems, action: 1 },
onSubmit: doCompare
});
}
Dialog.templates.docompare = {
title: LANG.dialog_compare,
width: 400,
// buttons: [['check', LANG.ok], ['x', LANG.cancel]],
buttons: [['okay', LANG.ok], ['cancel', LANG.cancel]],
fields:
[
{
id: 'selecteditems',
type: 'caption',
compute: function(field, value, form, td)
{
td.innerHTML = $WH.sprintf((value == 1 ? LANG.dialog_selecteditem : LANG.dialog_selecteditems), value);
}
},
{
id: 'action',
type: 'radio',
label: '',
value: 3,
submitOnDblClick: 1,
options: {
1: LANG.dialog_nosaveandview,
2: LANG.dialog_saveandview,
3: LANG.dialog_saveforlater
}
}
]
};

View File

@@ -0,0 +1,364 @@
function Tabs(opt)
{
$WH.cO(this, opt);
if (this.parent)
this.parent = $WH.ge(this.parent);
else
return;
this.selectedTab = -1;
// spiffyjr - This could eventually be removed. Refactored to remove multiple ul/li's.
this.uls = [];
this.tabs = [];
this.nShows = 0;
if (this.poundable == null)
this.poundable = 1;
this.poundedTab = null;
if (this.onLoad == null)
this.onLoad = Tabs.onLoad.bind(this);
if (this.onShow == null)
this.onShow = Tabs.onShow.bind(this);
if (this.onHide)
this.onHide = this.onHide.bind(this);
this.trackClick = Tabs.trackClick.bind(this);
}
Tabs.prototype = {
add: function(caption, opt)
{
var _,
index = this.tabs.length;
_ = {
caption: caption,
index: index,
owner: this
};
$WH.cO(_, opt);
this.tabs.push(_);
return index;
},
hide: function(index, visible)
{
if (this.tabs[index])
{
var selectedTab = this.selectedTab;
if (index == 0 && selectedTab == -1)
this.poundedTab = this.selectedTab = selectedTab = 0;
if (index != this.poundedTab)
this.selectedTab = -1;
this.tabs[index].hidden = !visible;
this.flush();
if (!visible && index == selectedTab)
{
this.selectedTab = selectedTab;
for (var i = 0, len = this.tabs.length; i < len; ++i)
{
if (i != index && !this.tabs[i].hidden)
return this.show(i, 1);
}
}
}
},
unlock: function(index, locked)
{
if (this.tabs[index])
{
this.tabs[index].locked = locked;
_ = $WH.gE(this.uls[0], 'a');
$('.icon-lock', _[index]).remove();
if (locked)
$('div, b', _[index]).prepend('<span class="icon-lock" />');
var _ = location.hash.substr(1).split(':')[0];
if (this.tabs[index].id == _)
this.show(index, 1);
}
},
focus: function(index)
{
if (index < 0)
index = this.tabs.length + index;
this.forceScroll = 1;
$WH.gE(this.uls[0], 'a')[index].onclick({}, true);
this.forceScroll = null;
},
show: function(index, forceClick)
{
var _;
if (isNaN(index) || index < 0)
index = 0;
else if (index >= this.tabs.length)
index = this.tabs.length - 1;
if ((forceClick == null && index == this.selectedTab) || this.tabs[index].hidden)
return;
if (this.tabs[index].locked)
return this.onShow(this.tabs[index], this.tabs[this.selectedTab]);
if (this.selectedTab != -1)
{
_ = this.tabs[this.selectedTab];
if (this.onHide && !this.onHide(_))
return;
if (_.onHide && !_.onHide())
return;
}
++this.nShows;
_ = $WH.gE(this.uls[0], 'a');
if (this.selectedTab != -1)
_[this.selectedTab].className = '';
_[index].className = 'selected';
_ = this.tabs[index];
if (_.onLoad)
{
_.onLoad();
_.onLoad = null;
}
this.onShow(this.tabs[index], this.tabs[this.selectedTab]);
if (_.onShow)
_.onShow(this.tabs[this.selectedTab]);
this.selectedTab = index;
},
flush: function(defaultTab)
{
var _, l, a, b, d, d2;
var container = $WH.ce('div');
container.className = 'tabs-container';
this.uls[0] = $WH.ce('ul');
this.uls[0].className = 'tabs';
d = $WH.ce('div');
d.className = 'tabs-levels';
$WH.ae(container, this.uls[0]);
for (var i = 0; i < this.tabs.length; ++i)
{
var tab = this.tabs[i];
l = $WH.ce('li');
b = $WH.ce('b');
a = $WH.ce('a');
if (tab.hidden)
l.style.display = 'none';
if (this.poundable)
a.href = '#' + tab.id;
else
a.href = 'javascript:;';
$WH.ns(a);
a.onclick = Tabs.onClick.bind(tab, a);
d = $WH.ce('div');
if (tab.locked)
{
s = $WH.ce('span');
s.className = 'icon-lock';
$WH.ae(d, s);
}
else if (tab.icon)
{
s = $WH.ce('span');
s.className = 'icontiny';
s.style.backgroundImage = 'url(' + g_staticUrl + '/images/wow/icons/tiny/' + tab.icon.toLowerCase() + '.gif)';
$WH.ae(d, s);
}
if (tab.tooltip)
{
a.onmouseover = (function(tooltip, e) { $WH.Tooltip.showAtCursor(e, tooltip, 0, 0, 'q'); }).bind(a, tab.tooltip);
a.onmousemove = $WH.Tooltip.cursorUpdate;
a.onmouseout = $WH.Tooltip.hide;
}
if (tab['class'])
d.className = tab['class'];
$WH.ae(d, $WH.ct(tab.caption));
$WH.ae(a, d);
if (tab.locked)
{
s = $WH.ce('span');
s.className = 'icon-lock';
$WH.ae(b, s);
}
else if (tab.icon)
{
s = $WH.ce('span');
s.className = 'icontiny';
s.style.backgroundImage = 'url(' + g_staticUrl + '/images/wow/icons/tiny/' + tab.icon.toLowerCase() + '.gif)';
$WH.ae(b, s);
}
$WH.ae(b, $WH.ct(tab.caption));
$WH.ae(a, b);
$WH.ae(l, a);
$WH.ae(this.uls[0], l);
}
$WH.ee(this.parent);
$WH.ae(this.parent, container);
if (this.onLoad)
{
_ = this.onLoad();
if (_ != null)
this.poundedTab = defaultTab = _;
}
this.show(defaultTab);
},
setTabName: function(index, name)
{
this.tabs[index].caption = name;
var _ = $WH.gE(this.uls[0], 'a');
g_setTextNodes(_[index], name);
},
setTabPound: function(index, pound)
{
if (!this.poundable)
return;
var _ = $WH.gE(this.uls[0], 'a');
_[index].href = '#' + this.tabs[index].id + (pound ? ':' + pound : '');
},
setTabTooltip: function(index, text)
{
this.tabs[index].tooltip = text;
var _ = $WH.gE(this.uls[0], 'a');
if (text == null)
_[index].onmouseover = _[index].onmousemove = _[index].onmouseout = null;
else
{
_[index].onmouseover = function(e) { $WH.Tooltip.showAtCursor(e, text, 0, 0, 'q2'); };
_[index].onmousemove = $WH.Tooltip.cursorUpdate;
_[index].onmouseout = $WH.Tooltip.hide;
}
},
getSelectedTab: function()
{
return this.selectedTab;
}
};
Tabs.onClick = function(a, e, forceClick)
{
if (forceClick == null && this.index == this.owner.selectedTab)
return;
var res = $WH.rf2(e);
if (res == null)
return;
this.owner.show(this.index, forceClick);
if (this.owner.poundable && !this.locked)
{
var _ = a.href.indexOf('#');
_ != -1 && location.replace(a.href.substr(_));
}
return res;
};
Tabs.onLoad = function()
{
if (!this.poundable || !location.hash.length)
return;
var _ = location.hash.substr(1).split(':')[0];
if (_)
return $WH.in_array(this.tabs, _, function(x) {
if (!x.locked)
return x.id;
});
};
Tabs.onShow = function(newTab, oldTab)
{
var _;
if (newTab.hidden || newTab.locked)
return;
if (oldTab)
$WH.ge('tab-' + oldTab.id).style.display = 'none';
if (this.poundedTab != null || oldTab)
this.trackClick(newTab);
_ = $WH.ge('tab-' + newTab.id);
_.style.display = '';
if (((this.nShows == 1 && this.poundedTab != null && this.poundedTab >= 0) || this.forceScroll) && !this.noScroll)
{
var el, padd;
if (this.__st)
{
el = this.__st;
padd = 15;
}
else
{
el = _;
padd = this.parent.offsetHeight + 15;
}
setTimeout($WH.g_scrollTo.bind(null, el, padd), 10);
}
};
Tabs.trackClick = function(tab)
{
if (!this.trackable || tab.tracked)
return;
g_trackEvent('Tabs', 'Show', this.trackable + ': ' + tab.id);
tab.tracked = 1;
}

View File

@@ -0,0 +1,130 @@
/*
TODO: Create "Tracking" class
*/
function g_trackPageview(tag)
{
function track()
{
if (typeof ga == 'function')
ga('send', 'pageview', tag);
};
$(document).ready(track);
}
function g_trackEvent(category, action, label, value)
{
function track()
{
if (typeof ga == 'function')
ga('send', 'event', category, action, label, value);
};
$(document).ready(track);
}
function g_attachTracking(node, category, action, label, value)
{
var $node = $(node);
$node.click(function()
{
g_trackEvent(category, action, label, value);
});
}
function g_addAnalytics()
{
var objs = {
'home-logo': {
'category': 'Homepage Logo',
'actions': {
'Click image': function(node) { return true; }
}
},
'home-featuredbox': {
'category': 'Featured Box',
'actions': {
'Follow link': function(node) { return (node.parentNode.className != 'home-featuredbox-links'); },
'Click image': function(node) { return (node.parentNode.className == 'home-featuredbox-links'); }
}
},
'home-oneliner': {
'category': 'Oneliner',
'actions': {
'Follow link': function(node) { return true; }
}
},
'sidebar-container': {
'category': 'Page sidebar',
'actions': {
'Click image': function(node) { return true; }
}
},
'toptabs-promo': {
'category': 'Page header',
'actions': {
'Click image': function(node) { return true; }
}
}
};
for (var i in objs)
{
var e = $WH.ge(i);
if (e)
g_addAnalyticsToNode(e, objs[i]);
}
}
function g_getNodeTextId(node)
{
var id = null,
text = g_getFirstTextContent(node);
if (text)
id = g_urlize(text);
else if (node.title)
id = g_urlize(node.title);
else if (node.id)
id = g_urlize(node.id);
return id;
}
function g_addAnalyticsToNode(node, opts, labelPrefix)
{
if (!opts || !opts.actions || !opts.category)
{
if ($WH.isset('g_dev') && g_dev)
{
console.log('Tried to add analytics event without appropriate parameters.');
console.log(node);
console.log(opts);
}
return;
}
var category = opts.category;
var tags = $WH.gE(node, 'a');
for (var i = 0; i < tags.length; ++i)
{
var node = tags[i];
var action = 'Follow link';
for (var a in opts.actions)
{
if (opts.actions[a] && opts.actions[a](node))
{
action = a;
break;
}
}
var label = (labelPrefix ? labelPrefix + '-' : '') + g_getNodeTextId(node);
g_attachTracking(node, category, action, label);
}
}
$(document).ready(g_addAnalytics);

View File

@@ -0,0 +1,887 @@
/*
Global functions related to UI elements and effects
*/
function g_getReputationPlusAchievementText(gold, silver, copper, reputation)
{
// aowow - WSA not in use
// var achievements = g_getAchievementText(gold, silver, copper, true);
var repText = $('<span>').addClass('wsach-pts');
repText.mouseover(function(event) {
$WH.Tooltip.showAtCursor(event, LANG.reputationtip, 0, 0, 'q');
}).mousemove(function(event) {
$WH.Tooltip.cursorUpdate(event);
}).mouseout(function() {
$WH.Tooltip.hide();
});
repText.css('color', 'white');
repText.text($WH.number_format(reputation));
var ret = $('<span>');
ret.append(' (');
ret.append(repText);
// ret.append(' &ndash; ');
// ret.append(achievements);
ret.append(')');
return ret;
}
function g_getAchievementText(gold, silver, copper, forumPost)
{
var ret = $('<span>').addClass('wsach-pts');
ret.mouseover(function(event) {$WH.Tooltip.showAtCursor(event, LANG.userachcount_tip, 0, 0, 'q');}).mousemove(function(event) {$WH.Tooltip.cursorUpdate(event)}).mouseout(function() {$WH.Tooltip.hide()});
var html = ' ';
if (!forumPost)
html += ' (';
if (gold)
html += '<i>' + gold + '</i>' + '&middot;';
if (silver)
html += '<b>' + silver + '</b>' + '&middot;';
if (!copper)
copper = 0;
html += '<u>' + copper + '</u>';
if (!forumPost)
html += ')';
ret.html(html);
return ret;
}
function g_addTooltip(element, text, className)
{
if (!className && text.indexOf('<table>') == -1)
className = 'q';
$WH.Tooltip.simple(element, text, className);
}
function g_addStaticTooltip(icon, text, className)
{
if (!className && text.indexOf('<table>') == -1)
className = 'q';
icon.onmouseover = function(event)
{
$WH.Tooltip.show(icon, text, 0, 0, className);
};
icon.onmouseout = $WH.Tooltip.hide;
}
/* If maxDelay is set, and delay > maxDelay, the full date will be shown instead. */
function g_formatTimeElapsed(delay)
{
function OMG(value, unit, abbrv)
{
if (abbrv && LANG.timeunitsab[unit] == '')
abbrv = 0;
if (abbrv)
return value + ' ' + LANG.timeunitsab[unit];
else
return value + ' ' + (value == 1 ? LANG.timeunitssg[unit] : LANG.timeunitspl[unit]);
}
var range = [31557600, 2629800, 604800, 86400, 3600, 60, 1];
var subunit = [1, 3, 3, -1, 5, -1, -1];
delay = Math.max(delay, 1);
for (var i = 3, len = range.length; i < len; ++i)
{
if (delay >= range[i])
{
var i1 = i;
var v1 = Math.floor(delay / range[i1]);
if (subunit[i1] != -1)
{
var i2 = subunit[i1];
delay %= range[i1];
var v2 = Math.floor(delay / range[i2]);
if (v2 > 0)
return OMG(v1, i1, 1) + ' ' + OMG(v2, i2, 1);
}
return OMG(v1, i1, 0);
}
}
return '(n/a)';
}
function g_GetStaffColorFromRoles(roles)
{
if (roles & U_GROUP_ADMIN)
return 'comment-blue';
if (roles & U_GROUP_GREEN_TEXT) // Mod, Bureau, Dev
return 'comment-green';
if (roles & U_GROUP_VIP) // VIP
return 'comment-gold';
if (roles & U_GROUP_PREMIUMISH) // Premium, Editor
return 'comment-gold';
return '';
}
// aowow - stand in for WH.User.getCommentRoleLabel
function g_GetCommentRoleLabel(roles, title)
{
if (title)
return title;
if (roles & U_GROUP_ADMIN)
return g_user_roles[2]; // LANG.administrator_abbrev
if (roles & U_GROUP_MOD)
return g_user_roles[4]; // LANG.moderator
if (roles & U_GROUP_PREMIUMISH)
return LANG.premiumuser;
return null;
};
function g_formatDate(sp, elapsed, theDate, time, alone)
{
var today = new Date();
var event_day = new Date();
event_day.setTime(today.getTime() - (1000 * elapsed));
var txt;
var event_day_midnight = new Date(event_day.getYear(), event_day.getMonth(), event_day.getDate());
var today_midnight = new Date(today.getYear(), today.getMonth(), today.getDate());
var delta = (today_midnight.getTime() - event_day_midnight.getTime());
delta /= 1000;
delta /= 86400;
delta = Math.round(delta);
if (elapsed >= 2592000) /* More than a month ago */
{
txt = LANG.date_on + g_formatDateSimple(theDate, time);
}
else if (delta > 1)
{
txt = $WH.sprintf(LANG.ddaysago, delta);
if (sp)
{
var _ = new Date();
_.setTime(theDate.getTime() + (g_localTime - g_serverTime));
sp.className += ' tip';
sp.title = _.toLocaleString();
}
}
else if (elapsed >= 43200)
{
if (today.getDay() == event_day.getDay())
txt = LANG.today;
else
txt = LANG.yesterday;
txt = g_formatTimeSimple(event_day, txt);
if (sp)
{
var _ = new Date();
_.setTime(theDate.getTime() + (g_localTime - g_serverTime));
sp.className += ' tip';
sp.title = _.toLocaleString();
}
}
else /* Less than 12 hours ago */
{
var txt = $WH.sprintf(LANG.date_ago, g_formatTimeElapsed(elapsed));
if (sp)
{
var _ = new Date();
_.setTime(theDate.getTime() + (g_localTime - g_serverTime));
sp.className += ' tip';
sp.title = _.toLocaleString();
}
}
if (alone == 1)
txt = txt.substr(0, 1).toUpperCase() + txt.substr(1);
if (sp)
$WH.ae(sp, $WH.ct(txt));
else
return txt;
}
function g_formatDateSimple(d, time)
{
function __twoDigits(n)
{
return (n < 10 ? '0' + n : n);
}
var b = '',
day = d.getDate(),
month = d.getMonth() + 1,
year = d.getFullYear();
if (year <= 1970)
b += LANG.unknowndate_stc;
else
b += $WH.sprintf(LANG.date_simple, __twoDigits(day), __twoDigits(month), year);
if (time != null)
b = g_formatTimeSimple(d, b);
return b;
}
function g_formatTimeSimple(d, txt, noPrefix)
{
function __twoDigits(n)
{
return (n < 10 ? '0' + n : n);
}
var hours = d.getHours(),
minutes = d.getMinutes();
if (txt == null)
txt = '';
txt += (noPrefix ? ' ' : LANG.date_at);
if (hours == 12)
txt += LANG.noon;
else if (hours == 0)
txt += LANG.midnight;
else if (hours > 12)
txt += (hours - 12) + ':' + __twoDigits(minutes) + ' ' + LANG.pm;
else
txt += hours + ':' + __twoDigits(minutes) + ' ' + LANG.am;
return txt;
}
function g_createGlow(txt, cn)
{
var s = $WH.ce('span');
for (var i = -1; i <= 1; ++i)
{
for (var j = -1; j <= 1; ++j)
{
var d = $WH.ce('div');
d.style.position = 'absolute';
d.style.whiteSpace = 'nowrap';
d.style.left = i + 'px';
d.style.top = j + 'px';
if (i == 0 && j == 0)
d.style.zIndex = 4;
else
{
d.style.color = 'black';
d.style.zIndex = 2;
}
//$WH.ae(d, $WH.ct(txt));
d.innerHTML = txt;
$WH.ae(s, d);
}
}
s.style.position = 'relative';
s.className = 'glow' + (cn != null ? ' ' + cn : '');
var ph = $WH.ce('span');
ph.style.visibility = 'hidden';
$WH.ae(ph, $WH.ct(txt));
$WH.ae(s, ph);
return s;
}
function g_createProgressBar(opt)
{
if (opt == null)
opt = {};
if (typeof opt.text == 'undefined')
opt.text = ' ';
if (opt.color == null)
opt.color = 'rep0';
if (opt.width == null || opt.width > 100)
opt.width = 100;
var el, div;
if (opt.hoverText)
{
el = $WH.ce('a');
el.href = 'javascript:;';
}
else
el = $WH.ce('span');
el.className = 'progressbar';
if (opt.text || opt.hoverText)
{
div = $WH.ce('div');
div.className = 'progressbar-text';
if (opt.text)
{
var del = $WH.ce('del');
$WH.ae(del, $WH.ct(opt.text));
$WH.ae(div, del);
}
if (opt.hoverText)
{
var ins = $WH.ce('ins');
$WH.ae(ins, $WH.ct(opt.hoverText));
$WH.ae(div, ins);
}
$WH.ae(el, div);
}
div = $WH.ce('div');
div.className = 'progressbar-' + opt.color;
div.style.width = opt.width + '%';
if (opt.height)
div.style.height = opt.height;
$WH.ae(div, $WH.ct(String.fromCharCode(160)));
$WH.ae(el, div);
if (opt.text)
{
var div = $WH.ce('div');
div.className = 'progressbar-text progressbar-hidden';
$WH.ae(div, $WH.ct(opt.text));
$WH.ae(el, div);
}
return el;
}
function g_createReputationBar(totalRep)
{
var P = g_createReputationBar.P;
if (!totalRep)
totalRep = 0;
totalRep += 42000;
if (totalRep < 0)
totalRep = 0;
else if (totalRep > 84999)
totalRep = 84999;
var currentRep = totalRep,
maxRep,
standing = 0;
for (var i = 0, len = P.length; i < len; ++i)
{
if (P[i] > currentRep)
break;
if (i < len - 1)
{
currentRep -= P[i];
standing = i + 1;
}
}
maxRep = P[standing];
var opt = {
text: g_reputation_standings[standing],
hoverText: currentRep + ' / ' + maxRep,
color: 'rep' + standing,
width: parseInt(currentRep / maxRep * 100)
};
return g_createProgressBar(opt);
}
g_createReputationBar.P = [36000, 3000, 3000, 3000, 6000, 12000, 21000, 999];
function g_createAchievementBar(points, outOf, overall, bonus)
{
if (!points)
points = 0;
var opt = {
text: points + (bonus > 0 ? '(+' + bonus + ')' : '') + (outOf > 0 ? ' / ' + outOf : ''),
color: (overall ? 'rep7' : 'ach' + (outOf > 0 ? 0 : 1)),
width: (outOf > 0 ? parseInt(points / outOf * 100) : 100)
};
return g_createProgressBar(opt);
}
function g_getMoneyHtml(money, side, costItems, costCurrency, achievementPoints)
{
var ns = 0,
html = '';
if (side == 1 || side == 'alliance')
side = 1;
else if (side == 2 || side == 'horde')
side = 2;
else
side = 3;
if (money >= 10000)
{
ns = 1;
var display = Math.floor(money / 10000);
html += '<span class="moneygold">' + $WH.number_format(display) + '</span>';
money %= 10000;
}
if (money >= 100)
{
if (ns)
html += ' ';
else
ns = 1;
var display = Math.floor(money / 100);
html += '<span class="moneysilver">' + display + '</span>';
money %= 100;
}
if (money >= 1)
{
if (ns)
html += ' ';
else
ns = 1;
html += '<span class="moneycopper">' + money + '</span>';
}
if (costItems != null)
{
for (var i = 0; i < costItems.length; ++i)
{
if (ns)
html += ' ';
else
ns = 1;
var itemId = costItems[i][0];
var count = costItems[i][1];
var icon = (g_items[itemId] && g_items[itemId].icon ? g_items[itemId].icon : 'inv_misc_questionmark');
html += '<a href="?item=' + itemId + '" class="moneyitem" style="background-image: url(' + g_staticUrl + '/images/wow/icons/tiny/' + icon.toLowerCase() + '.gif)">' + count + '</a>';
}
}
if (costCurrency != null)
{
for (var i = 0; i < costCurrency.length; ++i)
{
if (ns)
html += ' ';
else
ns = 1;
var currencyId = costCurrency[i][0];
var count = costCurrency[i][1];
var icon = (g_gatheredcurrencies[currencyId] && g_gatheredcurrencies[currencyId].icon ? g_gatheredcurrencies[currencyId].icon : ['inv_misc_questionmark', 'inv_misc_questionmark']);
if (side == 3 && icon[0] == icon[1])
side = 1;
// aowow: custom start
if (currencyId == 103) // arena
html += '<a href="?currency=' + currencyId + '" class="moneyarena tip" onmouseover="Listview.funcBox.moneyArenaOver(event)" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()">' + $WH.number_format(count) + '</a>';
else if (currencyId == 104) // honor
html += '<a href="?currency=' + currencyId + '" class="money' + (side == 1 ? 'alliance' : 'horde') + ' tip" onmouseover="Listview.funcBox.moneyHonorOver(event)" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()">' + (side == 3 ? '<span class="moneyalliance">' : '') + $WH.number_format(count) + (side == 3 ? '</span>' : '') + '</a>';
else // tokens
html += '<a href="?currency=' + currencyId + '" class="icontinyr tip q1" onmouseover="Listview.funcBox.moneyCurrencyOver(' + currencyId + ', ' + count + ', event)" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()" style="background-image: url(' + g_staticUrl + '/images/wow/icons/tiny/' + icon[0].toLowerCase() + '.gif)">' + count + '</a>';
// aowow: custom end
// html += '<a href="?currency=' + currencyId + '" class="icontinyr tip q1" onmouseover="Listview.funcBox.moneyCurrencyOver(' + currencyId + ', ' + count + ', event)" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()" style="background-image: url(' + g_staticUrl + '/images/icons/tiny/' + icon[(side == 3 ? 1 : side - 1)].toLowerCase() + '.gif)">' + (side == 3 ? '<span class="icontinyr" style="background-image: url(' + g_staticUrl + '/images/icons/tiny/' + icon[0].toLowerCase() + '.gif)">' : '') + count + (side == 3 ? '</span>' : '') + '</a>';
}
}
if (achievementPoints > 0)
{
if (ns)
html += ' ';
else
ns = 1;
html += '<span class="moneyachievement tip" onmouseover="Listview.funcBox.moneyAchievementOver(event)" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()">' + $WH.number_format(achievementPoints) + '</span>';
}
return html;
}
function g_pickerWheel(e)
{
e = $WH.$E(e);
if (e._wheelDelta < 0)
this.scrollTop += 27;
else
this.scrollTop -= 27;
}
function g_setSelectedLink(n, group)
{
if (!g_setSelectedLink.groups)
g_setSelectedLink.groups = {};
var _ = g_setSelectedLink.groups;
if (_[group])
_[group].className = _[group].className.replace('selected', '');
n.className += ' selected';
_[group] = n;
}
function g_setCheckedRow(n, group)
{
if (!g_setCheckedRow.groups)
g_setCheckedRow.groups = {};
var _ = g_setCheckedRow.groups;
if (_[group])
_[group].className = _[group].className.replace('checked', '');
n.className += ' checked';
_[group] = n;
}
function g_addPages(d, opt)
{
function createPageSquare(n, customText)
{
var foo;
if (n == opt.page)
{
foo = $WH.ce('span');
foo.className = 'selected';
}
else
{
foo = $WH.ce('a');
foo.href = (n > 1 ? opt.url + opt.sep + n + opt.pound : opt.url + opt.pound);
}
$WH.ae(foo, $WH.ct(customText != null ? customText : n));
return foo;
}
if (!opt.pound)
opt.pound = '';
if (!opt.sep)
opt.sep = '.';
if (opt.allOrNothing && opt.nPages <= 1)
return;
var leftAligned = (opt.align && opt.align == 'left');
var divPages = $WH.ce('div'),
pagesNumbers,
para = $WH.ce('var');
divPages.className = 'pages';
if (leftAligned)
divPages.className += ' pages-left';
// Pages
if (opt.nPages > 1)
{
pagesNumbers = $WH.ce('div');
pagesNumbers.className = 'pages-numbers';
var minPage = Math.max(2, opt.page - 2);
var maxPage = Math.min(opt.nPages - 1, opt.page + 2);
var elements = []; // Temporarily stored in an array so the order can be reversed when left-aligned.
if (opt.page != opt.nPages)
elements.push(createPageSquare(opt.page + 1, LANG.lvpage_next + String.fromCharCode(8250)));
elements.push(createPageSquare(opt.nPages));
if (maxPage < opt.nPages - 1)
{
var sp = $WH.ce('span');
$WH.ae(sp, $WH.ct('...'));
elements.push(sp);
}
for (var i = maxPage; i >= minPage; --i)
elements.push(createPageSquare(i));
if (minPage > 2)
{
var sp = $WH.ce('span');
$WH.ae(sp, $WH.ct('...'));
elements.push(sp);
}
elements.push(createPageSquare(1));
if (opt.page != 1)
elements.push(createPageSquare(opt.page - 1, String.fromCharCode(8249) + LANG.lvpage_previous));
if (leftAligned)
elements.reverse();
for (var i = 0, len = elements.length; i < len; ++i)
$WH.ae(pagesNumbers, elements[i]);
pagesNumbers.firstChild.style.marginRight = '0';
pagesNumbers.lastChild.style.marginLeft = '0';
}
// Number of items
var para = $WH.ce('var');
$WH.ae(para, $WH.ct($WH.sprintf(LANG[opt.wording[opt.nItems == 1 ? 0 : 1]], opt.nItems)));
if (opt.nPages > 1) // Go to page
{
var sp = $WH.ce('span');
$WH.ae(sp, $WH.ct(String.fromCharCode(8211)));
$WH.ae(para, sp);
var pageIcon = $WH.ce('a');
pageIcon.className = 'gotopage';
pageIcon.href = 'javascript:;';
$WH.ns(pageIcon);
pageIcon.onclick = function()
{
var n = prompt($WH.sprintf(LANG.prompt_gotopage, 1, opt.nPages), opt.page);
if (n != null)
{
n |= 0;
if (n != opt.page && n >= 1 && n <= opt.nPages)
document.location.href = (n > 1 ? opt.url + opt.sep + n + opt.pound : opt.url + opt.pound);
}
};
pageIcon.onmouseover = function(event)
{
$WH.Tooltip.showAtCursor(event, LANG.tooltip_gotopage, 0, 0, 'q2');
};
pageIcon.onmousemove = $WH.Tooltip.cursorUpdate;
pageIcon.onmouseout = $WH.Tooltip.hide;
$WH.ae(para, pageIcon);
}
if (leftAligned)
{
$WH.ae(divPages, para);
if (pagesNumbers)
$WH.ae(divPages, pagesNumbers);
}
else
{
if (pagesNumbers)
$WH.ae(divPages, pagesNumbers);
$WH.ae(divPages, para);
}
$WH.ae(d, divPages);
}
function g_disclose(el, _this)
{
_this.className = 'disclosure-' + (g_toggleDisplay(el) ? 'on' : 'off');
return false;
}
/* Displays a warning when the user attempts to leave the page if some elements are modified, unless the user leaves the page
* by submitting the form.
*
* The jQuery form object must be passed as first argument; the second argument is an array of jQuery objects of fields that
* are being watched for changes. The third argument is the warning message shown.
*
* This function must be called in the on ready event.
*/
function g_setupChangeWarning(form, elements, warningMessage)
{
if (!form)
return;
function ShowWarning() { return warningMessage; }
form.submit(function() { window.onbeforeunload = null; });
var initialText = [];
for (var idx in elements)
{
var text = elements[idx];
if (!text)
continue;
initialText[idx] = text.val();
text.keydown(function()
{
for (var idx in elements)
{
var text = elements[idx];
if (!text)
continue;
if (text.val() != initialText[idx])
{
window.onbeforeunload = ShowWarning;
return;
}
window.onbeforeunload = null;
}
});
}
}
$(document).ready(function() {
$WH.array_apply($WH.gE(document, 'dfn'), function(x) {
var text = x.title;
x.title = '';
x.className += ' tip';
if (text.indexOf('LANG.') === 0) // aowow - custom for less redundant texts
text = eval(text);
g_addTooltip(x, text, 'q');
});
// aowow - if i understand this right, this code binds an onCopy eventHandler to every child node of class="text"-nodes with the attribute unselectable="on"
// causing the text to disappear for 1ms, causing the empty node to be copied ... w/e, i'm not going to use this
/*
$('.text').bind('copy', function() {
$('*[unselectable]', this).each(function(i, v) {
var txt = $(v).text();
$(v).text('');
setTimeout(function() { $(v).text(txt) }, 1);
});
});
*/
});
function g_GetExpansionClassName(expansion)
{
switch (expansion)
{
case 0:
return null;
case 1:
return 'icon-bc-right';
case 2:
return 'icon-wotlk-right';
}
return null;
}
function UpdateProgressBar(element_id, new_pct)
{
if (!progress || new_pct < 0 || new_pct > 100)
return;
var progress = $(element_id);
progress.find('b').text(new_pct + '%');
progress.find('img').css('background-position', (-120 + Math.floor(new_pct * 1.2)) + 'px 50%');
}
/* %d chars left warning for inputs. Works automatically if you add data-charwarning="id-of-element-to-put-the-warning-in". */
$(document).ready(function() {
$('input').each(function() {
var maxChars = $(this).attr('maxlength');
var warningTextId = $(this).attr('data-charwarning');
var warningText = warningTextId ? $('#' + warningTextId) : null;
if (!maxChars || !warningText)
return;
hide = function() {
warningText.hide();
};
display = function(length) {
var charsRemaining = maxChars - length;
var pctFilled = length / maxChars;
var colorRed = parseInt((pctFilled >= 0.5) ? 0xFF : (pctFilled * 2 * 0xFF )).toString(16);
var colorGreen = parseInt((pctFilled < 0.5) ? 0xFF : (0xFF - ((pctFilled - 0.5) * 2 * 0xFF))).toString(16);
/* Is there a better way to do this? */
if (colorRed.length == 1)
colorRed = '0' + colorRed;
if (colorGreen.length == 1)
colorGreen = '0' + colorGreen;
warningText.text($WH.sprintf(LANG.charactersremaining_format, charsRemaining));
warningText.show();
warningText.css('color', '#' + colorRed + colorGreen + '00');
};
$(this).focus(function() { display($(this).val().length); })
.blur(function() { hide(); })
.keyup(function() { display($(this).val().length); });
});
});
function GetN5(num)
{
var absNum = Math.abs(num);
if (absNum < 10000) // 1234 = 1,234
return $WH.number_format(num);
if (absNum < 100000) // 12345 = 12.3k
return (Math.round(num / 100) / 10) + 'k';
if (absNum < 1000000) // 123456 = 123k
return Math.round(num / 1000) + 'k';
if (absNum < 10000000) // 1234567 = 1.23m
return (Math.round(num / 1000 / 10) / 100) + 'm';
if (absNum < 100000000) // 12345678 = 12.3m
return (Math.round(num / 1000 / 100) / 10) + 'm';
if (absNum < 1000000000) // 123456789 = 123m
return Math.round(num / 1000 / 1000) + 'm';
if (absNum < 10000000000) // 1234567890 = 1,234,567,890 = 1.23b
return (Math.round(num / 1000 / 1000 / 10) / 100) + 'b';
if (absNum < 10000000000) // 1234567890 = 1,234,567,890 = 1.23b
return (Math.round(num / 1000 / 1000 / 100) / 10) + 'b';
return Math.round(num / 1000 / 1000 / 1000) + 'b';
}
function CreateAjaxLoader()
{
return $('<img>').attr('alt', '').attr('src', g_staticUrl + '/images/icons/ajax.gif').addClass('ajax-loader');
}

View File

@@ -0,0 +1,254 @@
/*
Global utility functions related to arrays, format validation, regular expressions, and strings
*/
function g_createRange(min, max)
{
range = {};
for (var i = min; i <= max; ++i)
range[i] = i;
return range;
}
function g_sortIdArray(arr, reference, prop)
{
arr.sort(
prop ?
function(a, b) { return $WH.strcmp(reference[a][prop], reference[b][prop]) }
:
function(a, b) { return $WH.strcmp(reference[a], reference[b]) }
);
}
function g_sortJsonArray(src, reference, sortFunc, filterFunc)
{
var result = [];
for (var i in src)
{
if (reference[i] && (filterFunc == null || filterFunc(reference[i])))
result.push(i);
}
if (sortFunc != null)
result.sort(sortFunc);
else
g_sortIdArray(result, reference);
return result;
}
function g_urlize(str, allowLocales, profile)
{
var ta = $WH.ce('textarea');
ta.innerHTML = str.replace(/</g,"&lt;").replace(/>/g,"&gt;");
str = ta.value;
str = $WH.str_replace(str, ' / ', '-');
str = $WH.str_replace(str, "'", '');
if (profile)
{
str = $WH.str_replace(str, '(', '');
str = $WH.str_replace(str, ')', '');
var accents = {
"ß": "ss",
"á": "a", "ä": "a", "à": "a", "â": "a",
"è": "e", "ê": "e", "é": "e", "ë": "e",
"í": "i", "î": "i", "ì": "i", "ï": "i",
"ñ": "n",
"ò": "o", "ó": "o", "ö": "o", "ô": "o",
"ú": "u", "ü": "u", "û": "u", "ù": "u",
"œ": "oe",
"Á": "A", "Ä": "A", "À": "A", "Â": "A",
"È": "E", "Ê": "E", "É": "E", "Ë": "E",
"Í": "I", "Î": "I", "Ì": "I", "Ï": "I",
"Ñ": "N",
"Ò": "O", "Ó": "O", "Ö": "O", "Ô": "O",
"Ú": "U", "Ü": "U", "Û": "U", "Ù": "U",
"œ": "Oe"
};
for (var character in accents)
str = str.replace(new RegExp(character, "g"), accents[character]);
}
str = $WH.trim(str);
if (allowLocales)
str = $WH.str_replace(str, ' ', '-');
else
str = str.replace(/[^a-z0-9]/ig, '-');
str = $WH.str_replace(str, '--', '-');
str = $WH.str_replace(str, '--', '-');
str = $WH.rtrim(str, '-');
str = str.replace(/[A-Z]/g, function(x) { return x.toLowerCase() });
return str;
}
function g_isDateValid(date)
{
var match = /^(20[0-2]\d)-([01]\d)-([0-3]\d) ([0-2]\d):([0-5]\d):([0-5]\d)$/.exec(date);
return match;
}
function g_isIpAddress(str)
{
return /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/.test(str);
}
function g_isEmailValid(email)
{
return email.match(/^([a-z0-9._-]+)(\+[a-z0-9._-]+)?(@[a-z0-9.-]+\.[a-z]{2,4})$/i) != null;
}
function g_getCurrentDomain()
{
if (g_getCurrentDomain.CACHE)
return g_getCurrentDomain.CACHE;
var hostname = location.hostname;
if (!g_isIpAddress(hostname))
{
// Only keep the last 2 parts
var parts = hostname.split('.');
if (parts.length > 2)
{
parts.splice(0, parts.length - 2);
}
hostname = parts.join('.');
}
g_getCurrentDomain.CACHE = hostname;
return hostname;
}
function g_isExternalUrl(url)
{
if (!url)
return false;
if (url.indexOf('http') != 0 && url.indexOf('//') != 0)
return false;
else if (url.indexOf(g_getCurrentDomain()) != -1)
return false;
return true;
}
function g_createOrRegex(search, negativeGroup)
{
search = search.replace(/(\(|\)|\|\+|\*|\?|\$|\^)/g, '\\$1');
var parts = search.split(' '),
strRegex = '';
for (var j = 0, len = parts.length; j < len; ++j)
{
if (j > 0)
strRegex += '|';
strRegex += parts[j];
}
// The additional group is necessary so we dont replace %s
return new RegExp((negativeGroup != null ? '(' + negativeGroup + ')?' : '') + '(' + strRegex + ')', 'gi');
}
function g_getHash()
{
return '#' + decodeURIComponent(location.href.split('#')[1] || '');
}
// Lets you add/remove/edit the query parameters in the passed URL
function g_modifyUrl(url, params, opt)
{
if (!opt)
opt = $.noop;
// Preserve existing hash
var hash = '';
if (url.match(/(#.+)$/))
{
hash = RegExp.$1;
url = url.replace(hash, '');
}
$.each(params, function(paramName, newValue)
{
var needle;
var paramPrefix;
var paramValue;
var matches = url.match(new RegExp('(&|\\?)?' + paramName + '=?([^&]+)?'));
if (matches != null)
{
needle = matches[0];
paramPrefix = matches[1];
paramValue = decodeURIComponent(matches[2]);
}
// Remove
if (newValue == null)
{
if (!needle) // If param wasn't there, no need to remove anything
return;
paramValue = null;
}
// Append
else if (newValue.substr(0, 2) == '+=')
{
if (paramValue && opt.onAppendCollision)
{
paramValue = opt.onAppendCollision(paramValue, newValue.substr(2), opt.menuUrl);
}
else if (!paramValue && opt.onAppendEmpty)
{
paramValue = opt.onAppendEmpty(newValue.substr(2), opt.menuUrl);
}
else
{
if (!paramValue)
paramValue = '';
paramValue += $.trim(newValue.substr(2));
}
}
// Set
else
{
paramValue = newValue;
}
// Replace existing param
if (needle)
{
var replacement = '';
if (paramPrefix) // Preserve existing prefix
replacement += paramPrefix;
if (paramValue != null)
{
replacement += paramName;
if (paramValue)
replacement += '=' + $WH.urlencode2(paramValue);
}
url = url.replace(needle, replacement);
}
// Add new param
else if (paramValue || newValue == null || newValue.substr(0,2) != '+=')
{
url += (url.indexOf('?') == -1 ? '?' : '&') + paramName;
if (paramValue)
url += '=' + $WH.urlencode2(paramValue);
}
});
// Polish
url = url.replace('?&', '?');
url = url.replace(/&&/g, '&');
url = url.replace(/\/\?/g, '?');
url = url.replace(/(&|\?)+$/, ''); // Remove trailing & and ? characters
return url + hash;
}

View File

@@ -0,0 +1,539 @@
/*
Global video-related functions
*/
var vi_thumbnails = {
1: 'https://i3.ytimg.com/vi/$1/default.jpg' // YouTube
};
var vi_siteurls = {
1: 'https://www.youtube.com/watch?v=$1' // YouTube
};
var vi_sitevalidation = [
/https?:\/\/(?:www\.)?youtube\.com\/watch\?v=([^& ]{11})/i,
/https?:\/\/(?:www\.)?youtu\.be\/([^& ]{11})/i
];
function vi_submitAVideo()
{
tabsContribute.focus(2);
}
function vi_validateForm(f)
{
if (!f.elements['videourl'].value.length)
{
alert(LANG.message_novideo);
return false;
}
var urlmatch = false;
for (var i in vi_sitevalidation)
{
if (f.elements['videourl'].value.match(vi_sitevalidation[i]))
{
urlmatch = true;
break;
}
}
if (!urlmatch)
{
alert(LANG.message_novideo);
return false;
}
return true;
}
function vi_appendSticky()
{
var _ = $WH.ge('infobox-sticky-vi');
var type = g_pageInfo.type;
var typeId = g_pageInfo.typeId;
var pos = $WH.in_array(lv_videos, 1, function(x) { return x.sticky; });
if (pos != -1)
{
var video = lv_videos[pos];
var a = $WH.ce('a');
a.href = '#videos:id=' + video.id;
a.onclick = function(e) {
VideoViewer.show({ videos: lv_videos, pos: pos });
return $WH.rf2(e);
};
var img = $WH.ce('img');
img.src = $WH.sprintf(vi_thumbnails[video.videoType].replace(/\/default\.jpg/, '/mqdefault.jpg'), video.videoId);
img.className = 'border';
$WH.ae(a, img);
$WH.ae(_, a);
var th = $WH.ge('infobox-videos');
var a = $WH.ce('a');
if (!th)
{
var sections = $('th', _.parentNode);
th = sections[sections.length - (lv_videos && lv_videos.length ? 2 : 1)];
}
$WH.ae(a, $WH.ct(th.textContent + ' (' + lv_videos.length + ')'));
a.href = '#videos'
a.title = $WH.sprintf(LANG.infobox_showall, lv_videos.length);
a.onclick = function() {
tabsRelated.focus(-1);
return false;
};
$WH.ee(th);
$WH.ae(th, a);
}
// aowow - video submission opened for all
else // if (g_user && g_user.roles & (U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_VIDEO))
{
var a;
if (g_user.id > 0)
a = '<a href="javascript:;" onclick="vi_submitAVideo(); return false">';
else
a = '<a href="?account=signin">';
_.innerHTML = $WH.sprintf(LANG.infobox_noneyet, a + LANG.infobox_suggestone + '</a>');
}
// else
// $('#infobox-videos,#infobox-sticky-vi').closest('tr').css('display', 'none');
}
var g_videos = [];
var VideoViewer = new function()
{
var videos,
pos,
imgWidth,
imgHeight,
scale,
oldHash,
mode = 0,
collectionId,
pageTitle, // IE flash embed fix
container,
screen,
imgDiv,
aPrev,
aNext,
aCover,
aOriginal,
divFrom,
divCaption;
function computeDimensions()
{
var video = videos[pos];
var
captionExtraHeight = Math.max(divCaption.offsetHeight - 18, 0),
availHeight = Math.max(50, Math.min(520, $WH.g_getWindowSize().h - 72 - captionExtraHeight)),
scale = Math.min(1, availHeight / 520);
imgWidth = Math.round(scale * 880);
imgHeight = Math.round(scale * 520);
aPrev.style.height = aNext.style.height = aCover.style.height = (imgHeight - 95) + 'px';
Lightbox.setSize(Math.max(480, imgWidth) + 20, imgHeight + 52 + captionExtraHeight);
}
function getPound(pos)
{
var video = videos[pos],
buff = '#videos:';
if (mode == 0)
buff += 'id=' + video.id;
else
buff += collectionId + ':' + (pos + 1);
return buff;
}
function render(resizing)
{
if (resizing && (scale == 1) && $WH.g_getWindowSize().h > container.offsetHeight)
return;
container.style.visibility = 'hidden';
var video = videos[pos];
computeDimensions();
if (!resizing)
{
g_trackEvent('Videos', 'Show', video.id + (video.caption.length ? ' (' + video.caption + ')' : ''));
if (video.videoType == 1)
imgDiv.innerHTML = Markup.toHtml('[youtube=' + video.videoId + ' width=' + imgWidth + ' height=' + imgHeight + ' autoplay=true]', {mode:Markup.MODE_ARTICLE});
// ORIGINAL
aOriginal.href = $WH.sprintf(vi_siteurls[video.videoType], video.videoId);
// FROM
if (!video.user && typeof g_pageInfo == 'object')
video.user = g_pageInfo.username;
var hasFrom1 = (video.date && video.user),
hasFrom2 = (videos.length > 1);
if (hasFrom1)
{
var postedOn = new Date(video.date),
elapsed = (g_serverTime - postedOn) / 1000;
var a = divFrom.firstChild.childNodes[1];
a.href = '?user=' + video.user;
a.innerHTML = video.user;
var s = divFrom.firstChild.childNodes[3];
$WH.ee(s);
g_formatDate(s, elapsed, postedOn);
divFrom.firstChild.style.display = '';
}
else
divFrom.firstChild.style.display = 'none';
var s = divFrom.childNodes[1];
$WH.ee(s);
if (video.user)
{
if (hasFrom1)
$WH.ae(s, $WH.ct(' ' + LANG.dash + ' '));
var a = $WH.ce('a');
a.href = 'javascript:;';
a.onclick = ContactTool.show.bind(ContactTool, { mode: 5, video: video });
a.className = 'icon-report';
g_addTooltip(a, LANG.report_tooltip, 'q2');
$WH.ae(a, $WH.ct(LANG.report));
$WH.ae(s, a);
}
s = divFrom.childNodes[2];
if (hasFrom2)
{
var buff = '';
if (video.user)
buff = LANG.dash;
buff += (pos + 1) + LANG.lvpage_of + videos.length;
s.innerHTML = buff;
s.style.display = '';
}
else
s.style.display = 'none';
divFrom.style.display = (hasFrom1 || hasFrom2 ? '' : 'none');
// CAPTION
var hasCaption = (video.caption != null && video.caption.length);
var hasSubject = (video.subject != null && video.subject.length && video.type && video.typeId);
if (hasCaption || hasSubject)
{
var html = '';
if (hasSubject)
{
html += LANG.types[video.type][0] + LANG.colon;
html += '<a href="?' + g_types[video.type] + '=' + video.typeId + '">';
html += video.subject;
html += '</a>';
}
if (hasCaption)
{
if (hasSubject)
html += LANG.dash;
html += (video.noMarkup ? video.caption : Markup.toHtml(video.caption, { mode: Markup.MODE_SIGNATURE }));
}
divCaption.innerHTML = html;
divCaption.style.display = '';
}
else
divCaption.style.display = 'none';
// URLS
if (videos.length > 1)
{
aPrev.href = getPound(peekPos(-1));
aNext.href = getPound(peekPos( 1));
aPrev.style.display = aNext.style.display = '';
aCover.style.display = 'none';
}
else
{
aPrev.style.display = aNext.style.display = 'none';
aCover.style.display = '';
}
location.replace(getPound(pos));
}
else
$('object, embed', imgDiv).each(function() {
this.width = imgWidth;
this.height = imgHeight
});
Lightbox.reveal();
container.style.visibility = 'visible';
setTimeout(fixTitle, 1);
}
function peekPos(change)
{
var foo = pos;
foo += change;
if (foo < 0)
foo = videos.length - 1;
else if (foo >= videos.length)
foo = 0;
return foo;
}
function prevVideo()
{
pos = peekPos(-1);
render();
return false;
}
function nextVideo()
{
pos = peekPos(1);
render();
return false;
}
function fixTitle()
{
if (pageTitle)
document.title = pageTitle;
}
function onKeyUp(e)
{
e = $WH.$E(e);
switch (e.keyCode)
{
case 37: // Left
prevVideo();
break;
case 39: // Right
nextVideo();
break;
}
}
function onResize()
{
render(1);
}
function onHide()
{
$WH.ee(imgDiv);
if (videos.length > 1)
$WH.dE(document, 'keyup', onKeyUp);
if (oldHash && mode == 0)
{
if (oldHash.indexOf(':id=') != -1)
oldHash = '#videos';
location.replace(oldHash);
}
else
location.replace('#.');
fixTitle();
}
function onShow(dest, first, opt)
{
if (typeof opt.videos == 'string')
{
videos = g_videos[opt.videos];
mode = 1;
collectionId = opt.videos;
}
else
{
videos = opt.videos;
mode = 0;
collectionId = null;
}
container = dest;
pos = 0;
if (opt.pos && opt.pos >= 0 && opt.pos < videos.length)
pos = opt.pos;
if (first)
{
dest.className = 'screenshotviewer';
screen = $WH.ce('div');
screen.className = 'screenshotviewer-screen';
aPrev = $WH.ce('a');
aNext = $WH.ce('a');
aPrev.className = 'screenshotviewer-prev';
aNext.className = 'screenshotviewer-next';
aPrev.href = 'javascript:;';
aNext.href = 'javascript:;';
var foo = $WH.ce('span');
var b = $WH.ce('b');
// $WH.ae(b, $WH.ct(LANG.previous));
$WH.ae(foo, b);
$WH.ae(aPrev, foo);
var foo = $WH.ce('span');
var b = $WH.ce('b');
// $WH.ae(b, $WH.ct(LANG.next));
$WH.ae(foo, b);
$WH.ae(aNext, foo);
aPrev.onclick = prevVideo;
aNext.onclick = nextVideo;
aCover = $WH.ce('a');
aCover.className = 'screenshotviewer-cover';
aCover.href = 'javascript:;';
aCover.onclick = Lightbox.hide;
var foo = $WH.ce('span');
var b = $WH.ce('b');
// $WH.ae(b, $WH.ct(LANG.close));
$WH.ae(foo, b);
$WH.ae(aCover, foo);
$WH.ae(screen, aPrev);
$WH.ae(screen, aNext);
$WH.ae(screen, aCover);
imgDiv = $WH.ce('div');
$WH.ae(screen, imgDiv);
$WH.ae(dest, screen);
var aClose = $WH.ce('a');
// aClose.className = 'dialog-x';
aClose.className = 'screenshotviewer-close';
aClose.href = 'javascript:;';
aClose.onclick = Lightbox.hide;
// $WH.ae(aClose, $WH.ct(LANG.close));
$WH.ae(aClose, $WH.ce('span'));
$WH.ae(dest, aClose);
aOriginal = $WH.ce('a');
// aOriginal.className = 'dialog-arrow';
aOriginal.className = 'screenshotviewer-original';
aOriginal.href = 'javascript:;';
aOriginal.target = '_blank';
// $WH.ae(aOriginal, $WH.ct(LANG.original));
$WH.ae(aOriginal, $WH.ce('span'));
$WH.ae(dest, aOriginal);
divFrom = $WH.ce('div');
divFrom.className = 'screenshotviewer-from';
var sp = $WH.ce('span');
$WH.ae(sp, $WH.ct(LANG.lvscreenshot_from));
$WH.ae(sp, $WH.ce('a'));
$WH.ae(sp, $WH.ct(' '));
$WH.ae(sp, $WH.ce('span'));
$WH.ae(divFrom, sp);
$WH.ae(divFrom, $WH.ce('span'));
$WH.ae(divFrom, $WH.ce('span'));
$WH.ae(dest, divFrom);
divCaption = $WH.ce('div');
divCaption.className = 'screenshotviewer-caption';
$WH.ae(dest, divCaption);
var d = $WH.ce('div');
d.className = 'clear';
$WH.ae(dest, d);
}
oldHash = location.hash;
if (videos.length > 1)
$WH.aE(document, 'keyup', onKeyUp);
render();
}
this.checkPound = function()
{
pageTitle = $('title').html();
if (location.hash && location.hash.indexOf('#videos') == 0)
{
if (!g_listviews['videos']) // Standalone video viewer
{
var parts = location.hash.split(':');
if (parts.length == 3)
{
var collection = g_videos[parts[1]],
p = parseInt(parts[2]);
if (collection && p >= 1 && p <= collection.length)
{
VideoViewer.show({
videos: parts[1],
pos: p - 1
});
}
}
}
}
}
this.show = function(opt)
{
Lightbox.show('videoviewer', {
onShow: onShow,
onHide: onHide,
onResize: onResize
}, opt);
return false;
}
$(document).ready(this.checkPound);
};

View File

@@ -0,0 +1,28 @@
$(document).ready(function()
{
$('form.vote-comment input').click(function() {
var vote = $(this).attr('data-vote');
var block = $(this).parent();
var ajax = block.find('.ajax');
var inputs = block.find('input');
var post = block.attr('data-post');
var type = block.attr('data-type');
inputs.attr('disabled', 'disabled');
ajax.show();
$.post('?vote', { post: post, type: type, vote: vote }, function(data) {
if (data != 'ok')
{
inputs.removeAttr('disabled');
ajax.hide();
alert(LANG.voteerror_tip);
return;
}
block.remove();
});
return false;
});
});

View File

@@ -0,0 +1,417 @@
/*
Global WoW data
*/
var g_file_races = {
1: 'human',
2: 'orc',
3: 'dwarf',
4: 'nightelf',
5: 'scourge',
6: 'tauren',
7: 'gnome',
8: 'troll',
10: 'bloodelf',
11: 'draenei'
};
var g_file_classes = {
1: 'warrior',
2: 'paladin',
3: 'hunter',
4: 'rogue',
5: 'priest',
6: 'deathknight',
7: 'shaman',
8: 'mage',
9: 'warlock',
11: 'druid'
};
var g_file_specs = {
"-1": 'spell_shadow_sacrificialshield',
0: 'spell_nature_elementalabsorption',
6: ['spell_deathknight_bloodpresence', 'spell_deathknight_frostpresence', 'spell_deathknight_unholypresence' ],
11: ['spell_nature_starfall', 'ability_racial_bearform', 'spell_nature_healingtouch' ],
3: ['ability_hunter_beasttaming', 'ability_marksmanship', 'ability_hunter_swiftstrike' ],
8: ['spell_holy_magicalsentry', 'spell_fire_firebolt02', 'spell_frost_frostbolt02' ],
2: ['spell_holy_holybolt', 'spell_holy_devotionaura', 'spell_holy_auraoflight' ],
5: ['spell_holy_wordfortitude', 'spell_holy_holybolt', 'spell_shadow_shadowwordpain' ],
4: ['ability_rogue_eviscerate', 'ability_backstab', 'ability_stealth' ],
7: ['spell_nature_lightning', 'spell_nature_lightningshield', 'spell_nature_magicimmunity' ],
9: ['spell_shadow_deathcoil', 'spell_shadow_metamorphosis', 'spell_shadow_rainoffire' ],
1: ['ability_rogue_eviscerate', 'ability_warrior_innerrage', 'ability_warrior_defensivestance' ]
};
var g_file_genders = {
0: 'male',
1: 'female'
};
var g_file_factions = {
1: 'alliance',
2: 'horde'
};
var g_file_gems = {
1: 'meta',
2: 'red',
4: 'yellow',
6: 'orange',
8: 'blue',
10: 'purple',
12: 'green',
14: 'prismatic'
};
/*
Source:
http://www.wowwiki.com/Patches
http://www.wowwiki.com/Patches/1.x
*/
function g_getPatchVersionIndex(timestamp)
{
var _ = g_getPatchVersion;
var l = 0, u = _.T.length - 2, m;
while (u > l)
{
m = Math.floor((u + l) / 2);
if (timestamp >= _.T[m] && timestamp < _.T[m + 1])
return m;
if (timestamp >= _.T[m])
l = m + 1;
else
u = m - 1;
}
m = Math.ceil((u + l) / 2);
return m;
}
function g_getPatchVersion(timestamp)
{
var m = g_getPatchVersionIndex(timestamp);
return g_getPatchVersion.V[m];
}
g_getPatchVersion.V = [
'1.12.0',
'1.12.1',
'1.12.2',
'2.0.1',
'2.0.3',
'2.0.4',
'2.0.5',
'2.0.6',
'2.0.7',
'2.0.8',
'2.0.10',
'2.0.12',
'2.1.0',
'2.1.1',
'2.1.2',
'2.1.3',
'2.2.0',
'2.2.2',
'2.2.3',
'2.3.0',
'2.3.2',
'2.3.3',
'2.4.0',
'2.4.1',
'2.4.2',
'2.4.3',
'3.0.2',
'3.0.3',
'3.0.8',
'3.0.9',
'3.1.0',
'3.1.1',
'3.1.2',
'3.1.3',
'3.2.0',
'3.2.2',
'3.3.0',
'3.3.2',
'3.3.3',
'3.3.5',
'?????'
];
// javascript:void(prompt('', new Date('Aug 30 2011').getTime()))
g_getPatchVersion.T = [
// 1.12: Drums of War
1153540800000, // 1.12.0 22 August 2006
1159243200000, // 1.12.1 26 September 2006
1160712000000, // 1.12.2 13 October 2006
// 2.0: Before the Storm (The Burning Crusade)
1165294800000, // 2.0.1 5 December 2006
1168318800000, // 2.0.3 9 January 2007
1168578000000, // 2.0.4 12 January 2007
1168750800000, // 2.0.5 14 January 2007
1169528400000, // 2.0.6 23 January 2007
1171342800000, // 2.0.7 13 February 2007
1171602000000, // 2.0.8 16 February 2007
1173157200000, // 2.0.10 6 March 2007
1175572800000, // 2.0.12 3 April 2007
// 2.1: The Black Temple
1179806400000, // 2.1.0 22 May 2007
1181016000000, // 2.1.1 5 June 2007
1182225600000, // 2.1.2 19 June 2007
1184040000000, // 2.1.3 10 July 2007
// 2.2: Voice Chat!
1190692800000, // 2.2.0 25 September 2007
1191297600000, // 2.2.2 2 October 2007
1191902400000, // 2.2.3 9 October 2007
// 2.3: The Gods of Zul'Aman
1194930000000, // 2.3.0 13 November 2007
1199768400000, // 2.3.2 08 January 2008
1200978000000, // 2.3.3 22 January 2008
// 2.4: Fury of the Sunwell
1206417600000, // 2.4.0 25 March 2008
1207022400000, // 2.4.1 1 April 2008
1210651200000, // 2.4.2 13 May 2008
1216094400000, // 2.4.3 15 July 2008
// 3.0: Echoes of Doom
1223956800000, // 3.0.2 October 14 2008
1225774800000, // 3.0.3 November 4 2008
1232427600000, // 3.0.8 January 20 2009
1234242000000, // 3.0.9 February 10 2009
// 3.1: Secrets of Ulduar
1239681600000, // 3.1.0 April 14 2009
1240286400000, // 3.1.1 April 21 2009
1242705600000, // 3.1.2 19 May 2009
1243915200000, // 3.1.3 2 June 2009
// 3.2: Call of the Crusader
1249358400000, // 3.2.0 4 August 2009
1253595600000, // 3.2.2 22 September 2009
// 3.3: Fall of the Lich King
1260266400000, // 3.3.0 8 December 2009
1265104800000, // 3.3.2 2 February 2010
1269320400000, // 3.3.3 23 March 2010
1277182800000, // 3.3.5 22 June 2010
9999999999999
];
/*
Global stuff related to WoW database entries
*/
var
g_npcs = {},
g_objects = {},
g_items = {},
g_itemsets = {},
g_quests = {},
g_spells = {},
g_gatheredzones = {},
g_factions = {},
g_pets = {},
g_achievements = {},
g_titles = {},
g_holidays = {},
g_classes = {},
g_races = {},
g_skills = {},
g_gatheredcurrencies = {},
g_sounds = {},
g_icons = {},
g_enchantments = {},
g_emotes = {};
var g_types = {
1: 'npc',
2: 'object',
3: 'item',
4: 'itemset',
5: 'quest',
6: 'spell',
7: 'zone',
8: 'faction',
9: 'pet',
10: 'achievement',
11: 'title',
12: 'event',
13: 'class',
14: 'race',
15: 'skill',
17: 'currency',
19: 'sound',
29: 'icon',
300: 'guide',
501: 'emote',
502: 'enchantment',
503: 'areatrigger',
504: 'mail'
};
// Items
$WH.cO(g_items, {
add: function(id, json)
{
if (g_items[id] != null)
$WH.cO(g_items[id], json);
else
g_items[id] = json;
},
getIcon: function(id)
{
if (g_items[id] != null && g_items[id].icon)
return g_items[id].icon;
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_items.getIcon(id), size, null, '?item=' + id, num, qty);
}
});
// Spells
$WH.cO(g_spells, {
add: function(id, json)
{
if (g_spells[id] != null)
$WH.cO(g_spells[id], json);
else
g_spells[id] = json;
},
getIcon: function(id)
{
if (g_spells[id] != null && g_spells[id].icon)
return g_spells[id].icon;
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_spells.getIcon(id), size, null, '?spell=' + id, num, qty);
}
});
// Achievements
$WH.cO(g_achievements, {
getIcon: function(id)
{
if (g_achievements[id] != null && g_achievements[id].icon)
return g_achievements[id].icon;
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_achievements.getIcon(id), size, null, '?achievement=' + id, num, qty);
}
});
// Classes
$WH.cO(g_classes, {
getIcon: function(id)
{
if (g_file_classes[id])
return 'class_' + g_file_classes[id];
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_classes.getIcon(id), size, null, '?class=' + id, num, qty);
}
});
// Races
$WH.cO(g_races, {
getIcon: function(id, gender)
{
if (gender === undefined)
gender = 0
if (g_file_races[id] && g_file_genders[gender])
return 'race_' + g_file_races[id] + '_' + g_file_genders[gender];
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_races.getIcon(id), size, null, '?race=' + id, num, qty);
}
});
// Skills
$WH.cO(g_skills, {
getIcon: function(id)
{
if (g_skills[id] != null && g_skills[id].icon)
return g_skills[id].icon;
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_skills.getIcon(id), size, null, '?skill=' + id, num, qty);
}
});
// Currencies
$WH.cO(g_gatheredcurrencies, {
getIcon: function(id, side)
{
if (g_gatheredcurrencies[id] != null && g_gatheredcurrencies[id].icon)
{
if ($WH.is_array(g_gatheredcurrencies[id].icon) && !isNaN(side))
return g_gatheredcurrencies[id].icon[side];
return g_gatheredcurrencies[id].icon;
}
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_gatheredcurrencies.getIcon(id, (num > 0 ? 0 : 1)), size, null, null, Math.abs(num), qty);
}
});
// Holidays
$WH.cO(g_holidays, {
getIcon: function(id)
{
if (g_holidays[id] != null && g_holidays[id].icon)
return g_holidays[id].icon;
else
return 'inv_misc_questionmark';
},
createIcon: function(id, size, num, qty)
{
return Icon.create(g_holidays.getIcon(id), size, null, '?event=' + id, num, qty);
}
});
// TODO: Move to g_items
function g_getIngameLink(color, id, name)
{
//prompt(LANG.prompt_ingamelink, '/script DEFAULT_CHAT_FRAME:AddMessage("\\124c' + color + '\\124H' + id + '\\124h[' + name + ']\\124h\\124r");');
return '/script DEFAULT_CHAT_FRAME:AddMessage("\\124c' + color + '\\124H' + id + '\\124h[' + name + ']\\124h\\124r");';
}

View File

@@ -0,0 +1,4 @@
/*
* Wowhead Site Achievements (WSA)
* just a note; they'd need to go here if i cared
*/

View File

@@ -89,20 +89,36 @@ trait TrTemplateFile
return;
}
$content = file_get_contents($file);
if (!$content)
{
CLI::write('[build] template file is not readable - '.CLI::bold($file), CLI::LOG_ERROR);
$this->success = false;
return;
}
$result = '';
// replace constants
$content = Cfg::applyToString($content);
if (is_dir($file))
{
$i = 0;
foreach (glob($file.'/[A-Za-z0-9-_]*.*') as $f)
{
$i++;
if (($content = $this->applyCfg($f)) === null)
return;
yield $content;
if (CLISetup::writeFile($this->fileTemplateDest[$idx], $content))
$result .= $content . "\n";
}
if (!$i)
CLI::write('[build] template dir is empty - '.CLI::bold($file), CLI::LOG_WARN);
}
else /* if (is_file($file)) */
{
if (($content = $this->applyCfg($file)) === null)
return;
yield $content;
$result .= $content . "\n";
}
if (CLISetup::writeFile($this->fileTemplateDest[$idx], $result))
continue;
$this->success = false;
@@ -134,6 +150,17 @@ trait TrTemplateFile
}
}
}
private function applyCfg($file) : ?string
{
// replace constants
if ($content = file_get_contents($file))
return Cfg::applyToString($content, $this->numFmt ?? true);
CLI::write('[build] template file is not readable - '.CLI::bold($file), CLI::LOG_ERROR);
$this->success = false;
return null;
}
}
trait TrImageProcessor

View File

@@ -0,0 +1 @@
UPDATE `aowow_dbversion` SET `build` = CONCAT(IFNULL(`build`, ''), ' globaljs');

View File

@@ -1,20 +1,25 @@
var Draggable = new function () {
var Draggable = new function()
{
var
start = {},
mouse = {},
clickObj,
dragObj;
function onMouseDown(e) {
function onMouseDown(e)
{
e = $WH.$E(e);
if (this._handle) {
if (this._handle)
{
var _ = e._target,
found = false,
i = 0;
while (_ && i <= 3) {
if (_ == this._handle) {
while (_ && i <= 3)
{
if (_ == this._handle)
{
found = true;
break;
}
@@ -23,10 +28,9 @@ var Draggable = new function () {
++i;
}
if (!found) {
if (!found)
return false;
}
}
clickObj = this;
@@ -35,28 +39,29 @@ var Draggable = new function () {
$WH.aE(document, 'mousemove', onMouseMove);
$WH.aE(document, 'mouseup', onMouseUp);
if (clickObj.onClick) {
if (clickObj.onClick)
clickObj.onClick(e, clickObj);
}
return false;
}
function onMouseMove(e) {
function onMouseMove(e)
{
e = $WH.$E(e);
var pos = $WH.g_getCursorPos(e);
if (clickObj) {
if (Math.abs(pos.x - start.x) > 5 || Math.abs(pos.y - start.y) > 5) {
if (clickObj)
{
if (Math.abs(pos.x - start.x) > 5 || Math.abs(pos.y - start.y) > 5)
{
onDragStart(e, clickObj);
clickObj = null;
}
}
if (!dragObj || !dragObj._bounds) {
if (!dragObj || !dragObj._bounds)
return false;
}
var
bounds = getBounds(dragObj),
@@ -71,26 +76,27 @@ var Draggable = new function () {
return false;
}
function onMouseUp(e) {
function onMouseUp(e)
{
e = $WH.$E(e);
clickObj = null;
if (dragObj) {
if (dragObj)
onDragEnd(e);
}
}
function onDragStart(e, obj) {
if (dragObj) {
function onDragStart(e, obj)
{
if (dragObj)
onDragEnd(e);
}
var foo = $WH.ac(obj);
mouse.x = foo[0];
mouse.y = foo[1];
if (obj._targets.length) {
if (obj._targets.length)
{
dragObj = obj.cloneNode(true);
dragObj._orig = obj;
@@ -98,27 +104,26 @@ var Draggable = new function () {
// $WH.ae(document.body, dragObj); // 5.0.. why does it do that?
setPosition(-2323, -2323);
}
else {
else
dragObj = obj;
}
$WH.Tooltip.disabled = true;
$WH.Tooltip.hide();
if (obj.onDrag) {
if (obj.onDrag)
obj.onDrag(e, dragObj, obj);
}
dragObj._bounds = getBounds(obj._container);
dragObj.className += ' dragged';
}
function onDragEnd(e) {
var
found = false,
function onDragEnd(e)
{
var found = false,
cursor = $WH.g_getCursorPos(e);
if (dragObj._orig && dragObj._orig._targets.length) {
if (dragObj._orig && dragObj._orig._targets.length)
{
clearPosition();
var pos = {
@@ -131,25 +136,24 @@ var Draggable = new function () {
$WH.de(dragObj);
dragObj = dragObj._orig;
for (var i = 0, len = dragObj._targets.length; i < len; ++i) {
for (var i = 0, len = dragObj._targets.length; i < len; ++i)
{
var targObj = dragObj._targets[i],
bounds = getBounds(targObj);
if (pos.x2 >= bounds.x1 && pos.x1 < bounds.x2 && pos.y2 >= bounds.y1 && pos.y1 < bounds.y2) {
if (pos.x2 >= bounds.x1 && pos.x1 < bounds.x2 && pos.y2 >= bounds.y1 && pos.y1 < bounds.y2)
{
found = true;
if (dragObj.onDrop) {
if (dragObj.onDrop)
dragObj.onDrop(e, dragObj, targObj, (cursor.x >= bounds.x1 && cursor.x <= bounds.x2 && cursor.y >= bounds.y1 && cursor.y <= bounds.y2));
}
else {
else
$WH.ae(targObj, dragObj);
}
}
}
}
if (!found && dragObj.onDrop) {
if (!found && dragObj.onDrop)
dragObj.onDrop(e, dragObj, null);
}
$WH.dE(document, 'mousemove', onMouseMove);
$WH.dE(document, 'mouseup', onMouseUp);
@@ -160,7 +164,8 @@ var Draggable = new function () {
dragObj = null;
}
function setPosition(dX, dY) {
function setPosition(dX, dY)
{
dragObj.style.position = 'absolute';
dragObj.style.left = mouse.x + dX + 'px';
dragObj.style.top = mouse.y + dY + 'px';
@@ -169,12 +174,14 @@ var Draggable = new function () {
dragObj._y = mouse.y + dY;
}
function clearPosition() {
function clearPosition()
{
dragObj.style.left = '-2323px';
dragObj.style.top = '-2323px';
}
function getBounds(obj) {
function getBounds(obj)
{
var pos = $WH.ac(obj);
return {
@@ -185,45 +192,40 @@ var Draggable = new function () {
};
}
this.init = function (obj, opt) {
this.init = function (obj, opt)
{
obj.onmousedown = onMouseDown;
var a = obj.getElementsByTagName('a');
for (var i = 0, len = a.length; i < len; ++i) {
for (var i = 0, len = a.length; i < len; ++i)
$WH.ns(a[i]);
}
if (!obj._targets) {
if (!obj._targets)
obj._targets = [];
}
if (!obj._container) {
if (!obj._container)
obj._container = document.body;
}
if (opt != null) {
if (opt.targets) {
for (var i = 0, len = opt.targets.length; i < len; ++i) {
if (opt != null)
{
if (opt.targets)
{
for (var i = 0, len = opt.targets.length; i < len; ++i)
obj._targets.push($WH.ge(opt.targets[i]));
}
}
if (opt.container) {
if (opt.container)
obj._container = $WH.ge(opt.container);
}
// Functions
if (opt.onClick) {
if (opt.onClick)
obj.onClick = opt.onClick;
}
if (opt.onDrop) {
if (opt.onDrop)
obj.onDrop = opt.onDrop;
}
if (opt.onDrag) {
if (opt.onDrag)
obj.onDrag = opt.onDrag;
}
}
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -263,22 +263,24 @@ function vim_UpdateList(k) {
var td = $WH.ce('td');
td.align = 'center';
// if (video.status != 999 && !video.pending) { // Aowow - removed
var a = $WH.ce('a');
a.href = $WH.sprintf(vi_siteurls[video.videoType], video.videoId);
a.target = '_blank';
a.onclick = function (id, e) {
$WH.sp(e);
(vim_View.bind(null, this, id))();
return false;
}.bind(tr, video.id);
var previewImg = $WH.ce('img');
previewImg.src = $WH.sprintf(vi_thumbnails[video.videoType], video.videoId);
previewImg.height = 50;
$WH.ae(a, previewImg);
$WH.ae(td, a);
// }
/* aowow - removed
* if (video.status != 999 && !video.pending) {
* var a = $WH.ce('a');
* a.href = $WH.sprintf(vi_siteurls[video.videoType], video.videoId);
* a.target = '_blank';
* a.onclick = function (id, e) {
* $WH.sp(e);
* (vim_View.bind(null, this, id))();
* return false;
* }.bind(tr, video.id);
*
* var previewImg = $WH.ce('img');
* previewImg.src = $WH.sprintf(vi_thumbnails[video.videoType], video.videoId);
* previewImg.height = 50;
* $WH.ae(a, previewImg);
* $WH.ae(td, a);
* }
*/
$WH.ae(tr, td);
td = $WH.ce('td');
@@ -787,7 +789,7 @@ function () {
computeDimensions(0);
// Aowow - /uploads/videos/ not seen on server
// aowow - /uploads/videos/ not seen on server
// var url = g_staticUrl + '/uploads/videos/' + (video.pending ? 'pending' : 'normal') + '/' + video.id + '.jpg';
var url = video.url;
@@ -797,7 +799,7 @@ function () {
prevImgDiv.innerHTML = html;
if (!resizing) {
// Aowow - /uploads/videos/ not seen on server
// aowow - /uploads/videos/ not seen on server
// aOriginal.href = g_staticUrl + '/uploads/videos/' + (video.pending ? 'pending' : 'normal') + '/' + video.id + '.jpg';
aOriginal.href = $WH.sprintf(vi_siteurls[video.videoType], video.videoId);;
var hasFrom = video.date && video.user;