var BUILD_DATE = "20080905092037"; var utils; function load(){ var isSupported = utils.isSupportedBrowser(); if (!isSupported) { var messageDiv = document.getElementById("incompatibleBrowserMessage"); var msg = 'For optimal Wetpaint performance we recommend the latest versions of Internet Explorer or Firefox. For Mac users, we recommend Firefox instead of Safari.'; messageDiv.innerHTML = msg; messageDiv.style.display = 'block'; } } window.baseInit = window.init; if( window.baseInit == null ) window.baseInit = function(){} init = function( fcn ){ if( ! window.initFunctions ) window.initFunctions = new Array(); if( typeof(fcn) == "string") window.initFunctions[ window.initFunctions.length ] = fcn; else{ baseInit(); for( var i=0; i 0) ? document.documentElement.scrollLeft : document.getElementById("allcontent").scrollLeft; pos.top = (window.scrollY) ? window.scrollY : (document.documentElement.scrollTop > 0) ? document.documentElement.scrollTop : document.getElementById("allcontent").scrollTop; return pos; } /** * Returns an object with two parameters indicating the window dimensions in pixels. * Note that this method fakes an understanding of a vertical scrollbar (presumes 18px). * @return Object with x and y coordinates of window dimensions. * @type Object */ utils.getWindowDimensions = function() { var dim = {x:null,y:null}; if (self.innerHeight){ // all except Explorer dim.x = self.innerWidth - 18; dim.y = self.innerHeight; } else if (document.documentElement && document.documentElement.clientHeight){ // Explorer 7 and 6 Strict Mode if (this.isMSIE7) { dim.x = document.documentElement.clientWidth; }else{ dim.x = document.documentElement.clientWidth - 18; } dim.y = document.documentElement.clientHeight; } else if (document.body){ // other Explorers dim.x = document.body.clientWidth - 18; dim.y = document.body.clientHeight; } return dim; }; /** * Returns a node referencing the first element in the ancestry matching the starting node. * Will find instances of specific class names within space-seperated className list. * @param {node} node Starting DOM element node. * @param {String} names List of node names to be matched, comma separated. * @param {String} attrib_name (optional) Name of attribute required in matching node. * @param {String} attrib_name (optional) If attrib_name is specified, value of attribute required in matching node. * @param {node} stop_node (optional) Node that, if encountered, we stop looking for additional nodes. * @return Element referencing parent node. * @type Element */ utils.getParentElement = function(node, names, attrib_name, attrib_value, stop_node) { if (this.isMSIE && attrib_name == 'class') attrib_name = 'className'; if (node == null) return null; //return null, as no node is defined. if (typeof(names) == "undefined" || names == null) { if (node.nodeType == 1) return node; while ((node = node.parentNode) != null && node.nodeType != 1) ; // Find parent node that is a element return node; //return any node, as names is not defined. } var namesAr = names.split(','); do { for (var i=0; i'; if (testStartElement == testEndElement) return testStartElement; } while (testEndElement = testEndElement.parentNode); testEndElement = endElement; } while (testStartElement = testStartElement.parentNode); } } else { if (range.item) return range.item(0); if (range.parentElement().tagName.toLowerCase() == 'tbody') return range.parentElement().offsetParent; return range.parentElement(); } } //no common container found. return null; }; /** * This method replaces range.compareNode(), which was deprecated in Gecko 1.9 (i.e: Firefox 3). * * @param range The range for the comparison. * @param node The node to compare. * * @return one of the following constant integer values: * */ utils.rangeCompareNode = function( range, node ) { if( range.compareNode ) return range.compareNode(node); if( !node ) return 3; var nodeRange = node.ownerDocument.createRange(); try { nodeRange.selectNode(node); } catch(e) { nodeRange.selectNodeContents(node); } var nodeIsBefore = range.compareBoundaryPoints( Range.START_TO_START, nodeRange ) == 1; var nodeIsAfter = range.compareBoundaryPoints( Range.END_TO_END, nodeRange ) == -1; if( nodeIsBefore && !nodeIsAfter ) return 0; // Range.NODE_BEFORE if( !nodeIsBefore && nodeIsAfter ) return 1; // Range.NODE_AFTER if( nodeIsBefore && nodeIsAfter ) return 2; // Range.NODE_BEFORE_AND_AFTER return 3; // Range.NODE_INSIDE }; /** * Returns a reference to a document tree node that contains the start point of a Range or TextRange. * This method ignores empty Text elements at the start of the selection and accounts for selected images. * @param {Range} range A W3C DOM Range object, or an IE TextRange object. * @return Element referencing node containing the start of the range. * @type Element */ utils.getStartContainer = function(range) { if (range) { if (range.cloneContents) { //Trim leading empty text node if exists. var docFragment = range.cloneContents(); if (docFragment.childNodes.length > 1 && docFragment.childNodes[0].nodeType == 3 && docFragment.childNodes[0].length == 0) { return this.getTextElement(range.startContainer.nextSibling); } else if (docFragment.childNodes.length == 1 && docFragment.childNodes[0].nodeName.toLowerCase() == 'img') { var fragSrc = utils.regexpReplace(docFragment.childNodes[0].src,'^http://(.*?)/','','i') var imageMatches = this.getElementsByAttributeValue(range.startContainer,'img','src',fragSrc) for (var i=0;i 1 && docFragment.childNodes[docFragment.childNodes.length-1].nodeType == 3 && docFragment.childNodes[docFragment.childNodes.length-1].length == 0) { return this.getTextElement(range.endContainer.previousSibling); } else if (docFragment.childNodes.length == 1 && docFragment.childNodes[docFragment.childNodes.length-1].nodeName.toLowerCase() == 'img') { var fragSrc = utils.regexpReplace(docFragment.childNodes[docFragment.childNodes.length-1].src,'^http://(.*?)/','','i') var imageMatches = this.getElementsByAttributeValue(range.endContainer,'img','src',fragSrc) for (var i=0;i=0){ if(warnHTML){ messageNode.innerHTML = messageNode.innerHTML = warnHTML.replace('[REMCHARS]',remaining); } else{ messageNode.innerHTML = "Note: You can enter up to "+remaining+" additional characters."; } return true; }else{ if(limitHTML){ messageNode.innerHTML = limitHTML.replace('[CURCHARS]',currLength).replace('[MAXCHARS]', maxchars); } else { messageNode.innerHTML = "You have entered "+currLength+" characters. The limit is "+maxchars+"."; } return false; } } /** * A class to parse color values * @author Stoyan Stefanov * @link http://www.phpied.com/rgb-color-parser-in-javascript/ * @license Use it if you like it */ function RGBColor(color_string){ this.ok = false; // strip any leading # if (color_string.charAt(0) == '#') { // remove # if any color_string = color_string.substr(1,6); } color_string = color_string.replace(/ /g,''); color_string = color_string.toLowerCase(); // array of color definition objects var color_defs = [ { re: new RegExp("^rgb\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3})\\)$"), example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], process: function (bits){ return [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ]; } }, { re: new RegExp("^(\\w{2})(\\w{2})(\\w{2})$"), example: ['#00ff00', '336699'], process: function (bits){ return [ parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16) ]; } }, { re: new RegExp("^(\\w{1})(\\w{1})(\\w{1})$"), example: ['#fb0', 'f0f'], process: function (bits){ return [ parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16) ]; } } ]; // search through the definitions to find a match for (var i = 0; i < color_defs.length; i++) { var re = color_defs[i].re; var processor = color_defs[i].process; var bits = re.exec(color_string); if (bits) { channels = processor(bits); this.r = channels[0]; this.g = channels[1]; this.b = channels[2]; this.ok = true; } } // validate/cleanup values this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); // some getters this.toRGB = function () { return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; } this.toHex = function () { var r = this.r.toString(16); var g = this.g.toString(16); var b = this.b.toString(16); if (r.length == 1) r = '0' + r; if (g.length == 1) g = '0' + g; if (b.length == 1) b = '0' + b; return '#' + r + g + b; } this.colorDistance = function (r2, g2, b2) { var a = r2 - this.r; var b = g2 - this.g; var c = b2 - this.b; return Math.sqrt (a*a + b*b + c*c); } this.dToWhite = this.colorDistance(255, 255, 255); this.dToBlack = this.colorDistance(0 ,0 ,0); this.isDark = function() { return this.dToBlack < this.dToWhite; } this.blackOrWhiteOrGray = function(){ // try to return Gray unless current color is near gray // if so, return black or white, whichever is farther from current dToGray = this.colorDistance(151, 151, 151); if((dToGray - this.dToBlack) > (dToGray - this.dToWhite) ){ return (dToGray > this.dToBlack) ? 'Gray' : 'White' ; } else { return (dToGray > this.dToWhite) ? 'Gray' : 'Black' ; } } } function HSVColor(initial_color_string){ this.ok = false; // array of color definition objects this.color_defs = [ { re: new RegExp("^hsv\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3})\\)$"), example: ['hsv(360, 100, 100)', 'hsv(243,67,60)'], process: function (bits){ return [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ]; } }, { re: new RegExp("^(\\w{2})(\\w{2})(\\w{2})$"), example: ['#00ff00', '336699'], process: function (bits){ //HSV calculation var hsvR = Math.round(parseInt(bits[1],16)/.255)/1000; var hsvG = Math.round(parseInt(bits[2],16)/.255)/1000; var hsvB = Math.round(parseInt(bits[3],16)/.255)/1000; var max = Math.max(Math.max(hsvR, hsvG), hsvB); var min = Math.min(Math.min(hsvR, hsvG), hsvB); var hue = 0; var saturation = 0; var brightness = Math.round(max*100)/100; var delta = Math.round((max - min)*1000)/1000; if (max != 0) { saturation = Math.round((delta / max)*100)/100; } else { saturation = 0; hue = -1; } if (hsvR == max) { hue = (Math.round((hsvG - hsvB)*100)/100) / delta; } else if(hsvG == max) { hue = 2 + (Math.round((hsvB - hsvR)*100)/100) / delta; } else { hue = 4 + (Math.round((hsvR - hsvG)*100)/100) / delta; } hue *= 60; if (hue < 0) hue += 360; //window.status = bits[1] + '-' + bits[2] + '-' + bits[3] + ' ... ' + hsvR + '-' + hsvG + '-' + hsvB + ' ... ' + max + '-' + min + '-' + delta + ' ... ' + Math.round(hue) + '-' + parseInt(saturation*100) + '-' + parseInt(brightness*100) return [ Math.round(hue), parseInt(saturation*100), parseInt(brightness*100) ]; } } ]; //setter this.setValues = function (color_string) { // strip any leading # if (color_string.charAt(0) == '#') { // remove # if any color_string = color_string.substr(1,6); } color_string = color_string.replace(/ /g,''); color_string = color_string.toLowerCase(); // search through the definitions to find a match for (var i = 0; i < this.color_defs.length; i++) { var re = this.color_defs[i].re; var processor = this.color_defs[i].process; var bits = re.exec(color_string); if (bits) { channels = processor(bits); this.hue = channels[0]; this.saturation = channels[1]; this.brightness = channels[2]; this.ok = true; } } // validate/cleanup values this.hue = (this.hue < 0 || isNaN(this.hue)) ? 0 : ((this.hue > 360) ? 360 : this.hue); this.saturation = (this.saturation < 0 || isNaN(this.saturation)) ? 0 : ((this.saturation > 100) ? 100 : this.saturation); this.brightness = (this.brightness < 0 || isNaN(this.brightness)) ? 0 : ((this.brightness > 100) ? 100 : this.brightness); } // some getters this.toHex = function () { var red; var green; var blue; var hue = this.hue; var saturation = this.saturation/100; var brightness = this.brightness/100; var i, f, p, q, t; if (saturation == 0) { red = green = blue = brightness; } hue /= 60; // sector 0 to 5 i = Math.floor( hue ); f = hue - i; p = brightness * ( 1 - saturation ); q = brightness * ( 1 - saturation * f ); t = brightness * ( 1 - saturation * ( 1 - f ) ); switch( i ) { case 0: red = brightness; green = t; blue = p; break; case 1: red = q; green = brightness; blue = p; break; case 2: red = p; green = brightness; blue = t; break; case 3: red = p; green = q; blue = brightness; break; case 4: red = t; green = p; blue = brightness; break; default: red = brightness; green = p; blue = q; break; } //window.status = this.hue + ' ... ' + hue + '-' + saturation + '-' + brightness + ' ... ' + Math.round(red*255) + '-' + Math.round(green*255) + '-' + Math.round(blue*255) + ' ... ' + i + '-' + f + '-' + p + '-' + q + '-' + t; red = Math.round(red*255).toString(16); green = Math.round(green*255).toString(16); blue = Math.round(blue*255).toString(16); if (red.length == 1) red = '0' + red; if (green.length == 1) green = '0' + green; if (blue.length == 1) blue = '0' + blue; return '#' + red + green + blue; } this.toHSV = function () { return 'hsv(' + this.hue + ', ' + this.saturation + ', ' + this.brightness + ')'; } //load from initialization. if (initial_color_string) this.setValues(initial_color_string); return this; } utils.toggleMinMax = function(who, which){ if(typeof(who) == 'object'){ if(who.className.substring(0,6) == "toggle"){ switch(which){ case "min": who.className = "toggleMin"; break; case "max": who.className = "toggleMax"; break; default: who.className = (who.className == "toggleMin")? "toggleMax" : "toggleMin"; } }else{ this.toggleMinMax(who.offsetParent, which); } }else{ // throw error } } utils.getSortUri = function(sort) { var params = location.search.getObjectFromQuerystring(); var sortParam = "sort=" + sort; var uri = location.href; if (params["sort"]) { uri = location.href.replace(new RegExp("\\bsort=[^\\&]*\\b"), sortParam); } else { uri += (location.search.length > 0) ? "&" + sortParam : "?" + sortParam; } var offsetRE = new RegExp("\\boffset=[^\\&]*\\b"); if (offsetRE.test(uri)) uri = uri.replace(offsetRE, "offset=0"); return uri; } /** * Tracking * omniture */ utils.logMacroEvent = function( eventName, eventCode ){ if(typeof(s_gi)!='undefined'){ try{ s_w=s_gi(s_account); s_w.pageName= s_w.prop1 + ' - UIEvents - ' + eventName; s_w.prop7=eventName; //ui event name s_w.eVar8=eventName; //ui action s_w.events=''; if(eventCode){s_w_addEvent(eventCode);} s_w_addEvent('event8'); s_w_addEvent('event1'); s_w.t(); //increments page views } catch(s_w){ return; } } } utils.logMicroEvent = function( eventName, eventCode ){ if(typeof(s_gi)!='undefined'){ try{ s_w=s_gi(s_account); if(eventName.indexOf('error')!=-1){s_w.pageType='errorPage';} s_w.pageName= s_w.prop1 + ' - UIEvents - ' + eventName; s_w.prop7=eventName; //ui event name s_w.eVar8=eventName; //ui action s_w.events=''; if(eventCode){s_w_addEvent(eventCode);} s_w_addEvent('event8'); s_w.tl(); //doesn't increment page views } catch(s_w){ return; } } } /** * Generic */ function $() { var results = [], element; for (var i = 0; i < arguments.length; i++) { element = arguments[i]; if (typeof element == 'string' && element!='') element = document.getElementById(element); results.push( ( (typeof(Element)!='undefined') && Element && Element.extend) ? Element.extend(element) : element ); } return results.length < 2 ? results[0] : results; } function isFunction(a) { return typeof a == 'function'; } // Breaks javascript event to dom references in IE - preventing memory leaks // Use whenever removing an item from the dom or setting innerHTML function purge(d) { var a = d.attributes, i, l, n; if (a) { l = a.length; for (i = 0; i < l; i += 1) { n = a[i].name; if (typeof d[n] === 'function') { d[n] = null; } } } a = d.childNodes; if (a) { l = a.length; for (i = 0; i < l; i += 1) { purge(d.childNodes[i]); } } } /** * Dates */ //Load the dates returned from the XML server into a JS Date object, using ISO8601 date formatting standard. var DEFAULT_TIME_ZONE = -4; var DEFAULT_TIME_STRING = 'EDT'; Date.prototype.setISO8601 = function(string) { var expression = new RegExp( "(\\d{4})-(\\d{1,2})-(\\d{1,2})T(\\d{1,2}):(\\d{1,2}):(\\d{1,2})(-|\\+)(\\d{1,2}):(\\d{1,2})" ); var standard = string.replace( expression, "$2/$3/$1 $4:$5:$6 GMT$7$8$9" ); var date = new Date( standard ); this.setTime( date.getTime() ); }; //Return the millisecond format of the date as of midnight this morning. Date.prototype.getMidnightTime = function() { return this.getTime() - (this.getHours() * 3600000) - (this.getMinutes() * 60000) - (this.getSeconds() * 1000) - this.getMilliseconds(); }; Date.prototype.getWikiTime = function(noTimeZone) { var adjustForTimezoneOffset = function(date) { return new Date( date.getTime() + ( 1000 * 60 * ( date.getTimezoneOffset() - ( DEFAULT_TIME_ZONE * -60 ) ) ) ); }; var z = function(x) { return (0<=x&&x<=9?'0':'')+x; }; var adjusted = adjustForTimezoneOffset(this); var now = adjustForTimezoneOffset(new Date()); var arrDaysOfWeek = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; var arrMonths = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; var formattedDate = arrMonths[adjusted.getMonth()] + " " + adjusted.getDate() + " " + adjusted.getFullYear(); if( adjusted.getTime() > now.getMidnightTime() ) formattedDate = "Today"; else if( adjusted.getTime() > now.getMidnightTime() - 86000000 ) formattedDate = "Yesterday"; else if( adjusted.getTime() > now.getMidnightTime() - ( 86000000 * 7 ) ) formattedDate = arrDaysOfWeek[adjusted.getDay()]; formattedDate += ", "; formattedDate += adjusted.getHours() <= 12 ? adjusted.getHours() == 0 ? 12 : adjusted.getHours() : adjusted.getHours() - 12; formattedDate += ":" + z( adjusted.getMinutes() ) + ' ' + ( adjusted.getHours() < 12 ? "am" : "pm" ); return formattedDate + ( !noTimeZone ? " " + DEFAULT_TIME_STRING : "" ); }; Date.prototype.getStaticTime = function(noTimeZone) { var arrMonths = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"); var formattedDate = arrMonths[this.getMonth()] + " " + this.getDate() + " " + this.getFullYear(); formattedDate += ", "; formattedDate += (this.getHours() <= 12) ? (this.getHours() == 0) ? '12' : this.getHours() : (this.getHours() - 12); formattedDate += ":"; formattedDate += (this.getMinutes() < 10) ? "0" + this.getMinutes() : this.getMinutes(); formattedDate += (this.getHours() < 12) ? " am" : " pm"; var timeZone = (noTimeZone) ? '' : DEFAULT_TIME_STRING; return formattedDate + " " + timeZone; }; /** * Strings */ String.prototype.newlinesToHTML = function() { // remove \rs that IE SO helpfully adds var cleanedText = this.replace(/\r/gi, ""); return cleanedText.replace(/\n/gi, "
"); } String.prototype.newlinesToUnicode = function() { return this.replace(//gi, "\n"); } String.prototype.capitalize = function() { var charRE = /^[a-z]/; if (!charRE.test(this)) return this; // older versions of safari do not support passing a function to String.replace try { return this.replace(charRE, function(c) { return c.toUpperCase(); }); } catch (e) { var capChar = charRE.exec(this)[0].toUpperCase(); return this.replace(charRE, capChar); } } String.prototype.trim = function(in_str) { in_str = this != window ? this : in_str; return in_str.replace(/^\s+/g, '').replace(/\s+$/g, ''); }; String.prototype.encodeCDATA = function() { return this.replace(/]]>/g, "]]&gt;"); }; String.prototype.encodeHTML = function() { return this.replace(/&/g, "&").replace(//g, ">").replace(/"/g,""").replace(/'/g,"'"); }; String.prototype.decodeHTML = function() { return this.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g,'"').replace(/"/g,'"').replace(/'/g,"'").replace(/'/g,"'"); }; String.prototype.getObjectFromQuerystring = function() { var map = {}; var str = this.replace(/^\?/, ""); var pairs = str.split("&"); for (var i=0; i 1) ? decodeURIComponent(utils.regexpReplace(keyValue[1],"\\+"," ","gi")) : null; value = (value == "true") ? true : ((value == "false") ? false : value); if (map[keyValue[0]] && (map[keyValue[0]] instanceof Array)) map[keyValue[0]].push(value); else map[keyValue[0]] = value; } return map; }; utils.getQueryStringFromObject = function( obj, prefix ) { var queryString = ""; for( var key in obj ) { var value = obj[key]; if( prefix ) key = key; switch( typeof(value) ) { case "undefined": case "function": break; case "string": case "number": case "boolean": queryString += encodeURIComponent( ( prefix ? prefix + '.' : '' ) + key ) + "=" + encodeURIComponent(value) + "&"; break; case "object": if( value instanceof Array ) { for( var i = 0; i < value.length; i++ ) { var parseObject = {}; parseObject[key] = value[i]; var parsed = utils.getQueryStringFromObject( parseObject, prefix ); if( parsed ) queryString += parsed + '&'; } } else { var parsed = utils.getQueryStringFromObject( value, ( prefix ? prefix + "." : "" ) + key ); if( parsed ) queryString += parsed + '&'; } break; } } return queryString.replace( new RegExp("&$",'g'), "" ); }; /** * Numbers * required by addWidget and addImage */ Number.prototype.format = function(decpoint, sep) { // check for missing parameters and use defaults if so if (arguments.length == 1) { sep = ","; } if (arguments.length == 0) { sep = ","; decpoint = "."; } // need a string for operations var num = this.toString(); // separate the whole number and the fraction if possible a = num.split(decpoint); x = a[0]; // decimal y = a[1]; // fraction z = ""; if (typeof(x) != "undefined") { // reverse the digits. regexp works from left to right. for (i=x.length-1;i>=0;i--) z += x.charAt(i); // add seperators. but undo the trailing one, if there z = z.replace(/(\d{3})/g, "$1" + sep); if (z.slice(-sep.length) == sep) z = z.slice(0, -sep.length); x = ""; // reverse again to get back the number for (i=z.length-1;i>=0;i--) x += z.charAt(i); // add the fraction back in, if it was there if (typeof(y) != "undefined" && y.length > 0) x += decpoint + y; } return x; } /** * public class ClassLoader * * Handles asynchronous requests for JavaScript classes. * * @depends Request * @depends BUILD_DATE */ window.ClassLoader = { dependencies: { "CYOAutoLookup" : [ "AutoLookup" ], "TagAutoLookup" : [ "AutoLookup" ], "Editor": [ "Area", "Toolbar" ], "Toolbar": [ "ToolbarInput" ] }, /** * public static void load() * * Asynchronously loads the specified JavaScript class. After the class has been * successfully loaded, the specified callback method, if any, is run. * * @param String classId The name of the class to be loaded. * @param Function callback (optional) The method to run after the class has loaded. * @param Boolean loaded (internal) Marks the class as loaded and runs the callback. * * @depends Request to asynchronously request the class. * @depends BUILD_DATE to build the URL from which to load the class. */ load: function( classId, callback, loaded ) { var loadable = true; // First, check to see if the class is already loaded... if( loaded ) { if( typeof(callback) === "function" ) callback(); } else { // Load dependencies... var dependencies = this.dependencies[classId]; for( var i = 0; dependencies && i < dependencies.length; i++ ) loadable = this.load( dependencies[i], ClassLoader.generateDependencyCallback( dependencies[i], classId, callback ) ) && loadable; // If all dependencies are loaded, then load the class... if( loadable ) { var request = this.getRequest( classId ); if( request ) { if( request.validateResponse() ) setTimeout( function() { ClassLoader.load( classId, callback, true ); }, 0 ); else { loadable = false; // TODO: Attach this callback to the existing loader. We already have an open request for this class, so let's not interrupt it. } } else { loadable = false; request = this.getRequest( classId, true ); request.setListener( function() { if( request.validateResponse() ) { try { eval( request.getObjectFromXML()["script"]["text"] ); setTimeout( function() { ClassLoader.load( classId, callback, true ); }, 0 ); } catch (ex) {} } } ); request.send( "/classloader/" + classId + "/" + BUILD_DATE ); } } } return loadable; }, /** * private static Request getRequest() * * This method allows the ClassLoader to interact with requests it has made. * * @param String classId The name of the class corresponding to this request. * @param boolean force If true, creates a new request if one does not already exist. * * @return Request corresponding to the provided classId. */ getRequest: function( classId, force ) { var requestId = "class:" + classId; var request = application.requests[requestId]; if( force && !request ) request = application.initRequest(requestId); return request; }, /** * public static void cancel() * * This method will cancel any open requests the ClassLoader has made for the given classId, * including any dependencies. Classes which have already been loaded are not affected. * * @param String classId The name of the class for which requests should be cancelled. */ cancel: function( classId ) { var dependencies = this.dependencies[classId]; for( var i = 0; dependencies && i < dependencies.length; i++ ) this.cancel(dependencies[i]); var request = this.getRequest(classId); if( request ) request.invalidate(); }, /** * private static Function generateDependencyCallback() * * This method generates a callback method for the loading of a class dependency. * The generated method will remove the dependency from its parent's dependency chain, * and if the parent has no further dependencies, will attempt to load the parent. * * @param String dependency The name of the class dependency. * @param String parentClassId The name of the class which depends on dependency. This is * the parent class in the dependency chain -- not in the object hierarchy. * @param Function callback The callback to execute after all dependencies have loaded. * * @return A function which will enforce loading of parent classes in the dependency chain. */ generateDependencyCallback: function( dependency, parentClassId, callback ) { return function() { var dependencies = ClassLoader.dependencies[parentClassId]; for( var i = 0; i < dependencies.length; i++ ) { if( dependencies[i] == dependency ) { dependencies.splice(i,1); ClassLoader.dependencies[parentClassId] = dependencies; break; } } if( dependencies.length == 0 ) ClassLoader.load( parentClassId, callback ); }; } }; /** * Construct a new Tooltip object. * @class for teh shits * @constructor */ var tooltip = null; function Tooltip(referenceElement, xhtml, xOffset, yOffset, pitch, className) { if (!arguments.length) return; this.referenceElement = referenceElement; this.referencePosition = utils.getAbsolutePosition(referenceElement); this.pitch = (typeof(pitch) != 'undefined' && pitch.toLowerCase() == 'left') ? 'Left' : 'Right'; this.tooltipDiv = document.createElement("div"); this.tooltipDiv.id = "tooltipDiv"; this.tooltipDiv.className = (typeof(className) != 'undefined') ? className : ''; Element.extend(this.tooltipDiv); this.ttTopDiv = document.createElement("div"); this.ttTopDiv.id = "ttTopDiv"; this.ttTopDiv.className = "ttTop" + this.pitch; this.ttMidDiv = document.createElement("div"); this.ttMidDiv.id = "ttMidDiv"; this.ttBotDiv = document.createElement("div"); this.ttBotDiv.id = "ttBotDiv"; this.ttCloseDiv = document.createElement("div"); this.ttCloseDiv.id = "ttCloseDiv"; this.ttCloseDiv.className = "ttClose" + this.pitch; this.ttContentDiv = document.createElement("div"); this.ttContentDiv.id = "ttContentDiv"; this.ttTopDiv.appendChild(this.ttCloseDiv); this.tooltipDiv.appendChild(this.ttTopDiv); this.ttMidDiv.appendChild(this.ttContentDiv); this.tooltipDiv.appendChild(this.ttMidDiv); this.tooltipDiv.appendChild(this.ttBotDiv); this.tooltipDiv.style.visibility = 'hidden'; document.body.appendChild(this.tooltipDiv); this.tooltipDiv.style.top = this.referencePosition.absTop + 'px'; this.tooltipDiv.style.left = this.referencePosition.absLeft + 'px'; this.ttContentDiv.innerHTML = xhtml; //position the tooltip. this.xOffset = (typeof(xOffset) != 'undefined') ? parseInt(xOffset) : 0; this.yOffset = (typeof(yOffset) != 'undefined') ? parseInt(yOffset) : 0; if (this.pitch == 'Left') this.xOffset = this.xOffset - parseInt(this.tooltipDiv.scrollWidth); this.tooltipDiv.style.marginLeft = this.xOffset + 'px'; this.tooltipDiv.style.marginTop = this.yOffset + 'px'; //close existing tooltip if (tooltip){ tooltip.close(true) }; tooltip = this; //prep the close event handler. utils.addEvent( this.ttCloseDiv, "click", function (e) { if (window.tooltip) tooltip.close(); } ); this.open(); } Tooltip.prototype.setContent = function(xhtml) { this.xhtml = xhtml; this.ttContentDiv.innerHTML = this.xhtml; }; Tooltip.prototype.getContent = function() { return this.xhtml; }; Tooltip.prototype.close = function(opening) { //fade it out var tooltipToClose = tooltip; if(!opening) tooltip = null; new Effect.Fade(this.tooltipDiv, {duration:.3, afterFinish : function(){ document.body.removeChild(tooltipToClose.tooltipDiv); } }); return false; }; Tooltip.prototype.open = function() { //fade it in this.tooltipDiv.style.display='none'; this.tooltipDiv.style.visibility='visible'; new Effect.Appear(this.tooltipDiv, {duration:.3, afterFinish : function(){ } }); return false; };/** * Construct a new Request object. * @class Simple XMLHTTPRequest management class. * @constructor */ function Request(requestReference) { if (window.XMLHttpRequest) { this.req = new XMLHttpRequest(); } else if (window.ActiveXObject) { this.req = new ActiveXObject("Microsoft.XMLHTTP"); } this.reference = requestReference; this.url = null; this.method = null; this.xml = null; this.objFromXml = null; this.timeout = null; this.timeoutDelay = 0; //set this to allow a stream of requests to not conflict. this.isStatusComplete = false; this.isInvalidated = false; this.onResponseError = null; //function handler for all errors this.contentType = "text/xml"; } /** * Assigns the onReadyStateChange handler to a function. * @param {function} fn Event handler function that listens for the response of this request object. */ Request.prototype.setListener = function(fn) { this.listener = fn; } /** * Assigns a custom handler function to be called on response error. * @param {function} fn Handler function that deals with a response. */ Request.prototype.setErrorHandler = function(fn) { this.onResponseError = fn; } /** Invalidate this request. Provides a hook for listeners to tell whether or not to execute. */ Request.prototype.invalidate = function() { this.isInvalidated = true; } /** * Clears any pending requests and attempts to send a new request. * @param {String} url URL to which the request is to be sent. Note that the domain MUST be same-origin as this JS file. * @param {String} method GET, POST, PUT, DELETE, or HEAD. * @param {String} xml Body of the request, in standard XML format. Used with POST and PUT methods only. */ Request.prototype.send = function(url, method, xml) { if (this.req) { this.url = url; if (this.url.indexOf('.txt') == this.url.length - 4) this.url += '/' this.method = method || "GET"; this.xml = xml; this.timeoutSend = setTimeout('application.requests["' + this.reference + '"].asynchSend()',this.timeoutDelay); } } /** * Opens a connection to the specified URL and sends the request. This is called asynchronously from this.send(). */ Request.prototype.asynchSend = function() { if (utils.isSafari) { //overwrite the PUT or DELETE methods, to keep Safari from punting on them completely. if (this.method == 'PUT') { this.method = 'POST'; this.url = this.url + '?method=PUT'; } if (this.method == 'DELETE') { this.method = 'POST'; this.url = this.url + '?method=DELETE'; } } this.objFromXml = null; this.req.open(this.method, this.url, true); try { this.req.setRequestHeader( 'Content-Type', this.contentType ); } catch(e) { try { this.req.setContentType( this.contentType ); } catch(e) { try { this.req.contentType = this.contentType; } catch(e) {} } } var request = this; this.req.onreadystatechange = function(e) { //if( this.readyState == 4 ) utils.log( "<-", request.method, request.url, this.status, request.contentType, this.responseText ); if( request.listener ) request.listener.call( this, e ); }; //utils.log( "->", this.method, this.url, this.contentType, this.xml ); this.req.send(this.xml); } /** * Transforms a string for URL submission. Escapes the string. This used to do more (underscore, space thing). * @param {String} element_name Unescaped string. * @return Escaped string. * @type String */ Request.prototype.wikiEscape = function(element_name) { return encodeURIComponent(element_name); } /** * Transforms a string escaped for URL submission. Unescapes the string. This used to replace underscores with spaces. * @param {String} element_name Unescaped string. * @return Escaped string. * @type String */ Request.prototype.wikiUnescape = function(element_name) { return decodeURIComponent(element_name); } /** * @param {request} req Request object to examine the response of. * @return The documentElement of the XML in the response. * @type element */ Request.prototype.validateResponse = function(req, errorHandler) { if (typeof(req) == "undefined") req = this.req; if ( !this.isStatusComplete && !this.timeout ) { this.timeout = setTimeout("application.requests['" + this.reference + "'].showNoResponse();", 60000); return false; } if (this.isInvalidated) return false; if (req.readyState == 4) { clearTimeout(this.timeout); this.timeout = null; var returnStatus = 0; var returnText = ""; try { returnStatus = req.status; returnText = req.statusText; } catch (e) { returnStatus = 0; returnText = ""; } if (returnStatus == 200) { if (this.method == 'HEAD') return true; element = req.responseXML.documentElement; if (!element) return this.handleError(returnStatus, errorCode, 'We are sorry, a processing occurred. If this problem persists, please reload the page and try again.'); if (element.nodeName.toLowerCase() != "error") { this.isStatusComplete = true; return true; } else { //TODO improve error mapping var errorCode = parseInt(element.getAttribute("status")); switch (errorCode) { case 1: //UserCreateException case 6: //NoSuchPageException case 9: //PageOutOfDateException case 10: //UserNotFoundException case 17: //NoSuchFavoriteException case 18: //NoSuchAccountException case 23: //duplicate tag case 26: //general search error case 27: //search server is down case 29: //FieldValidationException - bad input case 32: //content page has been deleted case 40: //FavoriteAlreadyExistsException case 42: //Template doesn't exist case 1001: //RSS feed invalid case 34561: //Friendship already exists //return to listener for error handling. return true; break; case 401: //unauthorized return this.handleError(returnStatus, errorCode, 'It appears you are no longer signed-in or are unauthorized to use this feature.'); break; default: return this.handleError(returnStatus, errorCode, 'We are sorry, an error occurred. If this problem persists, please reload the page and try again.'); break; } utils.logMicroEvent('Response 200 exception - status='+element.getAttribute("status")+',statusText=' + returnText); return false; } } else if (returnStatus == 405){ //readonly return this.handleError(returnStatus, null, 'We are sorry, this feature has been temporarily disabled. Please reload the page and try again.'); } else if (returnStatus == 0) { //request aborted by script } else { utils.logMicroEvent('Response ' + returnStatus + ' exception - statusText=' + returnText); return this.handleError(returnStatus, null, "We are sorry, a server error occurred. \nIf this problem persists, please reload the page and try again."); } } return false; } Request.prototype.handleError = function(returnStatus, errorCode, errorText) { if (this.onResponseError) { this.onResponseError(returnStatus, errorCode, errorText) } else { if (errorText) alert(errorText); } return false; } Request.prototype.showNoResponse = function() { if (this.req.readyState != 4) { this.handleError(null, null, "We are sorry, this web site is not responding. If this problem persists, please reload the page and try again."); } } /** * Unmarshalls an XML element (and its children) into JS objects. If the XML element has same-named children, * they are placed into an Array(). * @param {element} xmlElement XML element to be unmarshalled. * @return Unmarshalled object containing data from the XML element. * @type Object */ Request.prototype.getObjectFromXML = function(xmlElement) { if (!this.objFromXml) this.objFromXml = this.parseXmlToObject(xmlElement); return this.objFromXml; } Request.prototype.parseXmlToObject = function(xmlElement) { if (typeof(xmlElement) == "undefined") xmlElement = this.req.responseXML.documentElement; if (!xmlElement) return null; var obj = new Object(); //nodeTest = '<' + xmlElement.nodeName; //for (var j=0;j (' + xmlElement.childNodes.length + ' children)'); if (xmlElement.attributes){ for (var j=0;j= 0) { return (childNode.nodeValue) ? childNode.nodeValue : childNode.text; } else { var childObj = this.parseXmlToObject(childNode); if (typeof obj[childNodeName] == "undefined") { try{ obj[childNodeName] = childObj; if (typeof obj[childNodeName] == "undefined") { //FF empty CDATA returns undefined. obj[childNodeName] = ''; } else { obj[childNodeName].length = 1; obj[childNodeName][0] = obj[childNodeName]; } } catch( e ){ alert( e ); } } else { if (obj[childNodeName].length == 1) { tmp = obj[childNodeName]; //obj[childNodeName].length = null; obj[childNodeName] = new Array(); obj[childNodeName][obj[childNodeName].length] = tmp; } obj[childNodeName][obj[childNodeName].length] = childObj; } } } } return obj; } //Constants & Globals var logoImageLoaded = false; //DOM Element Event Handler Assignments //Each event handler that the CYO deals with may be assigned to an element, if it exists. function initEvents() { if ($("logo_text")) { utils.addEvent($("logo_text"),"keydown",function(e) { setTimeout("customLogo.updateHeaderText()",0); }); utils.addEvent($("logo_text"),"change",function(e) { setTimeout("customLogo.updateHeaderText()",0); }); utils.addEvent($("logo_text"),"mouseup",function(e) { setTimeout("customLogo.updateHeaderText()",0); }); utils.addEvent($("logoOption_text_removeImage"),"click",function(e) { customLogo.removeImage(); }); utils.addEvent($("logoOption_text_removeImage2"),"click",function(e) { customLogo.removeImage(); }); utils.addEvent($("logoOption_image_openForm"),"click",function(e) { customLogo.setImageForm('open'); }); utils.addEvent($("logoOption_image_reopenForm"),"click",function(e) { customLogo.setImageForm('open'); }); } if ($("wikiUrl")) { var lookup; // Load the lookup classes initAutoComplete = function() { if( !( window.AutoLookupConfig && window.CYOAutoLookup ) ) return; var url = "/wikisearch?maxResults=MAXRESULTS&offset=OFFSET&name="; var lookupConfig = new AutoLookupConfig($("nameSuggestMsg").innerHTML); lookupConfig.setDataCollectionName("wiki"); lookupConfig.setDataValueNames(["name", "wikiDomain"]); lookupConfig.removeUpKeys(lookupConfig.upKeys); lookupConfig.removeDownKeys(lookupConfig.downKeys); lookupConfig.setSelectListener(null); lookup = new CYOAutoLookup(lookupConfig, $("wikiUrl"), "getWikiNames", url); if ($("wikiUrl").value) lookup.keyUp(null); } ClassLoader.load("CYOAutoLookup", initAutoComplete); ClassLoader.load("AutoLookupConfig", initAutoComplete); } //cyo handlers. if($("containerCyo")){ utils.addEvent($("cyo_description_trigger"),"click",function(e) { tooltip = new Tooltip($("cyo_description_trigger"), $("cyo_description_trigger").getElementsByTagName("span")[0].innerHTML, -200, 20, 'right', 'largeWrapperToolTip' ); return false; }); utils.addEvent($("cyo_contributors_trigger"),"click",function(e) { tooltip = new Tooltip($("cyo_contributors_trigger"), $("cyo_contributors_trigger").getElementsByTagName("span")[0].innerHTML, 0, 20, 'left' ); return false; }); utils.addEvent($("cyo_tags_trigger"),"click",function(e) { tooltip = new Tooltip($("cyo_tags_trigger"), $("cyo_tags_trigger").getElementsByTagName("span")[0].innerHTML, 0, 20 ); return false; }); utils.addEvent($("cyo_anon_trigger"),"click",function(e) { tooltip = new Tooltip($("cyo_anon_trigger"), $("cyo_anon_trigger").getElementsByTagName("span")[0].innerHTML, 0, 20 ); return false; }); utils.addEvent($("cyo_reg_trigger"),"click",function(e) { tooltip = new Tooltip($("cyo_reg_trigger"), $("cyo_reg_trigger").getElementsByTagName("span")[0].innerHTML, 0, 20 ); return false; }); utils.addEvent($("cyo_publicinvite_trigger"),"click",function(e) { if (utils.isMSIE) { var xOffset = document.getElementById('cyo_publicinvite_trigger').offsetWidth; }else{ var xOffset = document.getElementById('cyo_publicinvite_trigger').firstChild.offsetWidth; } tooltip = new Tooltip($("cyo_publicinvite_trigger"), $("cyo_publicinvite_trigger").getElementsByTagName("span")[0].innerHTML, xOffset, 20, 'left' ); return false; }); utils.addEvent($("cyo_privateinvite_trigger"),"click",function(e) { if (utils.isMSIE) { var xOffset = document.getElementById('cyo_privateinvite_trigger').offsetWidth; }else{ var xOffset = document.getElementById('cyo_privateinvite_trigger').firstChild.offsetWidth; } tooltip = new Tooltip($("cyo_privateinvite_trigger"), $("cyo_privateinvite_trigger").getElementsByTagName("span")[0].innerHTML, xOffset, 20, 'left' ); return false; }); utils.addEvent($("role_trigger"),"click",function(e) { if (tooltip) { tooltip.close(); return null; } else { if (utils.isMSIE) { var xOffset = document.getElementById('role_trigger').offsetWidth; }else{ var xOffset = document.getElementById('role_trigger').firstChild.offsetWidth; } tooltip = new Tooltip($("role_trigger"), $("role_trigger").getElementsByTagName("span")[0].innerHTML, xOffset, 20 ); return false; } }); } } init('setTimeout("initEvents();",0)'); /*checkWikiName = new function(){ this.nameList=[]; this.referenceName = 'checkWikiName'; this.charThreshold = 3; this.maxListLength = 10; this.firstThree = ''; this.createVisibleList = function(){ this.introText='   '+$('nameSuggestMsg').innerHTML+'
'; if (!this.nameListHolder){ this.nameListHolder=document.createElement('SPAN'); this.nameListHolder.className='suggestList'; this.formInputElement.parentNode.insertBefore(this.nameListHolder, this.formInputElement.nextSibling); } this.nameListHolder.innerHTML = ''; var count = 0; for(var i=0; i' + this.nameList[i].name + '
'; count++; } } if(this.nameListHolder.innerHTML==''){ this.destroyVisibleList(); } else { this.nameListHolder.innerHTML = this.introText + this.nameListHolder.innerHTML; utils.addEvent($(this.referenceName), 'click', function(e) {checkWikiName.destroyVisibleList()} ); } } this.destroyVisibleList = function(){ if(this.nameListHolder){ this.formInputElement.parentNode.removeChild(this.nameListHolder) this.nameListHolder=null; } } this.checkName = function(formInputElement){ this.formInputElement = formInputElement; //regExp removes whitespace (does trim) this.wikiName = formInputElement.value.trim(); //not enought letters do nothing if (this.wikiName.length < this.charThreshold) { this.destroyVisibleList(); return false; } this.uri = '/wikisearch?name='+this.wikiName; //ajax call if enough letters, or first three have changed if ( this.wikiName.length >= this.charThreshold && this.wikiName.substring(0,3)!=this.firstThree ){ var requestObj = application.initRequest(this.referenceName); requestObj.setListener( function(e) { if (requestObj.validateResponse()) { checkWikiName.nameList=[]; utils.stopThrobber(formInputElement); var xmlResults = requestObj.getObjectFromXML(); if (parseInt(xmlResults['results']) > 0){ for(var i=0; i0) { this.createVisibleList(); } return false; } } */ application = new function(){ this.requests = new Object; this.initRequest = function(requestReference) { if (this.requests[requestReference]) { if (this.requests[requestReference].req.readyState != 0) this.requests[requestReference].req.abort(); if (this.requests[requestReference].timeoutSend) clearTimeout(this.requests[requestReference].timeoutSend); } else { this.requests[requestReference] = new Request(requestReference); } return this.requests[requestReference]; }; this.attachedEvents = new Array(); this.detachEvents = function( ) { for (var i=application.attachedEvents.length-1; i>=0; i--) { if (application.attachedEvents[i]["elem"].removeEventListener) { application.attachedEvents[i]["elem"].removeEventListener(application.attachedEvents[i]["evtName"], application.attachedEvents[i]["handler"], false); } else if(application.attachedEvents[i]["elem"].detachEvent){ application.attachedEvents[i]["elem"].detachEvent("on" + application.attachedEvents[i]["evtName"],application.attachedEvents[i]["handler"]); } application.attachedEvents.length = i; } } init('setTimeout("utils.addEvent(window, \'unload\', application.detachEvents)" , 0)'); } var skinSlider = { slider : {}, paginator : {}, leftControl : {}, rightControl : {}, skins : [], thumbSizeX : 210, thumbSizeY : 204, groupSize : 8, getSlideIncrement : function(){ return this.thumbSizeX*this.groupSize/2 }, pages : [], pageTabs : [], currentPage : 0, currentPreviewImg : null, currentSelection : null, zoomImages : [], initialSkin : '', init : function() { this.formInput = $('skin'); this.slider = $('slider'); this.paginator = $('paginator'); this.leftControl = $('moveLeft'); this.rightControl = $('moveRight'); this.previewScreen = $('previewScreen'); this.skins = $( 'skinData' ).getElementsByTagName('li'); var topRow=''; var bottomRow=''; var flipRow=false; var paginatorhtml=''; var zoomhtml = ''; var skinName = ''; var thumb = ''; var radio= ''; var bigZoom = ''; var zoomLink = ''; Event.observe(this.leftControl, 'click', function(){ return skinSlider.slideSlider(-1) } ); Event.observe(this.rightControl, 'click', function(){ return skinSlider.slideSlider(1) } ); //set the initial skin if (this.formInput.value==''){ this.initialSkin = this.skins[0].id.replace('data_',''); this.formInput.value = this.initialSkin; } else { this.initialSkin = this.formInput.value; } init('skinSlider.setSelection($("skin_a_"+skinSlider.initialSkin))'); for (var i=0; i
'; zoomLink = ''+ 'zoom' radio = ''+ ''+ ' ' cell = ''+thumb+zoomLink+radio+''; if(flipRow){ bottomRow += cell; } else { topRow += cell; } if((i+1)%(this.groupSize/2)==0){ flipRow=(flipRow) ? false : true ; } if( ( i!=0 && (i+1)%this.groupSize==0 ) || (i+1==this.skins.length && topRow!='') ){ //duplicate with below div = document.createElement('div'); if (bottomRow == '') bottomRow = ''; //invalid HTML hack. div.innerHTML=''+topRow+''+bottomRow+'
'; this.pages[this.pages.length] = div; paginatorhtml+=''+(this.pages.length)+''; this.pageTabs[this.pages.length-1] = "pageNumber" + this.pages.length; if( i!=0 && (i+1)%this.groupSize==0 ){ topRow=bottomRow=''; } } } if (utils.isSafari) { this.paginator.innerHTML='
'+paginatorhtml+'
';; } else { this.paginator.innerHTML=''+paginatorhtml+'
';; } this.setOrder(); for (var i=0; i'; } }, setOrder : function(direction) { $( 'pageNumber'+(this.currentPage+1) ).className='off'; if(typeof(direction) != 'undefined'){ if (parseInt(direction) == 'NaN' || parseInt(direction) == 0) return false; this.currentPage += direction/Math.abs(direction); //adds 1 or subtracts 1, even if direction is > 1 or < -1. if (this.currentPage==-1) this.currentPage=this.pages.length-1; if (this.currentPage==this.pages.length) this.currentPage=0; //going right- take from the left, add to the right if(direction > 0){ elem = (this.currentPage==this.pages.length-1) ? this.pages[0] : this.pages[this.currentPage+1]; this.slider.removeChild(this.slider.firstChild); this.slider.appendChild(elem); if (--direction > 0) this.slideSlider(direction); } //going left- take from the right, add to the left else{ elem = (this.currentPage==0) ? this.pages[this.pages.length-1] : this.pages[this.currentPage-1]; this.slider.removeChild(this.slider.lastChild); this.slider.insertBefore(elem, this.slider.firstChild); if (++direction < 0) this.slideSlider(direction); } } else { //when first loaded - set end to be the left if(this.pages.length>2){ this.slider.appendChild(this.pages[this.pages.length-1]); } this.slider.appendChild(this.pages[0]); if(this.pages.length>1){ this.slider.appendChild(this.pages[1]); } } if(this.slider.firstChild){ this.slider.firstChild.style.left='0px'; this.slider.firstChild.style.top='0px'; } if(this.slider.childNodes[1]){ this.slider.childNodes[1].style.left= this.getSlideIncrement()+'px'; this.slider.childNodes[1].style.top='-'+this.thumbSizeY*2+'px'; } if(this.slider.lastChild){ this.slider.lastChild.style.left=this.getSlideIncrement()*2+'px'; this.slider.lastChild.style.top='-'+this.thumbSizeY*4+'px'; } $( 'pageNumber'+(this.currentPage+1) ).className='on'; }, slideSlider : function(steps) { new Effect.MoveBy(this.slider.childNodes[0],0,this.getSlideIncrement()*-steps/Math.abs(steps), { //beforeSetup: function(){Element.toggle('rightCover')}, queue: 'start', duration: .7/Math.abs(steps) }); new Effect.MoveBy(this.slider.childNodes[1],0,this.getSlideIncrement()*-steps/Math.abs(steps), { queue: 'start', duration: .7/Math.abs(steps) }); new Effect.MoveBy(this.slider.childNodes[2],0,this.getSlideIncrement()*-steps/Math.abs(steps), { afterFinish: function(){skinSlider.setOrder(steps)}, queue: 'start', duration: .7/Math.abs(steps) }); return false; }, setSelection : function(who) { var radio = who.parentNode.getElementsByTagName('INPUT')[0]; radio.focus(); if(radio)radio.checked=true; if(this.currentSelection){ // turn the previous one off this.currentSelection.className = this.currentSelection.className.replace(' on', '') //set the real form value this.formInput.value=radio.value; }; //load the correct css for the custom logo component customLogo.setSelection((this.currentSelection) ? this.currentSelection.id : null, who.parentNode.id); this.currentSelection = $(who.parentNode); this.currentSelection.className+=' on'; }, showPreviewImg : function(who) { this.hidePreviewImg(this.currentPreviewImg, function(){ $('zoomPreviewImage').src='/img/pxlclear.gif'; new Effect.Appear($('zoomPreview') , {duration:.3}); $('zoomPreviewImage').src='/skins/'+who+'/preview/img/preview_512.jpg'; }); skinSlider.currentPreviewImg=$('zoomPreview'); return false; }, hidePreviewImg : function(elem, callback){ if(elem){ new Effect.Fade(elem, { duration:.3, afterFinish: callback }); }else{ callback(); } return false; } }; var customLogo = { addImageText: '',//set this to the button value when the form is created addingImageText: '', init : function(){ if($('wikiImageUrl').value !=''){ this.imageURL = $("wikiImageUrl").value; $("headerSample").innerHTML = ''; logoImageLoaded = true; this.setImageForm('closed'); } if (utils.isSafari) { //Safari needs a displayed iframe to post to. $("imageFrame").style.display = 'block'; $("imageFrame").style.height = '1px'; $("imageFrame").style.width = '1px'; } utils.addEvent($("imageFrame"),"load",function(e) { customLogo.iFrameLoaded(); }); }, setSelection : function(oldSkinName, newSkinName){ this.currentSkin=newSkinName; var skinHeaderNew='skin_css_header'; //alert("old:" + oldSkinName + "new: " + newSkinName); if(!$(skinHeaderNew)){ var oStyle = document.createElement('LINK'); oStyle.id= skinHeaderNew; oStyle.rel= 'stylesheet'; oStyle.text= 'text/css'; oStyle.disabled=true; oStyle.href = '/skins/'+newSkinName+'/preview/headerSnippet.css'; document.documentElement.firstChild.appendChild(oStyle); oStyle.disabled=false; } else { this.isSkinCssLoaded=false; $(skinHeaderNew).href = '/skins/'+newSkinName+'/preview/headerSnippet.css'; } }, updateHeaderText : function() { var newtext = $('logo_text').value; newtext = (newtext == '') ? ' ' : newtext.encodeHTML(); $('headerSample').innerHTML = '' + newtext + ''; $('headerTitle').innerHTML = newtext; }, removeImage : function() { this.updateHeaderText(); $('wikiImageUrl').value = ''; logoImageLoaded = false; this.setImageForm('closed'); }, setImageForm : function(state) { formDiv = $("logoOption_image_form"); if (state == 'closed') { if (!logoImageLoaded) { $("logoOption_image_shownAbove").style.display = "none"; $("logoOption_text_shownAbove").style.display = "inline"; $("logoOption_image_empty").style.display = "block"; $("logoOption_image_exists").style.display = "none"; $("logoOption_text_editable").style.display = "block"; $("logoOption_text_uneditable").style.display = "none"; $("logoOption_text_uneditable2").style.display = "none"; $("responseImageTooLarge").style.display = "none"; } else { $("logoOption_image_shownAbove").style.display = "inline"; $("logoOption_text_shownAbove").style.display = "none"; $("logoOption_image_empty").style.display = "none"; $("logoOption_image_exists").style.display = "block"; $("logoOption_text_editable").style.display="none"; $("logoOption_text_uneditable").style.display = "block"; $("logoOption_text_uneditable2").style.display = "block"; } formDiv.style.display = "none"; formDiv.innerHTML = ""; } else if (state == 'open') { $("logoOption_image_empty").style.display = "none"; $("logoOption_image_exists").style.display = "none"; //Create our form content from the private form contents. //The private form contents should never be modified, which allows us to always revert to the initial display state. privateFormDiv = $("logoOption_image_form_private") formHTML = privateFormDiv.innerHTML formHTML = utils.regexpReplace(formHTML,'<','<','gi'); formHTML = utils.regexpReplace(formHTML,'>','>','gi'); formDiv.innerHTML = ''; if (utils.isMSIE) { //IE doesn't support dynamically created multipart form submits. (http://verens.com/archives/2005/07/06/ie-bugs-dynamically-creating-form-elements/) formEle = document.createElement('
'); } else { formEle = document.createElement("form"); formEle.setAttribute("id", "imageForm"); formEle.setAttribute("method", "POST"); formEle.setAttribute("action", ""); formEle.setAttribute("enctype", "multipart/form-data"); formEle.setAttribute("target", "imageFrame"); } formEle.innerHTML = formHTML; formDiv.appendChild(formEle); this.addImageButton = $('addImageButton'); this.addImageText = this.addImageButton.innerHTML; this.addingImageText = $('uploadActiveText').innerHTML; utils.addEvent(this.addImageButton,"click",function(e) { if (!customLogo.addImage()) utils.cancelEvent(e); }); this.validateLoadedImage = function() { if(logoImageLoaded)return; var imgDims = {x:this.originalImage.width,y:this.originalImage.height}; if (imgDims.y > 200 || imgDims.x > 1200) { //need to resize and re-request the image. if (imgDims.x/5 > imgDims.y/2) { //x is more diff than y imgDims.y = parseInt(1200 * imgDims.y / imgDims.x); imgDims.x = 1200; } else { //y is more diff than x imgDims.x = parseInt(200 * imgDims.x / imgDims.y); imgDims.y = 200; } this.imageURL += "/GW" + imgDims.x + "H" + imgDims.y; $("responseImageTooLarge").style.display = "block"; } else { $("responseImageTooLarge").style.display = "none"; } img = ($("headerSample").getElementsByTagName('img')[0]) if(img && typeof(img)!='undefined'){purge(img);} $("headerSample").innerHTML = ''; $("wikiImageUrl").value = this.imageURL; logoImageLoaded = true; this.setImageForm('closed'); } utils.addEvent($("imageLocation_file"),"click",function(e) { $("logoOption_image_fileInput").style.display = "block"; $("logoOption_image_urlInput").style.display = "none"; utils.findTargetElem(e).form.elements['url'].value = ''; utils.findTargetElem(e).form.elements['filepath'].value = ''; }); utils.addEvent($("imageLocation_external"),"click",function(e) { $("logoOption_image_fileInput").style.display = "none"; $("logoOption_image_urlInput").style.display = "block"; utils.findTargetElem(e).form.elements['url'].value = 'http://'; utils.findTargetElem(e).form.elements['filepath'].value = ''; }); utils.addEvent($("logoOption_image_cancelForm"),"click",function(e) { customLogo.setImageForm('closed'); }); formDiv.style.display='block'; } }, addImage: function() { var formEle = $('imageForm'); if ($("logoOption_image_response").innerHTML != '') $("logoOption_image_response").innerHTML = ''; var tempUrl = formEle.elements['url'].value.trim(); var tempPath = formEle.elements['filepath'].value.trim(); if ((tempUrl == '' || tempUrl == 'http://') && (tempPath == '' || tempPath.indexOf('http://') == 0)) { $("logoOption_image_response").innerHTML=$('uploadErrorMsg').innerHTML; return false; } else { if (tempPath == ''){ formEle.setAttribute( 'enctype', 'application/x-www-form-urlencoded'); } else { formEle.setAttribute( 'enctype', 'multipart/form-data'); } formEle.setAttribute( 'action', "/wiki/" + Request.prototype.wikiEscape(formEle.elements['imageWikiName'].value) + "/image/logo"); //this.addImageButton.innerHTML = this.addingImageText; utils.startThrobber(this.addImageButton.parentNode.parentNode); formEle.submit(); return true; } return false; }, iFrameLoaded: function() { var iframe = $("imageFrame"); var httpStatus = iframe.contentWindow.window['httpStatus']; logoImageLoaded=false; this.imageURL = iframe.contentWindow.window['uploadedFilePath']; utils.stopThrobber(this.addImageButton.parentNode.parentNode); if (typeof(this.imageURL) != 'undefined' && httpStatus == '200') { if(this.originalImage){ purge(this.originalImage); } this.originalImage = new Image(); this.originalImage.src = this.imageURL; utils.addEvent(this.originalImage,"load",function(e){customLogo.validateLoadedImage();}); } else if (!(iframe.contentWindow.window.location.href.indexOf(':blank')>0)){ $("logoOption_image_response").innerHTML=$('uploadErrorMsg').innerHTML; //this.addImageButton.innerHTML = this.addImageText; } } };