diff options
67 files changed, 3538 insertions, 11981 deletions
diff --git a/reports/site_media/AnchorPosition.js b/reports/site_media/AnchorPosition.js new file mode 100644 index 000000000..7db0cc89e --- /dev/null +++ b/reports/site_media/AnchorPosition.js @@ -0,0 +1,147 @@ +// =================================================================== +// Author: Matt Kruse <matt@mattkruse.com> +// WWW: http://www.mattkruse.com/ +// +// NOTICE: You may use this code for any purpose, commercial or +// private, without any further permission from the author. You may +// remove this notice from your final code if you wish, however it is +// appreciated by the author if at least my web site address is kept. +// +// You may *NOT* re-distribute this code in any way except through its +// use. That means, you can include it in your product, or your web +// site, or any other form where the code is actually being used. You +// may not put the plain javascript up on your site for download or +// include it in your javascript libraries for download. +// If you wish to share this code with others, please just point them +// to the URL instead. +// Please DO NOT link directly to my .js files from your site. Copy +// the files to your server and use them there. Thank you. +// =================================================================== + +/* +AnchorPosition.js +Author: Matt Kruse +Last modified: 10/11/02 + +DESCRIPTION: These functions find the position of an <A> tag in a document, +so other elements can be positioned relative to it. + +COMPATABILITY: Netscape 4.x,6.x,Mozilla, IE 5.x,6.x on Windows. Some small +positioning errors - usually with Window positioning - occur on the +Macintosh platform. + +FUNCTIONS: +getAnchorPosition(anchorname) + Returns an Object() having .x and .y properties of the pixel coordinates + of the upper-left corner of the anchor. Position is relative to the PAGE. + +getAnchorWindowPosition(anchorname) + Returns an Object() having .x and .y properties of the pixel coordinates + of the upper-left corner of the anchor, relative to the WHOLE SCREEN. + +NOTES: + +1) For popping up separate browser windows, use getAnchorWindowPosition. + Otherwise, use getAnchorPosition + +2) Your anchor tag MUST contain both NAME and ID attributes which are the + same. For example: + <A NAME="test" ID="test"> </A> + +3) There must be at least a space between <A> </A> for IE5.5 to see the + anchor tag correctly. Do not do <A></A> with no space. +*/ + +// getAnchorPosition(anchorname) +// This function returns an object having .x and .y properties which are the coordinates +// of the named anchor, relative to the page. +function getAnchorPosition(anchorname) { + // This function will return an Object with x and y properties + var useWindow=false; + var coordinates=new Object(); + var x=0,y=0; + // Browser capability sniffing + var use_gebi=false, use_css=false, use_layers=false; + if (document.getElementById) { use_gebi=true; } + else if (document.all) { use_css=true; } + else if (document.layers) { use_layers=true; } + // Logic to find position + if (use_gebi && document.all) { + x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]); + y=AnchorPosition_getPageOffsetTop(document.all[anchorname]); + } + else if (use_gebi) { + var o=document.getElementById(anchorname); + x=AnchorPosition_getPageOffsetLeft(o); + y=AnchorPosition_getPageOffsetTop(o); + } + else if (use_css) { + x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]); + y=AnchorPosition_getPageOffsetTop(document.all[anchorname]); + } + else if (use_layers) { + var found=0; + for (var i=0; i<document.anchors.length; i++) { + if (document.anchors[i].name==anchorname) { found=1; break; } + } + if (found==0) { + coordinates.x=0; coordinates.y=0; return coordinates; + } + x=document.anchors[i].x; + y=document.anchors[i].y; + } + else { + coordinates.x=0; coordinates.y=0; return coordinates; + } + coordinates.x=x; + coordinates.y=y; + return coordinates; + } + +// getAnchorWindowPosition(anchorname) +// This function returns an object having .x and .y properties which are the coordinates +// of the named anchor, relative to the window +function getAnchorWindowPosition(anchorname) { + var coordinates=getAnchorPosition(anchorname); + var x=0; + var y=0; + if (document.getElementById) { + if (isNaN(window.screenX)) { + x=coordinates.x-document.body.scrollLeft+window.screenLeft; + y=coordinates.y-document.body.scrollTop+window.screenTop; + } + else { + x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset; + y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset; + } + } + else if (document.all) { + x=coordinates.x-document.body.scrollLeft+window.screenLeft; + y=coordinates.y-document.body.scrollTop+window.screenTop; + } + else if (document.layers) { + x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset; + y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset; + } + coordinates.x=x; + coordinates.y=y; + return coordinates; + } + +// Functions for IE to get position of an object +function AnchorPosition_getPageOffsetLeft (el) { + var ol=el.offsetLeft; + while ((el=el.offsetParent) != null) { ol += el.offsetLeft; } + return ol; + } +function AnchorPosition_getWindowOffsetLeft (el) { + return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft; + } +function AnchorPosition_getPageOffsetTop (el) { + var ot=el.offsetTop; + while((el=el.offsetParent) != null) { ot += el.offsetTop; } + return ot; + } +function AnchorPosition_getWindowOffsetTop (el) { + return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop; + } diff --git a/reports/site_media/CalendarPopup.js b/reports/site_media/CalendarPopup.js index 333d88931..b63ff2f11 100644 --- a/reports/site_media/CalendarPopup.js +++ b/reports/site_media/CalendarPopup.js @@ -18,71 +18,676 @@ // the files to your server and use them there. Thank you.
// ===================================================================
-/* SOURCE FILE: AnchorPosition.js */
-function getAnchorPosition(anchorname){var useWindow=false;var coordinates=new Object();var x=0,y=0;var use_gebi=false, use_css=false, use_layers=false;if(document.getElementById){use_gebi=true;}else if(document.all){use_css=true;}else if(document.layers){use_layers=true;}if(use_gebi && document.all){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_gebi){var o=document.getElementById(anchorname);x=AnchorPosition_getPageOffsetLeft(o);y=AnchorPosition_getPageOffsetTop(o);}else if(use_css){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_layers){var found=0;for(var i=0;i<document.anchors.length;i++){if(document.anchors[i].name==anchorname){found=1;break;}}if(found==0){coordinates.x=0;coordinates.y=0;return coordinates;}x=document.anchors[i].x;y=document.anchors[i].y;}else{coordinates.x=0;coordinates.y=0;return coordinates;}coordinates.x=x;coordinates.y=y;return coordinates;}
-function getAnchorWindowPosition(anchorname){var coordinates=getAnchorPosition(anchorname);var x=0;var y=0;if(document.getElementById){if(isNaN(window.screenX)){x=coordinates.x-document.body.scrollLeft+window.screenLeft;y=coordinates.y-document.body.scrollTop+window.screenTop;}else{x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;}}else if(document.all){x=coordinates.x-document.body.scrollLeft+window.screenLeft;y=coordinates.y-document.body.scrollTop+window.screenTop;}else if(document.layers){x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;}coordinates.x=x;coordinates.y=y;return coordinates;}
-function AnchorPosition_getPageOffsetLeft(el){var ol=el.offsetLeft;while((el=el.offsetParent) != null){ol += el.offsetLeft;}return ol;}
-function AnchorPosition_getWindowOffsetLeft(el){return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;}
-function AnchorPosition_getPageOffsetTop(el){var ot=el.offsetTop;while((el=el.offsetParent) != null){ot += el.offsetTop;}return ot;}
-function AnchorPosition_getWindowOffsetTop(el){return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;}
-
-/* SOURCE FILE: date.js */
-var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
-function LZ(x){return(x<0||x>9?"":"0")+x}
-function isDate(val,format){var date=getDateFromFormat(val,format);if(date==0){return false;}return true;}
-function compareDates(date1,dateformat1,date2,dateformat2){var d1=getDateFromFormat(date1,dateformat1);var d2=getDateFromFormat(date2,dateformat2);if(d1==0 || d2==0){return -1;}else if(d1 > d2){return 1;}return 0;}
-function formatDate(date,format){format=format+"";var result="";var i_format=0;var c="";var token="";var y=date.getYear()+"";var M=date.getMonth()+1;var d=date.getDate();var E=date.getDay();var H=date.getHours();var m=date.getMinutes();var s=date.getSeconds();var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;var value=new Object();if(y.length < 4){y=""+(y-0+1900);}value["y"]=""+y;value["yyyy"]=y;value["yy"]=y.substring(2,4);value["M"]=M;value["MM"]=LZ(M);value["MMM"]=MONTH_NAMES[M-1];value["NNN"]=MONTH_NAMES[M+11];value["d"]=d;value["dd"]=LZ(d);value["E"]=DAY_NAMES[E+7];value["EE"]=DAY_NAMES[E];value["H"]=H;value["HH"]=LZ(H);if(H==0){value["h"]=12;}else if(H>12){value["h"]=H-12;}else{value["h"]=H;}value["hh"]=LZ(value["h"]);if(H>11){value["K"]=H-12;}else{value["K"]=H;}value["k"]=H+1;value["KK"]=LZ(value["K"]);value["kk"]=LZ(value["k"]);if(H > 11){value["a"]="PM";}else{value["a"]="AM";}value["m"]=m;value["mm"]=LZ(m);value["s"]=s;value["ss"]=LZ(s);while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(value[token] != null){result=result + value[token];}else{result=result + token;}}return result;}
-function _isInteger(val){var digits="1234567890";for(var i=0;i < val.length;i++){if(digits.indexOf(val.charAt(i))==-1){return false;}}return true;}
-function _getInt(str,i,minlength,maxlength){for(var x=maxlength;x>=minlength;x--){var token=str.substring(i,i+x);if(token.length < minlength){return null;}if(_isInteger(token)){return token;}}return null;}
-function getDateFromFormat(val,format){val=val+"";format=format+"";var i_val=0;var i_format=0;var c="";var token="";var token2="";var x,y;var now=new Date();var year=now.getYear();var month=now.getMonth()+1;var date=1;var hh=now.getHours();var mm=now.getMinutes();var ss=now.getSeconds();var ampm="";while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(token=="yyyy" || token=="yy" || token=="y"){if(token=="yyyy"){x=4;y=4;}if(token=="yy"){x=2;y=2;}if(token=="y"){x=2;y=4;}year=_getInt(val,i_val,x,y);if(year==null){return 0;}i_val += year.length;if(year.length==2){if(year > 70){year=1900+(year-0);}else{year=2000+(year-0);}}}else if(token=="MMM"||token=="NNN"){month=0;for(var i=0;i<MONTH_NAMES.length;i++){var month_name=MONTH_NAMES[i];if(val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()){if(token=="MMM"||(token=="NNN"&&i>11)){month=i+1;if(month>12){month -= 12;}i_val += month_name.length;break;}}}if((month < 1)||(month>12)){return 0;}}else if(token=="EE"||token=="E"){for(var i=0;i<DAY_NAMES.length;i++){var day_name=DAY_NAMES[i];if(val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()){i_val += day_name.length;break;}}}else if(token=="MM"||token=="M"){month=_getInt(val,i_val,token.length,2);if(month==null||(month<1)||(month>12)){return 0;}i_val+=month.length;}else if(token=="dd"||token=="d"){date=_getInt(val,i_val,token.length,2);if(date==null||(date<1)||(date>31)){return 0;}i_val+=date.length;}else if(token=="hh"||token=="h"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>12)){return 0;}i_val+=hh.length;}else if(token=="HH"||token=="H"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>23)){return 0;}i_val+=hh.length;}else if(token=="KK"||token=="K"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>11)){return 0;}i_val+=hh.length;}else if(token=="kk"||token=="k"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>24)){return 0;}i_val+=hh.length;hh--;}else if(token=="mm"||token=="m"){mm=_getInt(val,i_val,token.length,2);if(mm==null||(mm<0)||(mm>59)){return 0;}i_val+=mm.length;}else if(token=="ss"||token=="s"){ss=_getInt(val,i_val,token.length,2);if(ss==null||(ss<0)||(ss>59)){return 0;}i_val+=ss.length;}else if(token=="a"){if(val.substring(i_val,i_val+2).toLowerCase()=="am"){ampm="AM";}else if(val.substring(i_val,i_val+2).toLowerCase()=="pm"){ampm="PM";}else{return 0;}i_val+=2;}else{if(val.substring(i_val,i_val+token.length)!=token){return 0;}else{i_val+=token.length;}}}if(i_val != val.length){return 0;}if(month==2){if( ((year%4==0)&&(year%100 != 0) ) ||(year%400==0) ){if(date > 29){return 0;}}else{if(date > 28){return 0;}}}if((month==4)||(month==6)||(month==9)||(month==11)){if(date > 30){return 0;}}if(hh<12 && ampm=="PM"){hh=hh-0+12;}else if(hh>11 && ampm=="AM"){hh-=12;}var newdate=new Date(year,month-1,date,hh,mm,ss);return newdate.getTime();}
-function parseDate(val){var preferEuro=(arguments.length==2)?arguments[1]:false;generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');var d=null;for(var i=0;i<checkList.length;i++){var l=window[checkList[i]];for(var j=0;j<l.length;j++){d=getDateFromFormat(val,l[j]);if(d!=0){return new Date(d);}}}return null;}
-
-/* SOURCE FILE: PopupWindow.js */
-function PopupWindow_getXYPosition(anchorname){var coordinates;if(this.type == "WINDOW"){coordinates = getAnchorWindowPosition(anchorname);}else{coordinates = getAnchorPosition(anchorname);}this.x = coordinates.x;this.y = coordinates.y;}
-function PopupWindow_setSize(width,height){this.width = width;this.height = height;}
-function PopupWindow_populate(contents){this.contents = contents;this.populated = false;}
-function PopupWindow_setUrl(url){this.url = url;}
-function PopupWindow_setWindowProperties(props){this.windowProperties = props;}
-function PopupWindow_refresh(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).innerHTML = this.contents;}else if(this.use_css){document.all[this.divName].innerHTML = this.contents;}else if(this.use_layers){var d = document.layers[this.divName];d.document.open();d.document.writeln(this.contents);d.document.close();}}else{if(this.popupWindow != null && !this.popupWindow.closed){if(this.url!=""){this.popupWindow.location.href=this.url;}else{this.popupWindow.document.open();this.popupWindow.document.writeln(this.contents);this.popupWindow.document.close();}this.popupWindow.focus();}}}
-function PopupWindow_showPopup(anchorname){this.getXYPosition(anchorname);this.x += this.offsetX;this.y += this.offsetY;if(!this.populated &&(this.contents != "")){this.populated = true;this.refresh();}if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.left = this.x + "px";document.getElementById(this.divName).style.top = this.y + "px";document.getElementById(this.divName).style.visibility = "visible";}else if(this.use_css){document.all[this.divName].style.left = this.x;document.all[this.divName].style.top = this.y;document.all[this.divName].style.visibility = "visible";}else if(this.use_layers){document.layers[this.divName].left = this.x;document.layers[this.divName].top = this.y;document.layers[this.divName].visibility = "visible";}}else{if(this.popupWindow == null || this.popupWindow.closed){if(this.x<0){this.x=0;}if(this.y<0){this.y=0;}if(screen && screen.availHeight){if((this.y + this.height) > screen.availHeight){this.y = screen.availHeight - this.height;}}if(screen && screen.availWidth){if((this.x + this.width) > screen.availWidth){this.x = screen.availWidth - this.width;}}var avoidAboutBlank = window.opera ||( document.layers && !navigator.mimeTypes['*']) || navigator.vendor == 'KDE' ||( document.childNodes && !document.all && !navigator.taintEnabled);this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");}this.refresh();}}
-function PopupWindow_hidePopup(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.visibility = "hidden";}else if(this.use_css){document.all[this.divName].style.visibility = "hidden";}else if(this.use_layers){document.layers[this.divName].visibility = "hidden";}}else{if(this.popupWindow && !this.popupWindow.closed){this.popupWindow.close();this.popupWindow = null;}}}
-function PopupWindow_isClicked(e){if(this.divName != null){if(this.use_layers){var clickX = e.pageX;var clickY = e.pageY;var t = document.layers[this.divName];if((clickX > t.left) &&(clickX < t.left+t.clip.width) &&(clickY > t.top) &&(clickY < t.top+t.clip.height)){return true;}else{return false;}}else if(document.all){var t = window.event.srcElement;while(t.parentElement != null){if(t.id==this.divName){return true;}t = t.parentElement;}return false;}else if(this.use_gebi && e){var t = e.originalTarget;while(t.parentNode != null){if(t.id==this.divName){return true;}t = t.parentNode;}return false;}return false;}return false;}
-function PopupWindow_hideIfNotClicked(e){if(this.autoHideEnabled && !this.isClicked(e)){this.hidePopup();}}
-function PopupWindow_autoHide(){this.autoHideEnabled = true;}
-function PopupWindow_hidePopupWindows(e){for(var i=0;i<popupWindowObjects.length;i++){if(popupWindowObjects[i] != null){var p = popupWindowObjects[i];p.hideIfNotClicked(e);}}}
-function PopupWindow_attachListener(){if(document.layers){document.captureEvents(Event.MOUSEUP);}window.popupWindowOldEventListener = document.onmouseup;if(window.popupWindowOldEventListener != null){document.onmouseup = new Function("window.popupWindowOldEventListener();PopupWindow_hidePopupWindows();");}else{document.onmouseup = PopupWindow_hidePopupWindows;}}
-function PopupWindow(){if(!window.popupWindowIndex){window.popupWindowIndex = 0;}if(!window.popupWindowObjects){window.popupWindowObjects = new Array();}if(!window.listenerAttached){window.listenerAttached = true;PopupWindow_attachListener();}this.index = popupWindowIndex++;popupWindowObjects[this.index] = this;this.divName = null;this.popupWindow = null;this.width=0;this.height=0;this.populated = false;this.visible = false;this.autoHideEnabled = false;this.contents = "";this.url="";this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";if(arguments.length>0){this.type="DIV";this.divName = arguments[0];}else{this.type="WINDOW";}this.use_gebi = false;this.use_css = false;this.use_layers = false;if(document.getElementById){this.use_gebi = true;}else if(document.all){this.use_css = true;}else if(document.layers){this.use_layers = true;}else{this.type = "WINDOW";}this.offsetX = 0;this.offsetY = 0;this.getXYPosition = PopupWindow_getXYPosition;this.populate = PopupWindow_populate;this.setUrl = PopupWindow_setUrl;this.setWindowProperties = PopupWindow_setWindowProperties;this.refresh = PopupWindow_refresh;this.showPopup = PopupWindow_showPopup;this.hidePopup = PopupWindow_hidePopup;this.setSize = PopupWindow_setSize;this.isClicked = PopupWindow_isClicked;this.autoHide = PopupWindow_autoHide;this.hideIfNotClicked = PopupWindow_hideIfNotClicked;}
-
-
-/* SOURCE FILE: CalendarPopup.js */
-
-function CalendarPopup(){var c;if(arguments.length>0){c = new PopupWindow(arguments[0]);}else{c = new PopupWindow();c.setSize(150,175);}c.offsetX = -152;c.offsetY = 25;c.autoHide();c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");c.dayHeaders = new Array("S","M","T","W","T","F","S");c.returnFunction = "CP_tmpReturnFunction";c.returnMonthFunction = "CP_tmpReturnMonthFunction";c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";c.returnYearFunction = "CP_tmpReturnYearFunction";c.weekStartDay = 0;c.isShowYearNavigation = false;c.displayType = "date";c.disabledWeekDays = new Object();c.disabledDatesExpression = "";c.yearSelectStartOffset = 2;c.currentDate = null;c.todayText="Today";c.cssPrefix="";c.isShowNavigationDropdowns=false;c.isShowYearNavigationInput=false;window.CP_calendarObject = null;window.CP_targetInput = null;window.CP_dateFormat = "MM/dd/yyyy";c.copyMonthNamesToWindow = CP_copyMonthNamesToWindow;c.setReturnFunction = CP_setReturnFunction;c.setReturnMonthFunction = CP_setReturnMonthFunction;c.setReturnQuarterFunction = CP_setReturnQuarterFunction;c.setReturnYearFunction = CP_setReturnYearFunction;c.setMonthNames = CP_setMonthNames;c.setMonthAbbreviations = CP_setMonthAbbreviations;c.setDayHeaders = CP_setDayHeaders;c.setWeekStartDay = CP_setWeekStartDay;c.setDisplayType = CP_setDisplayType;c.setDisabledWeekDays = CP_setDisabledWeekDays;c.addDisabledDates = CP_addDisabledDates;c.setYearSelectStartOffset = CP_setYearSelectStartOffset;c.setTodayText = CP_setTodayText;c.showYearNavigation = CP_showYearNavigation;c.showCalendar = CP_showCalendar;c.hideCalendar = CP_hideCalendar;c.getStyles = getCalendarStyles;c.refreshCalendar = CP_refreshCalendar;c.getCalendar = CP_getCalendar;c.select = CP_select;c.setCssPrefix = CP_setCssPrefix;c.showNavigationDropdowns = CP_showNavigationDropdowns;c.showYearNavigationInput = CP_showYearNavigationInput;c.copyMonthNamesToWindow();return c;}
-function CP_copyMonthNamesToWindow(){if(typeof(window.MONTH_NAMES)!="undefined" && window.MONTH_NAMES!=null){window.MONTH_NAMES = new Array();for(var i=0;i<this.monthNames.length;i++){window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthNames[i];}for(var i=0;i<this.monthAbbreviations.length;i++){window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthAbbreviations[i];}}}
-function CP_tmpReturnFunction(y,m,d){if(window.CP_targetInput!=null){var dt = new Date(y,m-1,d,0,0,0);if(window.CP_calendarObject!=null){window.CP_calendarObject.copyMonthNamesToWindow();}window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);}else{alert('Use setReturnFunction() to define which function will get the clicked results!');}}
-function CP_tmpReturnMonthFunction(y,m){alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m);}
-function CP_tmpReturnQuarterFunction(y,q){alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q);}
-function CP_tmpReturnYearFunction(y){alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y);}
-function CP_setReturnFunction(name){this.returnFunction = name;}
-function CP_setReturnMonthFunction(name){this.returnMonthFunction = name;}
-function CP_setReturnQuarterFunction(name){this.returnQuarterFunction = name;}
-function CP_setReturnYearFunction(name){this.returnYearFunction = name;}
-function CP_setMonthNames(){for(var i=0;i<arguments.length;i++){this.monthNames[i] = arguments[i];}this.copyMonthNamesToWindow();}
-function CP_setMonthAbbreviations(){for(var i=0;i<arguments.length;i++){this.monthAbbreviations[i] = arguments[i];}this.copyMonthNamesToWindow();}
-function CP_setDayHeaders(){for(var i=0;i<arguments.length;i++){this.dayHeaders[i] = arguments[i];}}
-function CP_setWeekStartDay(day){this.weekStartDay = day;}
-function CP_showYearNavigation(){this.isShowYearNavigation =(arguments.length>0)?arguments[0]:true;}
-function CP_setDisplayType(type){if(type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year"){alert("Invalid display type! Must be one of: date,week-end,month,quarter,year");return false;}this.displayType=type;}
-function CP_setYearSelectStartOffset(num){this.yearSelectStartOffset=num;}
-function CP_setDisabledWeekDays(){this.disabledWeekDays = new Object();for(var i=0;i<arguments.length;i++){this.disabledWeekDays[arguments[i]] = true;}}
-function CP_addDisabledDates(start, end){if(arguments.length==1){end=start;}if(start==null && end==null){return;}if(this.disabledDatesExpression!=""){this.disabledDatesExpression+= "||";}if(start!=null){start = parseDate(start);start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}if(end!=null){end=parseDate(end);end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}if(start==null){this.disabledDatesExpression+="(ds<="+end+")";}else if(end ==null){this.disabledDatesExpression+="(ds>="+start+")";}else{this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")";}}
-function CP_setTodayText(text){this.todayText = text;}
-function CP_setCssPrefix(val){this.cssPrefix = val;}
-function CP_showNavigationDropdowns(){this.isShowNavigationDropdowns =(arguments.length>0)?arguments[0]:true;}
-function CP_showYearNavigationInput(){this.isShowYearNavigationInput =(arguments.length>0)?arguments[0]:true;}
-function CP_hideCalendar(){if(arguments.length > 0){window.popupWindowObjects[arguments[0]].hidePopup();}else{this.hidePopup();}}
-function CP_refreshCalendar(index){var calObject = window.popupWindowObjects[index];if(arguments.length>1){calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));}else{calObject.populate(calObject.getCalendar());}calObject.refresh();}
-function CP_showCalendar(anchorname){if(arguments.length>1){if(arguments[1]==null||arguments[1]==""){this.currentDate=new Date();}else{this.currentDate=new Date(parseDate(arguments[1]));}}this.populate(this.getCalendar());this.showPopup(anchorname);}
-function CP_select(inputobj, linkname, format){var selectedDate=(arguments.length>3)?arguments[3]:null;if(!window.getDateFromFormat){alert("calendar.select: To use this method you must also include 'date.js' for date formatting");return;}if(this.displayType!="date"&&this.displayType!="week-end"){alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");return;}if(inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea"){alert("calendar.select: Input object passed is not a valid form input object");window.CP_targetInput=null;return;}if(inputobj.disabled){return;}window.CP_targetInput = inputobj;window.CP_calendarObject = this;this.currentDate=null;var time=0;if(selectedDate!=null){time = getDateFromFormat(selectedDate,format)}else if(inputobj.value!=""){time = getDateFromFormat(inputobj.value,format);}if(selectedDate!=null || inputobj.value!=""){if(time==0){this.currentDate=null;}else{this.currentDate=new Date(time);}}window.CP_dateFormat = format;this.showCalendar(linkname);}
-function getCalendarStyles(){var result = "";var p = "";if(this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!=""){p=this.cssPrefix;}result += "<STYLE>\n";result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation{background-color:#C0C0C0;text-align:center;vertical-align:center;text-decoration:none;color:#000000;font-weight:bold;}\n";result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText{font-family:arial;font-size:8pt;}\n";result += "TD."+p+"cpDayColumnHeader{text-align:right;border:solid thin #C0C0C0;border-width:0px 0px 1px 0px;}\n";result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate{text-align:right;text-decoration:none;}\n";result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled{color:#D0D0D0;text-align:right;text-decoration:line-through;}\n";result += "."+p+"cpCurrentMonthDate, .cpCurrentDate{color:#000000;}\n";result += "."+p+"cpOtherMonthDate{color:#808080;}\n";result += "TD."+p+"cpCurrentDate{color:white;background-color: #C0C0C0;border-width:1px;border:solid thin #800000;}\n";result += "TD."+p+"cpCurrentDateDisabled{border-width:1px;border:solid thin #FFAAAA;}\n";result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled{border:solid thin #C0C0C0;border-width:1px 0px 0px 0px;}\n";result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled{height:20px;}\n";result += "A."+p+"cpTodayText{color:black;}\n";result += "."+p+"cpTodayTextDisabled{color:#D0D0D0;}\n";result += "."+p+"cpBorder{border:solid thin #808080;}\n";result += "</STYLE>\n";return result;}
-function CP_getCalendar(){var now = new Date();if(this.type == "WINDOW"){var windowref = "window.opener.";}else{var windowref = "";}var result = "";if(this.type == "WINDOW"){result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';}else{result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';result += '<TR><TD ALIGN=CENTER>\n';result += '<CENTER>\n';}if(this.displayType=="date" || this.displayType=="week-end"){if(this.currentDate==null){this.currentDate = now;}if(arguments.length > 0){var month = arguments[0];}else{var month = this.currentDate.getMonth()+1;}if(arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]){var year = arguments[1];}else{var year = this.currentDate.getFullYear();}var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);if( ((year%4 == 0)&&(year%100 != 0) ) ||(year%400 == 0) ){daysinmonth[2] = 29;}var current_month = new Date(year,month-1,1);var display_year = year;var display_month = month;var display_date = 1;var weekday= current_month.getDay();var offset = 0;offset =(weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;if(offset > 0){display_month--;if(display_month < 1){display_month = 12;display_year--;}display_date = daysinmonth[display_month]-offset+1;}var next_month = month+1;var next_month_year = year;if(next_month > 12){next_month=1;next_month_year++;}var last_month = month-1;var last_month_year = year;if(last_month < 1){last_month=12;last_month_year--;}var date_class;if(this.type!="WINDOW"){result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";}result += '<TR>\n';var refresh = windowref+'CP_refreshCalendar';var refreshLink = 'javascript:' + refresh;if(this.isShowNavigationDropdowns){result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="78" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpMonthNavigation" name="cpMonth" onChange="'+refresh+'('+this.index+',this.options[this.selectedIndex].value-0,'+(year-0)+');">';for( var monthCounter=1;monthCounter<=12;monthCounter++){var selected =(monthCounter==month) ? 'SELECTED' : '';result += '<option value="'+monthCounter+'" '+selected+'>'+this.monthNames[monthCounter-1]+'</option>';}result += '</select></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"> </TD>';result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="56" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpYearNavigation" name="cpYear" onChange="'+refresh+'('+this.index+','+month+',this.options[this.selectedIndex].value-0);">';for( var yearCounter=year-this.yearSelectStartOffset;yearCounter<=year+this.yearSelectStartOffset;yearCounter++){var selected =(yearCounter==year) ? 'SELECTED' : '';result += '<option value="'+yearCounter+'" '+selected+'>'+yearCounter+'</option>';}result += '</select></TD>';}else{if(this.isShowYearNavigation){result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><</A></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">></A></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"> </TD>';result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year-1)+');"><</A></TD>';if(this.isShowYearNavigationInput){result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';}else{result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';}result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year+1)+');">></A></TD>';}else{result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><<</A></TD>\n';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">>></A></TD>\n';}}result += '</TR></TABLE>\n';result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';result += '<TR>\n';for(var j=0;j<7;j++){result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';}result += '</TR>\n';for(var row=1;row<=6;row++){result += '<TR>\n';for(var col=1;col<=7;col++){var disabled=false;if(this.disabledDatesExpression!=""){var ds=""+display_year+LZ(display_month)+LZ(display_date);eval("disabled=("+this.disabledDatesExpression+")");}var dateClass = "";if((display_month == this.currentDate.getMonth()+1) &&(display_date==this.currentDate.getDate()) &&(display_year==this.currentDate.getFullYear())){dateClass = "cpCurrentDate";}else if(display_month == month){dateClass = "cpCurrentMonthDate";}else{dateClass = "cpOtherMonthDate";}if(disabled || this.disabledWeekDays[col-1]){result += ' <TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';}else{var selected_date = display_date;var selected_month = display_month;var selected_year = display_year;if(this.displayType=="week-end"){var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);d.setDate(d.getDate() +(7-col));selected_year = d.getYear();if(selected_year < 1000){selected_year += 1900;}selected_month = d.getMonth()+1;selected_date = d.getDate();}result += ' <TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';}display_date++;if(display_date > daysinmonth[display_month]){display_date=1;display_month++;}if(display_month > 12){display_month=1;display_year++;}}result += '</TR>';}var current_weekday = now.getDay() - this.weekStartDay;if(current_weekday < 0){current_weekday += 7;}result += '<TR>\n';result += ' <TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';if(this.disabledDatesExpression!=""){var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());eval("disabled=("+this.disabledDatesExpression+")");}if(disabled || this.disabledWeekDays[current_weekday+1]){result += ' <SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';}else{result += ' <A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';}result += ' <BR>\n';result += ' </TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year"){if(arguments.length > 0){var year = arguments[0];}else{if(this.displayType=="year"){var year = now.getFullYear()-this.yearSelectStartOffset;}else{var year = now.getFullYear();}}if(this.displayType!="year" && this.isShowYearNavigation){result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";result += '<TR>\n';result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');"><<</A></TD>\n';result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">>></A></TD>\n';result += '</TR></TABLE>\n';}}if(this.displayType=="month"){result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<4;i++){result += '<TR>';for(var j=0;j<3;j++){var monthindex =((i*3)+j);result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="quarter"){result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<2;i++){result += '<TR>';for(var j=0;j<2;j++){var quarter =((i*2)+j+1);result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="year"){var yearColumnSize = 4;result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";result += '<TR>\n';result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');"><<</A></TD>\n';result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">>></A></TD>\n';result += '</TR></TABLE>\n';result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<yearColumnSize;i++){for(var j=0;j<2;j++){var currentyear = year+(j*yearColumnSize)+i;result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.type == "WINDOW"){result += "</BODY></HTML>\n";}return result;}
+// HISTORY
+// ------------------------------------------------------------------
+// Feb 7, 2005: Fixed a CSS styles to use px unit
+// March 29, 2004: Added check in select() method for the form field
+// being disabled. If it is, just return and don't do anything.
+// March 24, 2004: Fixed bug - when month name and abbreviations were
+// changed, date format still used original values.
+// January 26, 2004: Added support for drop-down month and year
+// navigation (Thanks to Chris Reid for the idea)
+// September 22, 2003: Fixed a minor problem in YEAR calendar with
+// CSS prefix.
+// August 19, 2003: Renamed the function to get styles, and made it
+// work correctly without an object reference
+// August 18, 2003: Changed showYearNavigation and
+// showYearNavigationInput to optionally take an argument of
+// true or false
+// July 31, 2003: Added text input option for year navigation.
+// Added a per-calendar CSS prefix option to optionally use
+// different styles for different calendars.
+// July 29, 2003: Fixed bug causing the Today link to be clickable
+// even though today falls in a disabled date range.
+// Changed formatting to use pure CSS, allowing greater control
+// over look-and-feel options.
+// June 11, 2003: Fixed bug causing the Today link to be unselectable
+// under certain cases when some days of week are disabled
+// March 14, 2003: Added ability to disable individual dates or date
+// ranges, display as light gray and strike-through
+// March 14, 2003: Removed dependency on graypixel.gif and instead
+/// use table border coloring
+// March 12, 2003: Modified showCalendar() function to allow optional
+// start-date parameter
+// March 11, 2003: Modified select() function to allow optional
+// start-date parameter
+/*
+DESCRIPTION: This object implements a popup calendar to allow the user to
+select a date, month, quarter, or year.
+COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
+positioning errors - usually with Window positioning - occur on the
+Macintosh platform.
+The calendar can be modified to work for any location in the world by
+changing which weekday is displayed as the first column, changing the month
+names, and changing the column headers for each day.
+
+USAGE:
+// Create a new CalendarPopup object of type WINDOW
+var cal = new CalendarPopup();
+
+// Create a new CalendarPopup object of type DIV using the DIV named 'mydiv'
+var cal = new CalendarPopup('mydiv');
+
+// Easy method to link the popup calendar with an input box.
+cal.select(inputObject, anchorname, dateFormat);
+// Same method, but passing a default date other than the field's current value
+cal.select(inputObject, anchorname, dateFormat, '01/02/2000');
+// This is an example call to the popup calendar from a link to populate an
+// input box. Note that to use this, date.js must also be included!!
+<A HREF="#" onClick="cal.select(document.forms[0].date,'anchorname','MM/dd/yyyy'); return false;">Select</A>
+
+// Set the type of date select to be used. By default it is 'date'.
+cal.setDisplayType(type);
+
+// When a date, month, quarter, or year is clicked, a function is called and
+// passed the details. You must write this function, and tell the calendar
+// popup what the function name is.
+// Function to be called for 'date' select receives y, m, d
+cal.setReturnFunction(functionname);
+// Function to be called for 'month' select receives y, m
+cal.setReturnMonthFunction(functionname);
+// Function to be called for 'quarter' select receives y, q
+cal.setReturnQuarterFunction(functionname);
+// Function to be called for 'year' select receives y
+cal.setReturnYearFunction(functionname);
+
+// Show the calendar relative to a given anchor
+cal.showCalendar(anchorname);
+
+// Hide the calendar. The calendar is set to autoHide automatically
+cal.hideCalendar();
+
+// Set the month names to be used. Default are English month names
+cal.setMonthNames("January","February","March",...);
+
+// Set the month abbreviations to be used. Default are English month abbreviations
+cal.setMonthAbbreviations("Jan","Feb","Mar",...);
+
+// Show navigation for changing by the year, not just one month at a time
+cal.showYearNavigation();
+
+// Show month and year dropdowns, for quicker selection of month of dates
+cal.showNavigationDropdowns();
+
+// Set the text to be used above each day column. The days start with
+// sunday regardless of the value of WeekStartDay
+cal.setDayHeaders("S","M","T",...);
+
+// Set the day for the first column in the calendar grid. By default this
+// is Sunday (0) but it may be changed to fit the conventions of other
+// countries.
+cal.setWeekStartDay(1); // week is Monday - Sunday
+
+// Set the weekdays which should be disabled in the 'date' select popup. You can
+// then allow someone to only select week end dates, or Tuedays, for example
+cal.setDisabledWeekDays(0,1); // To disable selecting the 1st or 2nd days of the week
+
+// Selectively disable individual days or date ranges. Disabled days will not
+// be clickable, and show as strike-through text on current browsers.
+// Date format is any format recognized by parseDate() in date.js
+// Pass a single date to disable:
+cal.addDisabledDates("2003-01-01");
+// Pass null as the first parameter to mean "anything up to and including" the
+// passed date:
+cal.addDisabledDates(null, "01/02/03");
+// Pass null as the second parameter to mean "including the passed date and
+// anything after it:
+cal.addDisabledDates("Jan 01, 2003", null);
+// Pass two dates to disable all dates inbetween and including the two
+cal.addDisabledDates("January 01, 2003", "Dec 31, 2003");
+
+// When the 'year' select is displayed, set the number of years back from the
+// current year to start listing years. Default is 2.
+// This is also used for year drop-down, to decide how many years +/- to display
+cal.setYearSelectStartOffset(2);
+
+// Text for the word "Today" appearing on the calendar
+cal.setTodayText("Today");
+
+// The calendar uses CSS classes for formatting. If you want your calendar to
+// have unique styles, you can set the prefix that will be added to all the
+// classes in the output.
+// For example, normal output may have this:
+// <SPAN CLASS="cpTodayTextDisabled">Today<SPAN>
+// But if you set the prefix like this:
+cal.setCssPrefix("Test");
+// The output will then look like:
+// <SPAN CLASS="TestcpTodayTextDisabled">Today<SPAN>
+// And you can define that style somewhere in your page.
+
+// When using Year navigation, you can make the year be an input box, so
+// the user can manually change it and jump to any year
+cal.showYearNavigationInput();
+
+// Set the calendar offset to be different than the default. By default it
+// will appear just below and to the right of the anchorname. So if you have
+// a text box where the date will go and and anchor immediately after the
+// text box, the calendar will display immediately under the text box.
+cal.offsetX = 20;
+cal.offsetY = 20;
+
+NOTES:
+1) Requires the functions in AnchorPosition.js and PopupWindow.js
+
+2) Your anchor tag MUST contain both NAME and ID attributes which are the
+ same. For example:
+ <A NAME="test" ID="test"> </A>
+
+3) There must be at least a space between <A> </A> for IE5.5 to see the
+ anchor tag correctly. Do not do <A></A> with no space.
+
+4) When a CalendarPopup object is created, a handler for 'onmouseup' is
+ attached to any event handler you may have already defined. Do NOT define
+ an event handler for 'onmouseup' after you define a CalendarPopup object
+ or the autoHide() will not work correctly.
+
+5) The calendar popup display uses style sheets to make it look nice.
+
+*/
+
+// CONSTRUCTOR for the CalendarPopup Object
+function CalendarPopup() {
+ var c;
+ if (arguments.length>0) {
+ c = new PopupWindow(arguments[0]);
+ }
+ else {
+ c = new PopupWindow();
+ c.setSize(150,175);
+ }
+ c.offsetX = -152;
+ c.offsetY = 25;
+ c.autoHide();
+ // Calendar-specific properties
+ c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
+ c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
+ c.dayHeaders = new Array("S","M","T","W","T","F","S");
+ c.returnFunction = "CP_tmpReturnFunction";
+ c.returnMonthFunction = "CP_tmpReturnMonthFunction";
+ c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";
+ c.returnYearFunction = "CP_tmpReturnYearFunction";
+ c.weekStartDay = 0;
+ c.isShowYearNavigation = false;
+ c.displayType = "date";
+ c.disabledWeekDays = new Object();
+ c.disabledDatesExpression = "";
+ c.yearSelectStartOffset = 2;
+ c.currentDate = null;
+ c.todayText="Today";
+ c.cssPrefix="";
+ c.isShowNavigationDropdowns=false;
+ c.isShowYearNavigationInput=false;
+ window.CP_calendarObject = null;
+ window.CP_targetInput = null;
+ window.CP_dateFormat = "MM/dd/yyyy";
+ // Method mappings
+ c.copyMonthNamesToWindow = CP_copyMonthNamesToWindow;
+ c.setReturnFunction = CP_setReturnFunction;
+ c.setReturnMonthFunction = CP_setReturnMonthFunction;
+ c.setReturnQuarterFunction = CP_setReturnQuarterFunction;
+ c.setReturnYearFunction = CP_setReturnYearFunction;
+ c.setMonthNames = CP_setMonthNames;
+ c.setMonthAbbreviations = CP_setMonthAbbreviations;
+ c.setDayHeaders = CP_setDayHeaders;
+ c.setWeekStartDay = CP_setWeekStartDay;
+ c.setDisplayType = CP_setDisplayType;
+ c.setDisabledWeekDays = CP_setDisabledWeekDays;
+ c.addDisabledDates = CP_addDisabledDates;
+ c.setYearSelectStartOffset = CP_setYearSelectStartOffset;
+ c.setTodayText = CP_setTodayText;
+ c.showYearNavigation = CP_showYearNavigation;
+ c.showCalendar = CP_showCalendar;
+ c.hideCalendar = CP_hideCalendar;
+ c.getStyles = getCalendarStyles;
+ c.refreshCalendar = CP_refreshCalendar;
+ c.getCalendar = CP_getCalendar;
+ c.select = CP_select;
+ c.setCssPrefix = CP_setCssPrefix;
+ c.showNavigationDropdowns = CP_showNavigationDropdowns;
+ c.showYearNavigationInput = CP_showYearNavigationInput;
+ c.copyMonthNamesToWindow();
+ // Return the object
+ return c;
+ }
+function CP_copyMonthNamesToWindow() {
+ // Copy these values over to the date.js
+ if (typeof(window.MONTH_NAMES)!="undefined" && window.MONTH_NAMES!=null) {
+ window.MONTH_NAMES = new Array();
+ for (var i=0; i<this.monthNames.length; i++) {
+ window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthNames[i];
+ }
+ for (var i=0; i<this.monthAbbreviations.length; i++) {
+ window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthAbbreviations[i];
+ }
+ }
+}
+// Temporary default functions to be called when items clicked, so no error is thrown
+function CP_tmpReturnFunction(y,m,d) {
+ if (window.CP_targetInput!=null) {
+ var dt = new Date(y,m-1,d,0,0,0);
+ if (window.CP_calendarObject!=null) { window.CP_calendarObject.copyMonthNamesToWindow(); }
+ window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);
+ }
+ else {
+ alert('Use setReturnFunction() to define which function will get the clicked results!');
+ }
+ }
+function CP_tmpReturnMonthFunction(y,m) {
+ alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m);
+ }
+function CP_tmpReturnQuarterFunction(y,q) {
+ alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q);
+ }
+function CP_tmpReturnYearFunction(y) {
+ alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y);
+ }
+
+// Set the name of the functions to call to get the clicked item
+function CP_setReturnFunction(name) { this.returnFunction = name; }
+function CP_setReturnMonthFunction(name) { this.returnMonthFunction = name; }
+function CP_setReturnQuarterFunction(name) { this.returnQuarterFunction = name; }
+function CP_setReturnYearFunction(name) { this.returnYearFunction = name; }
+
+// Over-ride the built-in month names
+function CP_setMonthNames() {
+ for (var i=0; i<arguments.length; i++) { this.monthNames[i] = arguments[i]; }
+ this.copyMonthNamesToWindow();
+ }
+
+// Over-ride the built-in month abbreviations
+function CP_setMonthAbbreviations() {
+ for (var i=0; i<arguments.length; i++) { this.monthAbbreviations[i] = arguments[i]; }
+ this.copyMonthNamesToWindow();
+ }
+
+// Over-ride the built-in column headers for each day
+function CP_setDayHeaders() {
+ for (var i=0; i<arguments.length; i++) { this.dayHeaders[i] = arguments[i]; }
+ }
+
+// Set the day of the week (0-7) that the calendar display starts on
+// This is for countries other than the US whose calendar displays start on Monday(1), for example
+function CP_setWeekStartDay(day) { this.weekStartDay = day; }
+
+// Show next/last year navigation links
+function CP_showYearNavigation() { this.isShowYearNavigation = (arguments.length>0)?arguments[0]:true; }
+
+// Which type of calendar to display
+function CP_setDisplayType(type) {
+ if (type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year") { alert("Invalid display type! Must be one of: date,week-end,month,quarter,year"); return false; }
+ this.displayType=type;
+ }
+
+// How many years back to start by default for year display
+function CP_setYearSelectStartOffset(num) { this.yearSelectStartOffset=num; }
+
+// Set which weekdays should not be clickable
+function CP_setDisabledWeekDays() {
+ this.disabledWeekDays = new Object();
+ for (var i=0; i<arguments.length; i++) { this.disabledWeekDays[arguments[i]] = true; }
+ }
+
+// Disable individual dates or ranges
+// Builds an internal logical test which is run via eval() for efficiency
+function CP_addDisabledDates(start, end) {
+ if (arguments.length==1) { end=start; }
+ if (start==null && end==null) { return; }
+ if (this.disabledDatesExpression!="") { this.disabledDatesExpression+= "||"; }
+ if (start!=null) { start = parseDate(start); start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}
+ if (end!=null) { end=parseDate(end); end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}
+ if (start==null) { this.disabledDatesExpression+="(ds<="+end+")"; }
+ else if (end ==null) { this.disabledDatesExpression+="(ds>="+start+")"; }
+ else { this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")"; }
+ }
+
+// Set the text to use for the "Today" link
+function CP_setTodayText(text) {
+ this.todayText = text;
+ }
+
+// Set the prefix to be added to all CSS classes when writing output
+function CP_setCssPrefix(val) {
+ this.cssPrefix = val;
+ }
+
+// Show the navigation as an dropdowns that can be manually changed
+function CP_showNavigationDropdowns() { this.isShowNavigationDropdowns = (arguments.length>0)?arguments[0]:true; }
+
+// Show the year navigation as an input box that can be manually changed
+function CP_showYearNavigationInput() { this.isShowYearNavigationInput = (arguments.length>0)?arguments[0]:true; }
+
+// Hide a calendar object
+function CP_hideCalendar() {
+ if (arguments.length > 0) { window.popupWindowObjects[arguments[0]].hidePopup(); }
+ else { this.hidePopup(); }
+ bcfg2_check_date();
+ }
+
+// Refresh the contents of the calendar display
+function CP_refreshCalendar(index) {
+ var calObject = window.popupWindowObjects[index];
+ if (arguments.length>1) {
+ calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));
+ }
+ else {
+ calObject.populate(calObject.getCalendar());
+ }
+ calObject.refresh();
+ }
+
+// Populate the calendar and display it
+function CP_showCalendar(anchorname) {
+ if (arguments.length>1) {
+ if (arguments[1]==null||arguments[1]=="") {
+ this.currentDate=new Date();
+ }
+ else {
+ this.currentDate=new Date(parseDate(arguments[1]));
+ }
+ }
+ this.populate(this.getCalendar());
+ this.showPopup(anchorname);
+ }
+
+// Simple method to interface popup calendar with a text-entry box
+function CP_select(inputobj, linkname, format) {
+ var selectedDate=(arguments.length>3)?arguments[3]:null;
+ if (!window.getDateFromFormat) {
+ alert("calendar.select: To use this method you must also include 'date.js' for date formatting");
+ return;
+ }
+ if (this.displayType!="date"&&this.displayType!="week-end") {
+ alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");
+ return;
+ }
+ if (inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea") {
+ alert("calendar.select: Input object passed is not a valid form input object");
+ window.CP_targetInput=null;
+ return;
+ }
+ if (inputobj.disabled) { return; } // Can't use calendar input on disabled form input!
+ window.CP_targetInput = inputobj;
+ window.CP_calendarObject = this;
+ this.currentDate=null;
+ var time=0;
+ if (selectedDate!=null) {
+ time = getDateFromFormat(selectedDate,format)
+ }
+ else if (inputobj.value!="") {
+ time = getDateFromFormat(inputobj.value,format);
+ }
+ if (selectedDate!=null || inputobj.value!="") {
+ if (time==0) { this.currentDate=null; }
+ else { this.currentDate=new Date(time); }
+ }
+ window.CP_dateFormat = format;
+ this.showCalendar(linkname);
+ }
+
+// Get style block needed to display the calendar correctly
+function getCalendarStyles() {
+ var result = "";
+ var p = "";
+ if (this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!="") { p=this.cssPrefix; }
+ result += "<STYLE>\n";
+ result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation { background-color:#C0C0C0; text-align:center; vertical-align:center; text-decoration:none; color:#000000; font-weight:bold; }\n";
+ result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText { font-family:arial; font-size:8pt; }\n";
+ result += "TD."+p+"cpDayColumnHeader { text-align:right; border:solid thin #C0C0C0;border-width:0px 0px 1px 0px; }\n";
+ result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate { text-align:right; text-decoration:none; }\n";
+ result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled { color:#D0D0D0; text-align:right; text-decoration:line-through; }\n";
+ result += "."+p+"cpCurrentMonthDate, .cpCurrentDate { color:#000000; }\n";
+ result += "."+p+"cpOtherMonthDate { color:#808080; }\n";
+ result += "TD."+p+"cpCurrentDate { color:white; background-color: #C0C0C0; border-width:1px; border:solid thin #800000; }\n";
+ result += "TD."+p+"cpCurrentDateDisabled { border-width:1px; border:solid thin #FFAAAA; }\n";
+ result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled { border:solid thin #C0C0C0; border-width:1px 0px 0px 0px;}\n";
+ result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled { height:20px; }\n";
+ result += "A."+p+"cpTodayText { color:black; }\n";
+ result += "."+p+"cpTodayTextDisabled { color:#D0D0D0; }\n";
+ result += "."+p+"cpBorder { border:solid thin #808080; }\n";
+ result += "</STYLE>\n";
+ return result;
+ }
+
+// Return a string containing all the calendar code to be displayed
+function CP_getCalendar() {
+ var now = new Date();
+ // Reference to window
+ if (this.type == "WINDOW") { var windowref = "window.opener."; }
+ else { var windowref = ""; }
+ var result = "";
+ // If POPUP, write entire HTML document
+ if (this.type == "WINDOW") {
+ result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";
+ result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';
+ }
+ else {
+ result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';
+ result += '<TR><TD ALIGN=CENTER>\n';
+ result += '<CENTER>\n';
+ }
+ // Code for DATE display (default)
+ // -------------------------------
+ if (this.displayType=="date" || this.displayType=="week-end") {
+ if (this.currentDate==null) { this.currentDate = now; }
+ if (arguments.length > 0) { var month = arguments[0]; }
+ else { var month = this.currentDate.getMonth()+1; }
+ if (arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]) { var year = arguments[1]; }
+ else { var year = this.currentDate.getFullYear(); }
+ var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
+ if ( ( (year%4 == 0)&&(year%100 != 0) ) || (year%400 == 0) ) {
+ daysinmonth[2] = 29;
+ }
+ var current_month = new Date(year,month-1,1);
+ var display_year = year;
+ var display_month = month;
+ var display_date = 1;
+ var weekday= current_month.getDay();
+ var offset = 0;
+
+ offset = (weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;
+ if (offset > 0) {
+ display_month--;
+ if (display_month < 1) { display_month = 12; display_year--; }
+ display_date = daysinmonth[display_month]-offset+1;
+ }
+ var next_month = month+1;
+ var next_month_year = year;
+ if (next_month > 12) { next_month=1; next_month_year++; }
+ var last_month = month-1;
+ var last_month_year = year;
+ if (last_month < 1) { last_month=12; last_month_year--; }
+ var date_class;
+ if (this.type!="WINDOW") {
+ result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
+ }
+ result += '<TR>\n';
+ var refresh = windowref+'CP_refreshCalendar';
+ var refreshLink = 'javascript:' + refresh;
+ if (this.isShowNavigationDropdowns) {
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="78" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpMonthNavigation" name="cpMonth" onChange="'+refresh+'('+this.index+',this.options[this.selectedIndex].value-0,'+(year-0)+');">';
+ for( var monthCounter=1; monthCounter<=12; monthCounter++ ) {
+ var selected = (monthCounter==month) ? 'SELECTED' : '';
+ result += '<option value="'+monthCounter+'" '+selected+'>'+this.monthNames[monthCounter-1]+'</option>';
+ }
+ result += '</select></TD>';
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"> </TD>';
+
+ result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="56" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpYearNavigation" name="cpYear" onChange="'+refresh+'('+this.index+','+month+',this.options[this.selectedIndex].value-0);">';
+ for( var yearCounter=year-this.yearSelectStartOffset; yearCounter<=year+this.yearSelectStartOffset; yearCounter++ ) {
+ var selected = (yearCounter==year) ? 'SELECTED' : '';
+ result += '<option value="'+yearCounter+'" '+selected+'>'+yearCounter+'</option>';
+ }
+ result += '</select></TD>';
+ }
+ else {
+ if (this.isShowYearNavigation) {
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><</A></TD>';
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">></A></TD>';
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"> </TD>';
+
+ result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year-1)+');"><</A></TD>';
+ if (this.isShowYearNavigationInput) {
+ result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';
+ }
+ else {
+ result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';
+ }
+ result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year+1)+');">></A></TD>';
+ }
+ else {
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');"><<</A></TD>\n';
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';
+ result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">>></A></TD>\n';
+ }
+ }
+ result += '</TR></TABLE>\n';
+ result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';
+ result += '<TR>\n';
+ for (var j=0; j<7; j++) {
+
+ result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';
+ }
+ result += '</TR>\n';
+ for (var row=1; row<=6; row++) {
+ result += '<TR>\n';
+ for (var col=1; col<=7; col++) {
+ var disabled=false;
+ if (this.disabledDatesExpression!="") {
+ var ds=""+display_year+LZ(display_month)+LZ(display_date);
+ eval("disabled=("+this.disabledDatesExpression+")");
+ }
+ var dateClass = "";
+ if ((display_month == this.currentDate.getMonth()+1) && (display_date==this.currentDate.getDate()) && (display_year==this.currentDate.getFullYear())) {
+ dateClass = "cpCurrentDate";
+ }
+ else if (display_month == month) {
+ dateClass = "cpCurrentMonthDate";
+ }
+ else {
+ dateClass = "cpOtherMonthDate";
+ }
+ if (disabled || this.disabledWeekDays[col-1]) {
+ result += ' <TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';
+ }
+ else {
+ var selected_date = display_date;
+ var selected_month = display_month;
+ var selected_year = display_year;
+ if (this.displayType=="week-end") {
+ var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);
+ d.setDate(d.getDate() + (7-col));
+ selected_year = d.getYear();
+ if (selected_year < 1000) { selected_year += 1900; }
+ selected_month = d.getMonth()+1;
+ selected_date = d.getDate();
+ }
+ result += ' <TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';
+ }
+ display_date++;
+ if (display_date > daysinmonth[display_month]) {
+ display_date=1;
+ display_month++;
+ }
+ if (display_month > 12) {
+ display_month=1;
+ display_year++;
+ }
+ }
+ result += '</TR>';
+ }
+ var current_weekday = now.getDay() - this.weekStartDay;
+ if (current_weekday < 0) {
+ current_weekday += 7;
+ }
+ result += '<TR>\n';
+ result += ' <TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';
+ if (this.disabledDatesExpression!="") {
+ var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());
+ eval("disabled=("+this.disabledDatesExpression+")");
+ }
+ if (disabled || this.disabledWeekDays[current_weekday+1]) {
+ result += ' <SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';
+ }
+ else {
+ result += ' <A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';
+ }
+ result += ' <BR>\n';
+ result += ' </TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';
+ }
+
+ // Code common for MONTH, QUARTER, YEAR
+ // ------------------------------------
+ if (this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year") {
+ if (arguments.length > 0) { var year = arguments[0]; }
+ else {
+ if (this.displayType=="year") { var year = now.getFullYear()-this.yearSelectStartOffset; }
+ else { var year = now.getFullYear(); }
+ }
+ if (this.displayType!="year" && this.isShowYearNavigation) {
+ result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
+ result += '<TR>\n';
+ result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');"><<</A></TD>\n';
+ result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';
+ result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">>></A></TD>\n';
+ result += '</TR></TABLE>\n';
+ }
+ }
+
+ // Code for MONTH display
+ // ----------------------
+ if (this.displayType=="month") {
+ // If POPUP, write entire HTML document
+ result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
+ for (var i=0; i<4; i++) {
+ result += '<TR>';
+ for (var j=0; j<3; j++) {
+ var monthindex = ((i*3)+j);
+ result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';
+ }
+ result += '</TR>';
+ }
+ result += '</TABLE></CENTER></TD></TR></TABLE>\n';
+ }
+
+ // Code for QUARTER display
+ // ------------------------
+ if (this.displayType=="quarter") {
+ result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';
+ for (var i=0; i<2; i++) {
+ result += '<TR>';
+ for (var j=0; j<2; j++) {
+ var quarter = ((i*2)+j+1);
+ result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';
+ }
+ result += '</TR>';
+ }
+ result += '</TABLE></CENTER></TD></TR></TABLE>\n';
+ }
+
+ // Code for YEAR display
+ // ---------------------
+ if (this.displayType=="year") {
+ var yearColumnSize = 4;
+ result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
+ result += '<TR>\n';
+ result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');"><<</A></TD>\n';
+ result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">>></A></TD>\n';
+ result += '</TR></TABLE>\n';
+ result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
+ for (var i=0; i<yearColumnSize; i++) {
+ for (var j=0; j<2; j++) {
+ var currentyear = year+(j*yearColumnSize)+i;
+ result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';
+ }
+ result += '</TR>';
+ }
+ result += '</TABLE></CENTER></TD></TR></TABLE>\n';
+ }
+ // Common
+ if (this.type == "WINDOW") {
+ result += "</BODY></HTML>\n";
+ }
+ return result;
+ }
diff --git a/reports/site_media/PopupWindow.js b/reports/site_media/PopupWindow.js new file mode 100644 index 000000000..5a5823590 --- /dev/null +++ b/reports/site_media/PopupWindow.js @@ -0,0 +1,336 @@ +// =================================================================== +// Author: Matt Kruse <matt@mattkruse.com> +// WWW: http://www.mattkruse.com/ +// +// NOTICE: You may use this code for any purpose, commercial or +// private, without any further permission from the author. You may +// remove this notice from your final code if you wish, however it is +// appreciated by the author if at least my web site address is kept. +// +// You may *NOT* re-distribute this code in any way except through its +// use. That means, you can include it in your product, or your web +// site, or any other form where the code is actually being used. You +// may not put the plain javascript up on your site for download or +// include it in your javascript libraries for download. +// If you wish to share this code with others, please just point them +// to the URL instead. +// Please DO NOT link directly to my .js files from your site. Copy +// the files to your server and use them there. Thank you. +// =================================================================== + +/* +PopupWindow.js +Author: Matt Kruse +Last modified: 02/16/04 + +DESCRIPTION: This object allows you to easily and quickly popup a window +in a certain place. The window can either be a DIV or a separate browser +window. + +COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small +positioning errors - usually with Window positioning - occur on the +Macintosh platform. Due to bugs in Netscape 4.x, populating the popup +window with <STYLE> tags may cause errors. + +USAGE: +// Create an object for a WINDOW popup +var win = new PopupWindow(); + +// Create an object for a DIV window using the DIV named 'mydiv' +var win = new PopupWindow('mydiv'); + +// Set the window to automatically hide itself when the user clicks +// anywhere else on the page except the popup +win.autoHide(); + +// Show the window relative to the anchor name passed in +win.showPopup(anchorname); + +// Hide the popup +win.hidePopup(); + +// Set the size of the popup window (only applies to WINDOW popups +win.setSize(width,height); + +// Populate the contents of the popup window that will be shown. If you +// change the contents while it is displayed, you will need to refresh() +win.populate(string); + +// set the URL of the window, rather than populating its contents +// manually +win.setUrl("http://www.site.com/"); + +// Refresh the contents of the popup +win.refresh(); + +// Specify how many pixels to the right of the anchor the popup will appear +win.offsetX = 50; + +// Specify how many pixels below the anchor the popup will appear +win.offsetY = 100; + +NOTES: +1) Requires the functions in AnchorPosition.js + +2) Your anchor tag MUST contain both NAME and ID attributes which are the + same. For example: + <A NAME="test" ID="test"> </A> + +3) There must be at least a space between <A> </A> for IE5.5 to see the + anchor tag correctly. Do not do <A></A> with no space. + +4) When a PopupWindow object is created, a handler for 'onmouseup' is + attached to any event handler you may have already defined. Do NOT define + an event handler for 'onmouseup' after you define a PopupWindow object or + the autoHide() will not work correctly. +*/ + +// Set the position of the popup window based on the anchor +function PopupWindow_getXYPosition(anchorname) { + var coordinates; + if (this.type == "WINDOW") { + coordinates = getAnchorWindowPosition(anchorname); + } + else { + coordinates = getAnchorPosition(anchorname); + } + this.x = coordinates.x; + this.y = coordinates.y; + } +// Set width/height of DIV/popup window +function PopupWindow_setSize(width,height) { + this.width = width; + this.height = height; + } +// Fill the window with contents +function PopupWindow_populate(contents) { + this.contents = contents; + this.populated = false; + } +// Set the URL to go to +function PopupWindow_setUrl(url) { + this.url = url; + } +// Set the window popup properties +function PopupWindow_setWindowProperties(props) { + this.windowProperties = props; + } +// Refresh the displayed contents of the popup +function PopupWindow_refresh() { + if (this.divName != null) { + // refresh the DIV object + if (this.use_gebi) { + document.getElementById(this.divName).innerHTML = this.contents; + } + else if (this.use_css) { + document.all[this.divName].innerHTML = this.contents; + } + else if (this.use_layers) { + var d = document.layers[this.divName]; + d.document.open(); + d.document.writeln(this.contents); + d.document.close(); + } + } + else { + if (this.popupWindow != null && !this.popupWindow.closed) { + if (this.url!="") { + this.popupWindow.location.href=this.url; + } + else { + this.popupWindow.document.open(); + this.popupWindow.document.writeln(this.contents); + this.popupWindow.document.close(); + } + this.popupWindow.focus(); + } + } + } +// Position and show the popup, relative to an anchor object +function PopupWindow_showPopup(anchorname) { + this.getXYPosition(anchorname); + this.x += this.offsetX; + this.y += this.offsetY; + if (!this.populated && (this.contents != "")) { + this.populated = true; + this.refresh(); + } + if (this.divName != null) { + // Show the DIV object + if (this.use_gebi) { + document.getElementById(this.divName).style.left = this.x + "px"; + document.getElementById(this.divName).style.top = this.y + "px"; + document.getElementById(this.divName).style.visibility = "visible"; + } + else if (this.use_css) { + document.all[this.divName].style.left = this.x; + document.all[this.divName].style.top = this.y; + document.all[this.divName].style.visibility = "visible"; + } + else if (this.use_layers) { + document.layers[this.divName].left = this.x; + document.layers[this.divName].top = this.y; + document.layers[this.divName].visibility = "visible"; + } + } + else { + if (this.popupWindow == null || this.popupWindow.closed) { + // If the popup window will go off-screen, move it so it doesn't + if (this.x<0) { this.x=0; } + if (this.y<0) { this.y=0; } + if (screen && screen.availHeight) { + if ((this.y + this.height) > screen.availHeight) { + this.y = screen.availHeight - this.height; + } + } + if (screen && screen.availWidth) { + if ((this.x + this.width) > screen.availWidth) { + this.x = screen.availWidth - this.width; + } + } + var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ); + this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+""); + } + this.refresh(); + } + } +// Hide the popup +function PopupWindow_hidePopup() { + if (this.divName != null) { + if (this.use_gebi) { + document.getElementById(this.divName).style.visibility = "hidden"; + } + else if (this.use_css) { + document.all[this.divName].style.visibility = "hidden"; + } + else if (this.use_layers) { + document.layers[this.divName].visibility = "hidden"; + } + } + else { + if (this.popupWindow && !this.popupWindow.closed) { + this.popupWindow.close(); + this.popupWindow = null; + } + } + } +// Pass an event and return whether or not it was the popup DIV that was clicked +function PopupWindow_isClicked(e) { + if (this.divName != null) { + if (this.use_layers) { + var clickX = e.pageX; + var clickY = e.pageY; + var t = document.layers[this.divName]; + if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) { + return true; + } + else { return false; } + } + else if (document.all) { // Need to hard-code this to trap IE for error-handling + var t = window.event.srcElement; + while (t.parentElement != null) { + if (t.id==this.divName) { + return true; + } + t = t.parentElement; + } + return false; + } + else if (this.use_gebi && e) { + var t = e.originalTarget; + while (t.parentNode != null) { + if (t.id==this.divName) { + return true; + } + t = t.parentNode; + } + return false; + } + return false; + } + return false; + } + +// Check an onMouseDown event to see if we should hide +function PopupWindow_hideIfNotClicked(e) { + if (this.autoHideEnabled && !this.isClicked(e)) { + this.hidePopup(); + } + } +// Call this to make the DIV disable automatically when mouse is clicked outside it +function PopupWindow_autoHide() { + this.autoHideEnabled = true; + } +// This global function checks all PopupWindow objects onmouseup to see if they should be hidden +function PopupWindow_hidePopupWindows(e) { + for (var i=0; i<popupWindowObjects.length; i++) { + if (popupWindowObjects[i] != null) { + var p = popupWindowObjects[i]; + p.hideIfNotClicked(e); + } + } + } +// Run this immediately to attach the event listener +function PopupWindow_attachListener() { + if (document.layers) { + document.captureEvents(Event.MOUSEUP); + } + window.popupWindowOldEventListener = document.onmouseup; + if (window.popupWindowOldEventListener != null) { + document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();"); + } + else { + document.onmouseup = PopupWindow_hidePopupWindows; + } + } +// CONSTRUCTOR for the PopupWindow object +// Pass it a DIV name to use a DHTML popup, otherwise will default to window popup +function PopupWindow() { + if (!window.popupWindowIndex) { window.popupWindowIndex = 0; } + if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); } + if (!window.listenerAttached) { + window.listenerAttached = true; + PopupWindow_attachListener(); + } + this.index = popupWindowIndex++; + popupWindowObjects[this.index] = this; + this.divName = null; + this.popupWindow = null; + this.width=0; + this.height=0; + this.populated = false; + this.visible = false; + this.autoHideEnabled = false; + + this.contents = ""; + this.url=""; + this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no"; + if (arguments.length>0) { + this.type="DIV"; + this.divName = arguments[0]; + } + else { + this.type="WINDOW"; + } + this.use_gebi = false; + this.use_css = false; + this.use_layers = false; + if (document.getElementById) { this.use_gebi = true; } + else if (document.all) { this.use_css = true; } + else if (document.layers) { this.use_layers = true; } + else { this.type = "WINDOW"; } + this.offsetX = 0; + this.offsetY = 0; + // Method mappings + this.getXYPosition = PopupWindow_getXYPosition; + this.populate = PopupWindow_populate; + this.setUrl = PopupWindow_setUrl; + this.setWindowProperties = PopupWindow_setWindowProperties; + this.refresh = PopupWindow_refresh; + this.showPopup = PopupWindow_showPopup; + this.hidePopup = PopupWindow_hidePopup; + this.setSize = PopupWindow_setSize; + this.isClicked = PopupWindow_isClicked; + this.autoHide = PopupWindow_autoHide; + this.hideIfNotClicked = PopupWindow_hideIfNotClicked; + } diff --git a/reports/site_media/base.css b/reports/site_media/base.css deleted file mode 100644 index ddbf02165..000000000 --- a/reports/site_media/base.css +++ /dev/null @@ -1,5 +0,0 @@ - -/* Import other styles */ -@import url('global.css'); -@import url('layout.css'); -@import url('boxypastel.css'); diff --git a/reports/site_media/bcfg2.js b/reports/site_media/bcfg2.js new file mode 100644 index 000000000..962815c32 --- /dev/null +++ b/reports/site_media/bcfg2.js @@ -0,0 +1,26 @@ +function hide_table_array(ar) { + for(i=0; i < ar.length; i++) { + toggleMe(ar[i]); + }; +} +function clientdetailload() { + toggleMe('bad_table'); + toggleMe('modified_table'); + toggleMe('extra_table'); +} +function toggleMe(elementId) { + element = document.getElementById(elementId); + if (element) { + element.style.display = (element.style.display != 'none' ? 'none' : ''); + } +} +function pageJump(elementId) { + url = ''; + element = document.getElementById(elementId); + if (element) { + url = element.value; + } + if (url) { + location.href = url; + } +} diff --git a/reports/site_media/bcfg2_base.css b/reports/site_media/bcfg2_base.css new file mode 100644 index 000000000..daa6538f1 --- /dev/null +++ b/reports/site_media/bcfg2_base.css @@ -0,0 +1,244 @@ +body { + margin: 0; + padding: 0; + color: #383838; + font-family: verdana,Arial,Helvetica; +} +a { + color: #383838; + text-decoration: none; +} +a:visited a:active { + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +img { + border: 0; +} + +#header { + width: 100%; + height: 115px; + position: relative; + color: #000000; + background-color: #F2F2F2; + border-bottom: 1px solid #98DBCC; +} +div.page_name { + color: #383838; + position: relative; + border-bottom: 1px solid #98DBCC; + border-left: 1px solid #98DBCC; +} +.page_name h1 { + font-size: 125%; + color: #20435C; + margin: 0; + padding: 6px 0 3px 10px; + font-weight: normal; +} +#footer { + text-align: center; + width: 100%; + color: #11303d; + border-top: 1px solid #98DBCC; + font-size: 12px; + padding: 5px 0 5px 0; +} + +#document { +} + +#sidemenucontainer { + float:left; + margin-left: -100%; + width: 200px; + color: #383838; +} +#sidemenu { + padding: 10px 5px 0 10px; + font-size: 90%; +} +#sidemenu a { + color: #383838; + text-decoration: none; +} +#sidemenu a:visited a:active { + color: #383838; +} +#sidemenu a:hover { + text-decoration: underline; +} +#sidemenu ul { + padding: 0; + margin-top: 0; + margin-bottom: 0; +} +ul.menu-level1 { + margin: 10px; + list-style-type: none; +} +ul.menu-level2 { + margin-left: 30px; + list-style-type: circle; +} +#contentwrapper { + margin: 0 0 0 200px; + background: #ffffff; + min-width: 750px; +} +#content { + float: left; + width: 100%; +} +#content a:hover { + text-decoration: underline; +} +#timepiece { + margin-right: 30px; + font-size: 90%; + position: absolute; + bottom: 0px; + right: 0px; +} + +.dirty-lineitem { + background: #FFAAAA; +} +.dirty-lineitem a { + color: #10324b; + text-decoration: none; +} +.clean-lineitem { + background: #AAFFBB; +} +.clean-lineitem a { + color: #10324b; + text-decoration: none; +} +.modified-lineitem { + background: #FFEC8B; +} +.extra-lineitem { + background: #63B8FF; +} + +table.grid-view { + border: solid 1px #98DBCC; + margin: 12px auto; + font-size: 90%; +} +.grid-view td { + padding: 2px 5px; +} + +.listview { + padding-top:3px; + padding-bottom:3px; +} +.listview_alt { + background:#F2F2F2; + padding-top:3px; + padding-bottom:3px; +} + +.detail_wrapper { + margin: 15px 0 15px 15px; +} +.detail_header { + border-bottom: 1px solid #98DBCC; + margin-bottom: 10px; +} +.detail_wrapper h2 { + font-size:125%; + font-weight:normal; + display: inline; +} +.detail_wrapper h3 { + font-size:100%; + font-weight:bold; + display: inline; +} + +div.entry_list { + border: 1px solid #98DBCC; + margin-top: 5px; + width: 650px; +} +div.entry_list_head { + padding: 5px; +} +div.entry_list h3 { + font-size: 100%; + font-weight: bold; + margin: 0; + padding: 0; + display: inline; +} +table.entry_list { + margin: 0; + padding: 5px 10px; + //border-top: solid 1px #98DBCC; + font-size: 90%; + width: 100%; +} +table.entry_list td { + padding-right: 10px; +} +td.entry_list_type { + width: 20%; +} +.entry_expand_tab { + float: right; + margin-top: -2px; +} +.entry_expand_tab:hover { + cursor: pointer; +} + +div.note-box { + margin-left: 20px; + margin-right: 20px; + padding: 3px; + border: solid 1px #98DBCC; + font-size: 80%; + font-style: italic; + background: #FCF6CF; +} +div.client_list_box { + font-size: 85%; +} +div.recent_history_box { + font-size: 90%; + padding: 0 10px; +} +#table_list_header { + font-weight: bold; +} +#table_list_header td { + border-bottom:1px solid #98DBCC; +} +div.warningbox { + margin: 10px 0; + padding: 5px 10px; + border:1px solid #98DBCC; + background: #FFEC8B; + font-weight: bold; + font-size: 90%; +} +div.recent_history_wrapper { + border: none; +} +div.page_bar { + padding: 0 20px; +} +div.filter_bar { + padding: 0 20px; +} +span.nav_bar_current { + font-size: 90%; + border: 1px solid #98DBCC; + padding: 1px; +} diff --git a/reports/site_media/boxypastel.css b/reports/site_media/boxypastel.css deleted file mode 100644 index 4ec296f4d..000000000 --- a/reports/site_media/boxypastel.css +++ /dev/null @@ -1,230 +0,0 @@ -/* body */ -/*body {*/ -/* background-color: #fff;*/ -/* color: #000;*/ -/* font: 12px 'Lucida Grande', Arial, Helvetica, sans-serif;*/ -/* margin-left:25px;*/ -/* margin-right:100px;*/ -/* }*/ - - - -/* links */ -a:link { - color: #00f; - text-decoration: none; - } -a:visited { - color: #00a; - text-decoration: none; - } -a:hover { - color: #00a; - text-decoration: underline; - } -a:active { - color: #00a; - text-decoration: underline; - } -/* divs*/ -div.bad { - border: 1px solid #660000; - background: #FF6A6A; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.modified { - border: 1px solid #CC9900; - background: #FFEC8B; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.clean { - border: 1px solid #006600; - background: #9AFF9A; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.extra { - border: 1px solid #006600; - background: #6699CC; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.warning { - border: 1px solid #CC3300; - background: #FF9933; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.all-warning { - border: 1px solid #DD5544; - background: #FFD9A2; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.down { - border: 1px solid #999; - background-color: #DDD; - margin: 10px 0; - padding: 8px; - text-align: left; - margin-left:50px; - margin-right:50px; - } -div.items { - display: none; - } -div.nodebox { - border: 1px solid #c7cfd5; - background: #f1f5f9; - margin: 20px 0; - padding: 8px 8px 16px 8px; - text-align: left; - position:relative; - } -/*Divs For Statusbar*/ -div.redbar { - border: 0px solid #660000; - background: #FF6666; - margin: 0px; - float: left; - } - -div.greenbar { - border: 0px solid #006600; - background: #66FF66; - margin: 0px; - float: left; - } -div.statusborder { - border: 1px solid #000000; - background: #FF6666; - margin: 0px; - float: right; - width: 100%; - } - /*invisitable*/ -table.invisitable { - width: 100%; - border: 0px; - cell-padding: 0px; - padding: 0px; - border-width: 0px; - } -/*Spans*/ -span.nodename { - font-style: italic; - } -span.nodelisttitle { - font-size: 14px; - } -span.mini-date { - font-size: 10px; - right: 65px; - } - - -div.dirty-lineitem { - background: #FF6A6A; - width:100%; - } -div.modified-lineitem { - background: #FFEC8B; - } -div.clean-lineitem { - background: #9AFF9A; - width:100%; - } -div.extra-lineitem { - background: #6699CC; - } -div.warning-lineitem { - background: #FF9933; - } - - - - - -h2 { - font-size: 16px; - color: #000; - } - -ul.plain { - list-style-type:none; - text-align: left; - } - -.notebox { - position: absolute; - top: 0px; - right: 0px; - padding: 1px; - text-indent:0px; - border: 1px solid #FFF; - background: #999; - color: #FFF; - } - -.configbox { - position: absolute; - bottom: 0px; - right: 0px; - padding: 1px; - text-indent:0px; - border: 1px solid #999; - background: #FFF; - color: #999; - } - -p.indented{ - text-indent: 50px - } - -/* Sortable tables */ -table.sortable a.sortheader { - background-color:#dfd; - font-weight: bold; - text-decoration: none; - display: block; - -} -table.sortable { - padding: 2px 4px 2px 4px; - border: 1px solid #000000; - border-spacing: 0px -} -td.sortable{ - padding: 2px 8px 2px 8px; -} - -th.sortable{ - background-color:#F3DD91; - border: 1px solid #FFFFFF; -} -tr.tablelist { - background-color:#EDF3FE; -} -tr.tablelist-alt{ - background-color:#FFFFFF; -} diff --git a/reports/site_media/date.js b/reports/site_media/date.js new file mode 100644 index 000000000..9a923408a --- /dev/null +++ b/reports/site_media/date.js @@ -0,0 +1,335 @@ +// =================================================================== +// Author: Matt Kruse <matt@mattkruse.com> +// WWW: http://www.mattkruse.com/ +// +// NOTICE: You may use this code for any purpose, commercial or +// private, without any further permission from the author. You may +// remove this notice from your final code if you wish, however it is +// appreciated by the author if at least my web site address is kept. +// +// You may *NOT* re-distribute this code in any way except through its +// use. That means, you can include it in your product, or your web +// site, or any other form where the code is actually being used. You +// may not put the plain javascript up on your site for download or +// include it in your javascript libraries for download. +// If you wish to share this code with others, please just point them +// to the URL instead. +// Please DO NOT link directly to my .js files from your site. Copy +// the files to your server and use them there. Thank you. +// =================================================================== + +// HISTORY +// ------------------------------------------------------------------ +// May 17, 2003: Fixed bug in parseDate() for dates <1970 +// March 11, 2003: Added parseDate() function +// March 11, 2003: Added "NNN" formatting option. Doesn't match up +// perfectly with SimpleDateFormat formats, but +// backwards-compatability was required. + +// ------------------------------------------------------------------ +// These functions use the same 'format' strings as the +// java.text.SimpleDateFormat class, with minor exceptions. +// The format string consists of the following abbreviations: +// +// Field | Full Form | Short Form +// -------------+--------------------+----------------------- +// Year | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits) +// Month | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits) +// | NNN (abbr.) | +// Day of Month | dd (2 digits) | d (1 or 2 digits) +// Day of Week | EE (name) | E (abbr) +// Hour (1-12) | hh (2 digits) | h (1 or 2 digits) +// Hour (0-23) | HH (2 digits) | H (1 or 2 digits) +// Hour (0-11) | KK (2 digits) | K (1 or 2 digits) +// Hour (1-24) | kk (2 digits) | k (1 or 2 digits) +// Minute | mm (2 digits) | m (1 or 2 digits) +// Second | ss (2 digits) | s (1 or 2 digits) +// AM/PM | a | +// +// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm! +// Examples: +// "MMM d, y" matches: January 01, 2000 +// Dec 1, 1900 +// Nov 20, 00 +// "M/d/yy" matches: 01/20/00 +// 9/2/00 +// "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM" +// ------------------------------------------------------------------ + +var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); +var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat'); +function LZ(x) {return(x<0||x>9?"":"0")+x} + +// ------------------------------------------------------------------ +// isDate ( date_string, format_string ) +// Returns true if date string matches format of format string and +// is a valid date. Else returns false. +// It is recommended that you trim whitespace around the value before +// passing it to this function, as whitespace is NOT ignored! +// ------------------------------------------------------------------ +function isDate(val,format) { + var date=getDateFromFormat(val,format); + if (date==0) { return false; } + return true; + } + +// ------------------------------------------------------------------- +// compareDates(date1,date1format,date2,date2format) +// Compare two date strings to see which is greater. +// Returns: +// 1 if date1 is greater than date2 +// 0 if date2 is greater than date1 of if they are the same +// -1 if either of the dates is in an invalid format +// ------------------------------------------------------------------- +function compareDates(date1,dateformat1,date2,dateformat2) { + var d1=getDateFromFormat(date1,dateformat1); + var d2=getDateFromFormat(date2,dateformat2); + if (d1==0 || d2==0) { + return -1; + } + else if (d1 > d2) { + return 1; + } + return 0; + } + +// ------------------------------------------------------------------ +// formatDate (date_object, format) +// Returns a date in the output format specified. +// The format string uses the same abbreviations as in getDateFromFormat() +// ------------------------------------------------------------------ +function formatDate(date,format) { + format=format+""; + var result=""; + var i_format=0; + var c=""; + var token=""; + var y=date.getYear()+""; + var M=date.getMonth()+1; + var d=date.getDate(); + var E=date.getDay(); + var H=date.getHours(); + var m=date.getMinutes(); + var s=date.getSeconds(); + var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k; + // Convert real date parts into formatted versions + var value=new Object(); + if (y.length < 4) {y=""+(y-0+1900);} + value["y"]=""+y; + value["yyyy"]=y; + value["yy"]=y.substring(2,4); + value["M"]=M; + value["MM"]=LZ(M); + value["MMM"]=MONTH_NAMES[M-1]; + value["NNN"]=MONTH_NAMES[M+11]; + value["d"]=d; + value["dd"]=LZ(d); + value["E"]=DAY_NAMES[E+7]; + value["EE"]=DAY_NAMES[E]; + value["H"]=H; + value["HH"]=LZ(H); + if (H==0){value["h"]=12;} + else if (H>12){value["h"]=H-12;} + else {value["h"]=H;} + value["hh"]=LZ(value["h"]); + if (H>11){value["K"]=H-12;} else {value["K"]=H;} + value["k"]=H+1; + value["KK"]=LZ(value["K"]); + value["kk"]=LZ(value["k"]); + if (H > 11) { value["a"]="PM"; } + else { value["a"]="AM"; } + value["m"]=m; + value["mm"]=LZ(m); + value["s"]=s; + value["ss"]=LZ(s); + while (i_format < format.length) { + c=format.charAt(i_format); + token=""; + while ((format.charAt(i_format)==c) && (i_format < format.length)) { + token += format.charAt(i_format++); + } + if (value[token] != null) { result=result + value[token]; } + else { result=result + token; } + } + return result; + } + +// ------------------------------------------------------------------ +// Utility functions for parsing in getDateFromFormat() +// ------------------------------------------------------------------ +function _isInteger(val) { + var digits="1234567890"; + for (var i=0; i < val.length; i++) { + if (digits.indexOf(val.charAt(i))==-1) { return false; } + } + return true; + } +function _getInt(str,i,minlength,maxlength) { + for (var x=maxlength; x>=minlength; x--) { + var token=str.substring(i,i+x); + if (token.length < minlength) { return null; } + if (_isInteger(token)) { return token; } + } + return null; + } + +// ------------------------------------------------------------------ +// getDateFromFormat( date_string , format_string ) +// +// This function takes a date string and a format string. It matches +// If the date string matches the format string, it returns the +// getTime() of the date. If it does not match, it returns 0. +// ------------------------------------------------------------------ +function getDateFromFormat(val,format) { + val=val+""; + format=format+""; + var i_val=0; + var i_format=0; + var c=""; + var token=""; + var token2=""; + var x,y; + var now=new Date(); + var year=now.getYear(); + var month=now.getMonth()+1; + var date=1; + var hh=now.getHours(); + var mm=now.getMinutes(); + var ss=now.getSeconds(); + var ampm=""; + + while (i_format < format.length) { + // Get next token from format string + c=format.charAt(i_format); + token=""; + while ((format.charAt(i_format)==c) && (i_format < format.length)) { + token += format.charAt(i_format++); + } + // Extract contents of value based on format token + if (token=="yyyy" || token=="yy" || token=="y") { + if (token=="yyyy") { x=4;y=4; } + if (token=="yy") { x=2;y=2; } + if (token=="y") { x=2;y=4; } + year=_getInt(val,i_val,x,y); + if (year==null) { return 0; } + i_val += year.length; + if (year.length==2) { + if (year > 70) { year=1900+(year-0); } + else { year=2000+(year-0); } + } + } + else if (token=="MMM"||token=="NNN"){ + month=0; + for (var i=0; i<MONTH_NAMES.length; i++) { + var month_name=MONTH_NAMES[i]; + if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) { + if (token=="MMM"||(token=="NNN"&&i>11)) { + month=i+1; + if (month>12) { month -= 12; } + i_val += month_name.length; + break; + } + } + } + if ((month < 1)||(month>12)){return 0;} + } + else if (token=="EE"||token=="E"){ + for (var i=0; i<DAY_NAMES.length; i++) { + var day_name=DAY_NAMES[i]; + if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) { + i_val += day_name.length; + break; + } + } + } + else if (token=="MM"||token=="M") { + month=_getInt(val,i_val,token.length,2); + if(month==null||(month<1)||(month>12)){return 0;} + i_val+=month.length;} + else if (token=="dd"||token=="d") { + date=_getInt(val,i_val,token.length,2); + if(date==null||(date<1)||(date>31)){return 0;} + i_val+=date.length;} + else if (token=="hh"||token=="h") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<1)||(hh>12)){return 0;} + i_val+=hh.length;} + else if (token=="HH"||token=="H") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<0)||(hh>23)){return 0;} + i_val+=hh.length;} + else if (token=="KK"||token=="K") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<0)||(hh>11)){return 0;} + i_val+=hh.length;} + else if (token=="kk"||token=="k") { + hh=_getInt(val,i_val,token.length,2); + if(hh==null||(hh<1)||(hh>24)){return 0;} + i_val+=hh.length;hh--;} + else if (token=="mm"||token=="m") { + mm=_getInt(val,i_val,token.length,2); + if(mm==null||(mm<0)||(mm>59)){return 0;} + i_val+=mm.length;} + else if (token=="ss"||token=="s") { + ss=_getInt(val,i_val,token.length,2); + if(ss==null||(ss<0)||(ss>59)){return 0;} + i_val+=ss.length;} + else if (token=="a") { + if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";} + else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";} + else {return 0;} + i_val+=2;} + else { + if (val.substring(i_val,i_val+token.length)!=token) {return 0;} + else {i_val+=token.length;} + } + } + // If there are any trailing characters left in the value, it doesn't match + if (i_val != val.length) { return 0; } + // Is date valid for month? + if (month==2) { + // Check for leap year + if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year + if (date > 29){ return 0; } + } + else { if (date > 28) { return 0; } } + } + if ((month==4)||(month==6)||(month==9)||(month==11)) { + if (date > 30) { return 0; } + } + // Correct hours value + if (hh<12 && ampm=="PM") { hh=hh-0+12; } + else if (hh>11 && ampm=="AM") { hh-=12; } + var newdate=new Date(year,month-1,date,hh,mm,ss); + return newdate.getTime(); + } + +// ------------------------------------------------------------------ +// parseDate( date_string [, prefer_euro_format] ) +// +// This function takes a date string and tries to match it to a +// number of possible date formats to get the value. It will try to +// match against the following international formats, in this order: +// y-M-d MMM d, y MMM d,y y-MMM-d d-MMM-y MMM d +// M/d/y M-d-y M.d.y MMM-d M/d M-d +// d/M/y d-M-y d.M.y d-MMM d/M d-M +// A second argument may be passed to instruct the method to search +// for formats like d/M/y (european format) before M/d/y (American). +// Returns a Date object or null if no patterns match. +// ------------------------------------------------------------------ +function parseDate(val) { + var preferEuro=(arguments.length==2)?arguments[1]:false; + generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d'); + monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d'); + dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M'); + var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst'); + var d=null; + for (var i=0; i<checkList.length; i++) { + var l=window[checkList[i]]; + for (var j=0; j<l.length; j++) { + d=getDateFromFormat(val,l[j]); + if (d!=0) { return new Date(d); } + } + } + return null; + } diff --git a/reports/site_media/global.css b/reports/site_media/global.css deleted file mode 100644 index ba51e804c..000000000 --- a/reports/site_media/global.css +++ /dev/null @@ -1,10 +0,0 @@ - -body { - margin:0; - padding:0; - font-size:12px; - font-family:"Lucida Grande","Bitstream Vera Sans",Verdana,Arial,sans-serif; - color:#000; - background:#FFF; - height:100%; - } diff --git a/reports/site_media/layout.css b/reports/site_media/layout.css deleted file mode 100644 index b8789ce22..000000000 --- a/reports/site_media/layout.css +++ /dev/null @@ -1,44 +0,0 @@ -/* Page Structure */ -#container { float:left; padding:1em 2em 0 1em; background:#FFFFFF; min-width: 650px; min-height:500px; } -#header { width:100%; } -#content-main { float:left; background: #000000; padding:0; } - -/* HEADER */ -#header { background:#000; color:#ffc;} -#header a:link, #header a:visited { color:white; } -#header a:hover { text-decoration:underline; } -#branding h1 { padding:8px; font-size:18px; margin:0; font-weight:normal; color:#f4f379; } -#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; } -#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; } - -/*SIDEBAR*/ -#sidebar {float: left; position: relative; width: auto; height: 100%; padding: 0 1em 0 1em; color:ffc; min-height:500px;} -a.sidebar:link {color: #fff;} -a.sidebar:active {color: #fff;} -a.sidebar:visited {color: #fff;} -a.sidebar:hover {color: #fff;} -ul.sidebar { - color: #ffc; - text-decoration: none; - list-style-type: none; - padding: 0 1em 0 1em; - margin: 12px 0 12px 0; -} -ul.sidebar-level2 { - text-indent: -2em; - list-style-type: none; - font-size: 11px; -} - -/* Page Header */ -div.header { - background-color: #DDD; - padding: 1em; - position: relative; -} -div.header h1 { - font-size: 18px; - font-weight: normal; - padding: 0; - margin: 0; -} diff --git a/reports/site_media/main.js b/reports/site_media/main.js deleted file mode 100644 index 556130466..000000000 --- a/reports/site_media/main.js +++ /dev/null @@ -1,27 +0,0 @@ -function toggleLayer(whichLayer) - { - if (document.getElementById) - { - // this is the way the standards work - var style2 = document.getElementById(whichLayer).style; - style2.display = style2.display? "":"block"; - } - else if (document.all) - { - // this is the way old msie versions work - var style2 = document.all[whichLayer].style; - style2.display = style2.display? "":"block"; - } - else if (document.layers) - { - // this is the way nn4 works - var style2 = document.layers[whichLayer].style; - style2.display = style2.display? "":"block"; - } - } - -function MM_jumpMenu(targ,selObj,restore) -{ //v3.0 - eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'"); - if (restore) selObj.selectedIndex=0; -}
\ No newline at end of file diff --git a/reports/site_media/sorttable.js b/reports/site_media/sorttable.js deleted file mode 100644 index 83c87708e..000000000 --- a/reports/site_media/sorttable.js +++ /dev/null @@ -1,203 +0,0 @@ - -// -// Sourced originally from: -// -// http://www.kryogenix.org/code/browser/sorttable/ - - - -addEvent(window, "load", sortables_init); - -var SORT_COLUMN_INDEX; - -function sortables_init() { - // Find all tables with class sortable and make them sortable - if (!document.getElementsByTagName) return; - tbls = document.getElementsByTagName("table"); - for (ti=0;ti<tbls.length;ti++) { - thisTbl = tbls[ti]; - if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) { - //initTable(thisTbl.id); - ts_makeSortable(thisTbl); - } - } -} - -function ts_makeSortable(table) { - if (table.rows && table.rows.length > 0) { - var firstRow = table.rows[0]; - } - if (!firstRow) return; - - // Assign classes to the rows when the table's first loaded - for (i=1;i<table.rows.length;i++) { - if (i%2 == 0) table.rows[i].className='tablelist'; - else table.rows[i].className='tablelist tablelist-alt'; - } - - // We have a first row: assume it's the header, and make its contents clickable links - for (var i=0;i<firstRow.cells.length;i++) { - var cell = firstRow.cells[i]; - var txt = ts_getInnerText(cell); - cell.innerHTML = '<a href="#" onclick="ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow"></span></a>'; - } -} - -function ts_getInnerText(el) { - if (typeof el == "string") return el; - if (typeof el == "undefined") { return el }; - if (el.innerText) return el.innerText; //Not needed but it is faster - var str = ""; - - var cs = el.childNodes; - var l = cs.length; - for (var i = 0; i < l; i++) { - switch (cs[i].nodeType) { - case 1: //ELEMENT_NODE - str += ts_getInnerText(cs[i]); - break; - case 3: //TEXT_NODE - str += cs[i].nodeValue; - break; - } - } - return str; -} - -function ts_resortTable(lnk, clid) { - // get the span - var span; - for (var ci=0;ci<lnk.childNodes.length;ci++) { - if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci]; - } - var spantext = ts_getInnerText(span); - var td = lnk.parentNode; - var column = clid || td.cellIndex; - var table = getParent(td,'TABLE'); - - // Work out a type for the column - if (table.rows.length <= 1) return; - var itm = ts_getInnerText(table.rows[1].cells[column]); - sortfn = ts_sort_caseinsensitive; - if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date; - if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date; - - if (itm.match(/^[\d\.]+$/)) sortfn = ts_sort_numeric; - SORT_COLUMN_INDEX = column; - var firstRow = new Array(); - var newRows = new Array(); - for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; } - for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; } - - newRows.sort(sortfn); - - if (span.getAttribute("sortdir") == 'down') { - ARROW = ''; - newRows.reverse(); - span.setAttribute('sortdir','up'); - } else { - ARROW = ''; - span.setAttribute('sortdir','down'); - } - - // Assign updated classes to the rows when the sort's finished - for (i=0;i<newRows.length;i++) { - if (i%2 == 1) newRows[i].className='tablelist'; - else newRows[i].className='tablelist tablelist-alt'; - } - - // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones - // don't do sortbottom rows - for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);} - // do sortbottom rows only - for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);} - - // Delete any other arrows there may be showing - var allspans = document.getElementsByTagName("span"); - for (var ci=0;ci<allspans.length;ci++) { - if (allspans[ci].className == 'sortarrow') { - if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us? - allspans[ci].innerHTML = ''; - } - } - } - - span.innerHTML = ARROW; -} - -function getParent(el, pTagName) { - if (el == null) return null; - else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase - return el; - else - return getParent(el.parentNode, pTagName); -} -function ts_sort_date(a,b) { - // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX - aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]); - bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]); - if (aa.length == 10) { - dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2); - } else { - yr = aa.substr(6,2); - if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; } - dt1 = yr+aa.substr(3,2)+aa.substr(0,2); - } - if (bb.length == 10) { - dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2); - } else { - yr = bb.substr(6,2); - if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; } - dt2 = yr+bb.substr(3,2)+bb.substr(0,2); - } - if (dt1==dt2) return 0; - if (dt1<dt2) return -1; - return 1; -} - -function ts_sort_currency(a,b) { - aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,''); - bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,''); - return parseFloat(aa) - parseFloat(bb); -} - -function ts_sort_numeric(a,b) { - aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX])); - if (isNaN(aa)) aa = 0; - bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX])); - if (isNaN(bb)) bb = 0; - return aa-bb; -} - -function ts_sort_caseinsensitive(a,b) { - aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase(); - bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase(); - if (aa==bb) return 0; - if (aa<bb) return -1; - return 1; -} - -function ts_sort_default(a,b) { - aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]); - bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]); - if (aa==bb) return 0; - if (aa<bb) return -1; - return 1; -} - - -function addEvent(elm, evType, fn, useCapture) -// addEvent and removeEvent -// cross-browser event handling for IE5+, NS6 and Mozilla -// By Scott Andrew -{ - if (elm.addEventListener){ - elm.addEventListener(evType, fn, useCapture); - return true; - } else if (elm.attachEvent){ - var r = elm.attachEvent("on"+evType, fn); - return r; - } else { - alert("Handler could not be removed"); - } -} diff --git a/reports/site_media/syntax-coloring.css b/reports/site_media/syntax-coloring.css deleted file mode 100644 index 23eb757a4..000000000 --- a/reports/site_media/syntax-coloring.css +++ /dev/null @@ -1,59 +0,0 @@ - -.highlight{ background: #fff; } -.highlight .c { color: #008800; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */ -.highlight .o { color: #666666 } /* Operator */ -.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #008800 } /* Comment.Preproc */ -.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #FF0000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #00A000 } /* Generic.Inserted */ -.highlight .go { color: #808080 } /* Generic.Output */ -.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #0040D0 } /* Generic.Traceback */ -.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */ -.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */ -.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #AA22FF; font-weight: bold } /* Keyword.Type */ -.highlight .m { color: #666666 } /* Literal.Number */ -.highlight .s { color: #BB4444 } /* Literal.String */ -.highlight .na { color: #BB4444 } /* Name.Attribute */ -.highlight .nb { color: #AA22FF } /* Name.Builtin */ -.highlight .nc { color: #0000FF } /* Name.Class */ -.highlight .no { color: #880000 } /* Name.Constant */ -.highlight .nd { color: #AA22FF } /* Name.Decorator */ -.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #00A000 } /* Name.Function */ -.highlight .nl { color: #A0A000 } /* Name.Label */ -.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #B8860B } /* Name.Variable */ -.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.highlight .mf { color: #666666 } /* Literal.Number.Float */ -.highlight .mh { color: #666666 } /* Literal.Number.Hex */ -.highlight .mi { color: #666666 } /* Literal.Number.Integer */ -.highlight .mo { color: #666666 } /* Literal.Number.Oct */ -.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */ -.highlight .sc { color: #BB4444 } /* Literal.String.Char */ -.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #BB4444 } /* Literal.String.Double */ -.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */ -.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -.highlight .sx { color: #008000 } /* Literal.String.Other */ -.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ -.highlight .s1 { color: #BB4444 } /* Literal.String.Single */ -.highlight .ss { color: #B8860B } /* Literal.String.Symbol */ -.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #B8860B } /* Name.Variable.Class */ -.highlight .vg { color: #B8860B } /* Name.Variable.Global */ -.highlight .vi { color: #B8860B } /* Name.Variable.Instance */ -.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
\ No newline at end of file diff --git a/reports/site_media/yui/dom/README b/reports/site_media/yui/dom/README deleted file mode 100644 index 966543f58..000000000 --- a/reports/site_media/yui/dom/README +++ /dev/null @@ -1,75 +0,0 @@ -Dom Release Notes - -*** version 0.12.2 *** -* no change - -*** version 0.12.1 *** - -* getElementsByClassName no longer reverts to document when "root" not found -* setXY no longer makes a second call to getXY unless noRetry is false -* minified version no longer strips line breaks - -*** version 0.12.0 *** - -* fixed getXY for IE null parent -* branching set/getStyle at load time instead of run time - -*** version 0.11.3 *** - -* fixed getX and getY returning incorrect values for collections -* fixed getXY incorrectly calculated for Opera inline elements -* fixed isAncestor failure in safari when 2nd arg is document.documentElement -* fixed infinite loop in replaceClass when oldClassName == newClassName -* getDocumentWidth no longer includes scrollbars - - -*** version 0.11.2 *** -* limit depth of parent.document crawl to 1 for getXY -* test offsetParent instead of parentNode for getXY -* return null if no el fo r get -* just addClass if no class to replace for replaceClass - - -*** version 0.11.1 *** - -* return null if el is null for get() -* test offsetParent rather than parentNode for getXY() -* limit depth of parent.document crawl for IE getXY() to 1 -* if no oldClassName to replace, just addClass for replaceClass() - - -*** version 0.11.0 *** -* Work around Opera 9 broken currentStyle -* Removed timeout wrapper from setXY retry -* Tagname tests now case-insensitive -* Internal "this" references changed to allow for method shorthand -* get/setStyle now accept both camel and hyphen case -* Gecko reverted to crawling offsets for getXY - - -*** version 0.10.0 *** - -* Safari now fails gracefully when querying computedStyle of an unavailable element - -* Class management functions added (hasClass, addClass, removeClass, replaceClass, getElementsByClassName) - -* All methods that accept HTMLElements or IDs now also accept arrays of HTMLElements and/or IDs - -* GenerateId method added - -* isAncestor method added - -* inDocument method added - -* getElementsBy method added - -* batch method added - -* getClientHeight/Width deprecated in favor of getViewportHeight/Width - -* getDocumentHeight/Width methods added - -*** version 0.9.0 *** - -* Initial release - diff --git a/reports/site_media/yui/dom/dom-debug.js b/reports/site_media/yui/dom/dom-debug.js deleted file mode 100644 index e9368d90f..000000000 --- a/reports/site_media/yui/dom/dom-debug.js +++ /dev/null @@ -1,927 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ -/** - * The dom module provides helper methods for manipulating Dom elements. - * @module dom - * - */ - -(function() { - var Y = YAHOO.util, // internal shorthand - getStyle, // for load time browser branching - setStyle, // ditto - id_counter = 0, // for use with generateId - propertyCache = {}; // for faster hyphen converts - - // brower detection - var ua = navigator.userAgent.toLowerCase(), - isOpera = (ua.indexOf('opera') > -1), - isSafari = (ua.indexOf('safari') > -1), - isGecko = (!isOpera && !isSafari && ua.indexOf('gecko') > -1), - isIE = (!isOpera && ua.indexOf('msie') > -1); - - // regex cache - var patterns = { - HYPHEN: /(-[a-z])/i - }; - - var logger = {}; - logger.log = function() { YAHOO.log.apply(window, arguments); }; - - var toCamel = function(property) { - if ( !patterns.HYPHEN.test(property) ) { - return property; // no hyphens - } - - if (propertyCache[property]) { // already converted - return propertyCache[property]; - } - - while( patterns.HYPHEN.exec(property) ) { - property = property.replace(RegExp.$1, - RegExp.$1.substr(1).toUpperCase()); - } - - propertyCache[property] = property; - return property; - //return property.replace(/-([a-z])/gi, function(m0, m1) {return m1.toUpperCase()}) // cant use function as 2nd arg yet due to safari bug - }; - - // branching at load instead of runtime - if (document.defaultView && document.defaultView.getComputedStyle) { // W3C DOM method - getStyle = function(el, property) { - var value = null; - - var computed = document.defaultView.getComputedStyle(el, ''); - if (computed) { // test computed before touching for safari - value = computed[toCamel(property)]; - } - - return el.style[property] || value; - }; - } else if (document.documentElement.currentStyle && isIE) { // IE method - getStyle = function(el, property) { - switch( toCamel(property) ) { - case 'opacity' :// IE opacity uses filter - var val = 100; - try { // will error if no DXImageTransform - val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity; - - } catch(e) { - try { // make sure its in the document - val = el.filters('alpha').opacity; - } catch(e) { - logger.log('getStyle: IE filter failed', - 'error', 'Dom'); - } - } - return val / 100; - break; - default: - // test currentStyle before touching - var value = el.currentStyle ? el.currentStyle[property] : null; - return ( el.style[property] || value ); - } - }; - } else { // default to inline only - getStyle = function(el, property) { return el.style[property]; }; - } - - if (isIE) { - setStyle = function(el, property, val) { - switch (property) { - case 'opacity': - if ( typeof el.style.filter == 'string' ) { // in case not appended - el.style.filter = 'alpha(opacity=' + val * 100 + ')'; - - if (!el.currentStyle || !el.currentStyle.hasLayout) { - el.style.zoom = 1; // when no layout or cant tell - } - } - break; - default: - el.style[property] = val; - } - }; - } else { - setStyle = function(el, property, val) { - el.style[property] = val; - }; - } - - /** - * Provides helper methods for DOM elements. - * @namespace YAHOO.util - * @class Dom - */ - YAHOO.util.Dom = { - /** - * Returns an HTMLElement reference. - * @method get - * @param {String | HTMLElement |Array} el Accepts a string to use as an ID for getting a DOM reference, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @return {HTMLElement | Array} A DOM reference to an HTML element or an array of HTMLElements. - */ - get: function(el) { - if (!el) { return null; } // nothing to work with - - if (typeof el != 'string' && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is - logger.log('get(' + el + ') returning ' + el, 'info', 'Dom'); - return el; - } - - if (typeof el == 'string') { // ID - logger.log('get("' + el + '") returning ' + document.getElementById(el), 'info', 'Dom'); - return document.getElementById(el); - } - else { // array of ID's and/or elements - var collection = []; - for (var i = 0, len = el.length; i < len; ++i) { - collection[collection.length] = Y.Dom.get(el[i]); - } - - logger.log('get("' + el + '") returning ' + collection, 'info', 'Dom'); - return collection; - } - - logger.log('element ' + el + ' not found', 'error', 'Dom'); - return null; // safety, should never happen - }, - - /** - * Normalizes currentStyle and ComputedStyle. - * @method getStyle - * @param {String | HTMLElement |Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {String} property The style property whose value is returned. - * @return {String | Array} The current value of the style property for the element(s). - */ - getStyle: function(el, property) { - property = toCamel(property); - - var f = function(element) { - return getStyle(element, property); - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Wrapper for setting style properties of HTMLElements. Normalizes "opacity" across modern browsers. - * @method setStyle - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {String} property The style property to be set. - * @param {String} val The value to apply to the given property. - */ - setStyle: function(el, property, val) { - property = toCamel(property); - - var f = function(element) { - setStyle(element, property, val); - logger.log('setStyle setting ' + property + ' to ' + val, 'info', 'Dom'); - - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Gets the current position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method getXY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @return {Array} The XY position of the element(s) - */ - getXY: function(el) { - var f = function(el) { - - // has to be part of document to have pageXY - if (el.parentNode === null || el.offsetParent === null || - this.getStyle(el, 'display') == 'none') { - logger.log('getXY failed: element not available', 'error', 'Dom'); - return false; - } - - var parentNode = null; - var pos = []; - var box; - - if (el.getBoundingClientRect) { // IE - box = el.getBoundingClientRect(); - var doc = document; - if ( !this.inDocument(el) && parent.document != document) {// might be in a frame, need to get its scroll - doc = parent.document; - - if ( !this.isAncestor(doc.documentElement, el) ) { - logger.log('getXY failed: element not available', 'error', 'Dom'); - return false; - } - - } - - var scrollTop = Math.max(doc.documentElement.scrollTop, doc.body.scrollTop); - var scrollLeft = Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft); - - return [box.left + scrollLeft, box.top + scrollTop]; - } - else { // safari, opera, & gecko - pos = [el.offsetLeft, el.offsetTop]; - parentNode = el.offsetParent; - if (parentNode != el) { - while (parentNode) { - pos[0] += parentNode.offsetLeft; - pos[1] += parentNode.offsetTop; - parentNode = parentNode.offsetParent; - } - } - if (isSafari && this.getStyle(el, 'position') == 'absolute' ) { // safari doubles in some cases - pos[0] -= document.body.offsetLeft; - pos[1] -= document.body.offsetTop; - } - } - - if (el.parentNode) { parentNode = el.parentNode; } - else { parentNode = null; } - - while (parentNode && parentNode.tagName.toUpperCase() != 'BODY' && parentNode.tagName.toUpperCase() != 'HTML') - { // account for any scrolled ancestors - if (Y.Dom.getStyle(parentNode, 'display') != 'inline') { // work around opera inline scrollLeft/Top bug - pos[0] -= parentNode.scrollLeft; - pos[1] -= parentNode.scrollTop; - } - - if (parentNode.parentNode) { - parentNode = parentNode.parentNode; - } else { parentNode = null; } - } - - logger.log('getXY returning ' + pos, 'info', 'Dom'); - - return pos; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Gets the current X position of an element based on page coordinates. The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method getX - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @return {String | Array} The X position of the element(s) - */ - getX: function(el) { - var f = function(el) { - return Y.Dom.getXY(el)[0]; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Gets the current Y position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method getY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @return {String | Array} The Y position of the element(s) - */ - getY: function(el) { - var f = function(el) { - return Y.Dom.getXY(el)[1]; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Set the position of an html element in page coordinates, regardless of how the element is positioned. - * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setXY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @param {Array} pos Contains X & Y values for new position (coordinates are page-based) - * @param {Boolean} noRetry By default we try and set the position a second time if the first fails - */ - setXY: function(el, pos, noRetry) { - var f = function(el) { - var style_pos = this.getStyle(el, 'position'); - if (style_pos == 'static') { // default to relative - this.setStyle(el, 'position', 'relative'); - style_pos = 'relative'; - } - - var pageXY = this.getXY(el); - if (pageXY === false) { // has to be part of doc to have pageXY - logger.log('setXY failed: element not available', 'error', 'Dom'); - return false; - } - - var delta = [ // assuming pixels; if not we will have to retry - parseInt( this.getStyle(el, 'left'), 10 ), - parseInt( this.getStyle(el, 'top'), 10 ) - ]; - - if ( isNaN(delta[0]) ) {// in case of 'auto' - delta[0] = (style_pos == 'relative') ? 0 : el.offsetLeft; - } - if ( isNaN(delta[1]) ) { // in case of 'auto' - delta[1] = (style_pos == 'relative') ? 0 : el.offsetTop; - } - - if (pos[0] !== null) { el.style.left = pos[0] - pageXY[0] + delta[0] + 'px'; } - if (pos[1] !== null) { el.style.top = pos[1] - pageXY[1] + delta[1] + 'px'; } - - if (!noRetry) { - var newXY = this.getXY(el); - - // if retry is true, try one more time if we miss - if ( (pos[0] !== null && newXY[0] != pos[0]) || - (pos[1] !== null && newXY[1] != pos[1]) ) { - this.setXY(el, pos, true); - } - } - - logger.log('setXY setting position to ' + pos, 'info', 'Dom'); - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Set the X position of an html element in page coordinates, regardless of how the element is positioned. - * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setX - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {Int} x The value to use as the X coordinate for the element(s). - */ - setX: function(el, x) { - Y.Dom.setXY(el, [x, null]); - }, - - /** - * Set the Y position of an html element in page coordinates, regardless of how the element is positioned. - * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {Int} x To use as the Y coordinate for the element(s). - */ - setY: function(el, y) { - Y.Dom.setXY(el, [null, y]); - }, - - /** - * Returns the region position of the given element. - * The element must be part of the DOM tree to have a region (display:none or elements not appended return false). - * @method getRegion - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @return {Region | Array} A Region or array of Region instances containing "top, left, bottom, right" member data. - */ - getRegion: function(el) { - var f = function(el) { - var region = new Y.Region.getRegion(el); - logger.log('getRegion returning ' + region, 'info', 'Dom'); - return region; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Returns the width of the client (viewport). - * @method getClientWidth - * @deprecated Now using getViewportWidth. This interface left intact for back compat. - * @return {Int} The width of the viewable area of the page. - */ - getClientWidth: function() { - return Y.Dom.getViewportWidth(); - }, - - /** - * Returns the height of the client (viewport). - * @method getClientHeight - * @deprecated Now using getViewportHeight. This interface left intact for back compat. - * @return {Int} The height of the viewable area of the page. - */ - getClientHeight: function() { - return Y.Dom.getViewportHeight(); - }, - - /** - * Returns a array of HTMLElements with the given class. - * For optimized performance, include a tag and/or root node when possible. - * @method getElementsByClassName - * @param {String} className The class name to match against - * @param {String} tag (optional) The tag name of the elements being collected - * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point - * @return {Array} An array of elements that have the given class name - */ - getElementsByClassName: function(className, tag, root) { - var method = function(el) { return Y.Dom.hasClass(el, className); }; - return Y.Dom.getElementsBy(method, tag, root); - }, - - /** - * Determines whether an HTMLElement has the given className. - * @method hasClass - * @param {String | HTMLElement | Array} el The element or collection to test - * @param {String} className the class name to search for - * @return {Boolean | Array} A boolean value or array of boolean values - */ - hasClass: function(el, className) { - var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'); - - var f = function(el) { - logger.log('hasClass returning ' + re.test(el['className']), 'info', 'Dom'); - return re.test(el['className']); - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Adds a class name to a given element or collection of elements. - * @method addClass - * @param {String | HTMLElement | Array} el The element or collection to add the class to - * @param {String} className the class name to add to the class attribute - */ - addClass: function(el, className) { - var f = function(el) { - if (this.hasClass(el, className)) { return; } // already present - - logger.log('addClass adding ' + className, 'info', 'Dom'); - - el['className'] = [el['className'], className].join(' '); - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Removes a class name from a given element or collection of elements. - * @method removeClass - * @param {String | HTMLElement | Array} el The element or collection to remove the class from - * @param {String} className the class name to remove from the class attribute - */ - removeClass: function(el, className) { - var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', 'g'); - - var f = function(el) { - if (!this.hasClass(el, className)) { return; } // not present - - logger.log('removeClass removing ' + className, 'info', 'Dom'); - - var c = el['className']; - el['className'] = c.replace(re, ' '); - if ( this.hasClass(el, className) ) { // in case of multiple adjacent - this.removeClass(el, className); - } - - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Replace a class with another class for a given element or collection of elements. - * If no oldClassName is present, the newClassName is simply added. - * @method replaceClass - * @param {String | HTMLElement | Array} el The element or collection to remove the class from - * @param {String} oldClassName the class name to be replaced - * @param {String} newClassName the class name that will be replacing the old class name - */ - replaceClass: function(el, oldClassName, newClassName) { - if (oldClassName === newClassName) { // avoid infinite loop - return false; - } - - var re = new RegExp('(?:^|\\s+)' + oldClassName + '(?:\\s+|$)', 'g'); - - var f = function(el) { - logger.log('replaceClass replacing ' + oldClassName + ' with ' + newClassName, 'info', 'Dom'); - - if ( !this.hasClass(el, oldClassName) ) { - this.addClass(el, newClassName); // just add it if nothing to replace - return; // note return - } - - el['className'] = el['className'].replace(re, ' ' + newClassName + ' '); - - if ( this.hasClass(el, oldClassName) ) { // in case of multiple adjacent - this.replaceClass(el, oldClassName, newClassName); - } - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Generates a unique ID - * @method generateId - * @param {String | HTMLElement | Array} el (optional) An optional element array of elements to add an ID to (no ID is added if one is already present). - * @param {String} prefix (optional) an optional prefix to use (defaults to "yui-gen"). - * @return {String | Array} The generated ID, or array of generated IDs (or original ID if already present on an element) - */ - generateId: function(el, prefix) { - prefix = prefix || 'yui-gen'; - el = el || {}; - - var f = function(el) { - if (el) { - el = Y.Dom.get(el); - } else { - el = {}; // just generating ID in this case - } - - if (!el.id) { - el.id = prefix + id_counter++; - logger.log('generateId generating ' + el.id, 'info', 'Dom'); - } // dont override existing - - logger.log('generateId returning ' + el.id, 'info', 'Dom'); - - return el.id; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Determines whether an HTMLElement is an ancestor of another HTML element in the DOM hierarchy. - * @method isAncestor - * @param {String | HTMLElement} haystack The possible ancestor - * @param {String | HTMLElement} needle The possible descendent - * @return {Boolean} Whether or not the haystack is an ancestor of needle - */ - isAncestor: function(haystack, needle) { - haystack = Y.Dom.get(haystack); - if (!haystack || !needle) { return false; } - - var f = function(needle) { - if (haystack.contains && !isSafari) { // safari "contains" is broken - logger.log('isAncestor returning ' + haystack.contains(needle), 'info', 'Dom'); - return haystack.contains(needle); - } - else if ( haystack.compareDocumentPosition ) { - logger.log('isAncestor returning ' + !!(haystack.compareDocumentPosition(needle) & 16), 'info', 'Dom'); - return !!(haystack.compareDocumentPosition(needle) & 16); - } - else { // loop up and test each parent - var parent = needle.parentNode; - - while (parent) { - if (parent == haystack) { - logger.log('isAncestor returning true', 'info', 'Dom'); - return true; - } - else if (!parent.tagName || parent.tagName.toUpperCase() == 'HTML') { - logger.log('isAncestor returning false', 'info', 'Dom'); - return false; - } - - parent = parent.parentNode; - } - logger.log('isAncestor returning false', 'info', 'Dom'); - return false; - } - }; - - return Y.Dom.batch(needle, f, Y.Dom, true); - }, - - /** - * Determines whether an HTMLElement is present in the current document. - * @method inDocument - * @param {String | HTMLElement} el The element to search for - * @return {Boolean} Whether or not the element is present in the current document - */ - inDocument: function(el) { - var f = function(el) { - return this.isAncestor(document.documentElement, el); - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Returns a array of HTMLElements that pass the test applied by supplied boolean method. - * For optimized performance, include a tag and/or root node when possible. - * @method getElementsBy - * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. - - * @param {String} tag (optional) The tag name of the elements being collected - * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point - */ - getElementsBy: function(method, tag, root) { - tag = tag || '*'; - - var nodes = []; - - if (root) { - root = Y.Dom.get(root); - if (!root) { // if no root node, then no children - return nodes; - } - } else { - root = document; - } - - var elements = root.getElementsByTagName(tag); - - if ( !elements.length && (tag == '*' && root.all) ) { - elements = root.all; // IE < 6 - } - - for (var i = 0, len = elements.length; i < len; ++i) { - if ( method(elements[i]) ) { nodes[nodes.length] = elements[i]; } - } - - logger.log('getElementsBy returning ' + nodes, 'info', 'Dom'); - - return nodes; - }, - - /** - * Returns an array of elements that have had the supplied method applied. - * The method is called with the element(s) as the first arg, and the optional param as the second ( method(el, o) ). - * @method batch - * @param {String | HTMLElement | Array} el (optional) An element or array of elements to apply the method to - * @param {Function} method The method to apply to the element(s) - * @param {Any} o (optional) An optional arg that is passed to the supplied method - * @param {Boolean} override (optional) Whether or not to override the scope of "method" with "o" - * @return {HTMLElement | Array} The element(s) with the method applied - */ - batch: function(el, method, o, override) { - var id = el; - el = Y.Dom.get(el); - - var scope = (override) ? o : window; - - if (!el || el.tagName || !el.length) { // is null or not a collection (tagName for SELECT and others that can be both an element and a collection) - if (!el) { - logger.log(id + ' not available', 'error', 'Dom'); - return false; - } - return method.call(scope, el, o); - } - - var collection = []; - - for (var i = 0, len = el.length; i < len; ++i) { - if (!el[i]) { - id = el[i]; - logger.log(id + ' not available', 'error', 'Dom'); - } - collection[collection.length] = method.call(scope, el[i], o); - } - - return collection; - }, - - /** - * Returns the height of the document. - * @method getDocumentHeight - * @return {Int} The height of the actual document (which includes the body and its margin). - */ - getDocumentHeight: function() { - var scrollHeight = (document.compatMode != 'CSS1Compat') ? document.body.scrollHeight : document.documentElement.scrollHeight; - - var h = Math.max(scrollHeight, Y.Dom.getViewportHeight()); - logger.log('getDocumentHeight returning ' + h, 'info', 'Dom'); - return h; - }, - - /** - * Returns the width of the document. - * @method getDocumentWidth - * @return {Int} The width of the actual document (which includes the body and its margin). - */ - getDocumentWidth: function() { - var scrollWidth = (document.compatMode != 'CSS1Compat') ? document.body.scrollWidth : document.documentElement.scrollWidth; - var w = Math.max(scrollWidth, Y.Dom.getViewportWidth()); - logger.log('getDocumentWidth returning ' + w, 'info', 'Dom'); - return w; - }, - - /** - * Returns the current height of the viewport. - * @method getViewportHeight - * @return {Int} The height of the viewable area of the page (excludes scrollbars). - */ - getViewportHeight: function() { - var height = self.innerHeight; // Safari, Opera - var mode = document.compatMode; - - if ( (mode || isIE) && !isOpera ) { // IE, Gecko - height = (mode == 'CSS1Compat') ? - document.documentElement.clientHeight : // Standards - document.body.clientHeight; // Quirks - } - - logger.log('getViewportHeight returning ' + height, 'info', 'Dom'); - return height; - }, - - /** - * Returns the current width of the viewport. - * @method getViewportWidth - * @return {Int} The width of the viewable area of the page (excludes scrollbars). - */ - - getViewportWidth: function() { - var width = self.innerWidth; // Safari - var mode = document.compatMode; - - if (mode || isIE) { // IE, Gecko, Opera - width = (mode == 'CSS1Compat') ? - document.documentElement.clientWidth : // Standards - document.body.clientWidth; // Quirks - } - logger.log('getViewportWidth returning ' + width, 'info', 'Dom'); - return width; - } - }; -})(); -/** - * A region is a representation of an object on a grid. It is defined - * by the top, right, bottom, left extents, so is rectangular by default. If - * other shapes are required, this class could be extended to support it. - * @namespace YAHOO.util - * @class Region - * @param {Int} t the top extent - * @param {Int} r the right extent - * @param {Int} b the bottom extent - * @param {Int} l the left extent - * @constructor - */ -YAHOO.util.Region = function(t, r, b, l) { - - /** - * The region's top extent - * @property top - * @type Int - */ - this.top = t; - - /** - * The region's top extent as index, for symmetry with set/getXY - * @property 1 - * @type Int - */ - this[1] = t; - - /** - * The region's right extent - * @property right - * @type int - */ - this.right = r; - - /** - * The region's bottom extent - * @property bottom - * @type Int - */ - this.bottom = b; - - /** - * The region's left extent - * @property left - * @type Int - */ - this.left = l; - - /** - * The region's left extent as index, for symmetry with set/getXY - * @property 0 - * @type Int - */ - this[0] = l; -}; - -/** - * Returns true if this region contains the region passed in - * @method contains - * @param {Region} region The region to evaluate - * @return {Boolean} True if the region is contained with this region, - * else false - */ -YAHOO.util.Region.prototype.contains = function(region) { - return ( region.left >= this.left && - region.right <= this.right && - region.top >= this.top && - region.bottom <= this.bottom ); - - // this.logger.debug("does " + this + " contain " + region + " ... " + ret); -}; - -/** - * Returns the area of the region - * @method getArea - * @return {Int} the region's area - */ -YAHOO.util.Region.prototype.getArea = function() { - return ( (this.bottom - this.top) * (this.right - this.left) ); -}; - -/** - * Returns the region where the passed in region overlaps with this one - * @method intersect - * @param {Region} region The region that intersects - * @return {Region} The overlap region, or null if there is no overlap - */ -YAHOO.util.Region.prototype.intersect = function(region) { - var t = Math.max( this.top, region.top ); - var r = Math.min( this.right, region.right ); - var b = Math.min( this.bottom, region.bottom ); - var l = Math.max( this.left, region.left ); - - if (b >= t && r >= l) { - return new YAHOO.util.Region(t, r, b, l); - } else { - return null; - } -}; - -/** - * Returns the region representing the smallest region that can contain both - * the passed in region and this region. - * @method union - * @param {Region} region The region that to create the union with - * @return {Region} The union region - */ -YAHOO.util.Region.prototype.union = function(region) { - var t = Math.min( this.top, region.top ); - var r = Math.max( this.right, region.right ); - var b = Math.max( this.bottom, region.bottom ); - var l = Math.min( this.left, region.left ); - - return new YAHOO.util.Region(t, r, b, l); -}; - -/** - * toString - * @method toString - * @return string the region properties - */ -YAHOO.util.Region.prototype.toString = function() { - return ( "Region {" + - "top: " + this.top + - ", right: " + this.right + - ", bottom: " + this.bottom + - ", left: " + this.left + - "}" ); -}; - -/** - * Returns a region that is occupied by the DOM element - * @method getRegion - * @param {HTMLElement} el The element - * @return {Region} The region that the element occupies - * @static - */ -YAHOO.util.Region.getRegion = function(el) { - var p = YAHOO.util.Dom.getXY(el); - - var t = p[1]; - var r = p[0] + el.offsetWidth; - var b = p[1] + el.offsetHeight; - var l = p[0]; - - return new YAHOO.util.Region(t, r, b, l); -}; - -///////////////////////////////////////////////////////////////////////////// - - -/** - * A point is a region that is special in that it represents a single point on - * the grid. - * @namespace YAHOO.util - * @class Point - * @param {Int} x The X position of the point - * @param {Int} y The Y position of the point - * @constructor - * @extends YAHOO.util.Region - */ -YAHOO.util.Point = function(x, y) { - if (x instanceof Array) { // accept output from Dom.getXY - y = x[1]; - x = x[0]; - } - - /** - * The X position of the point, which is also the right, left and index zero (for Dom.getXY symmetry) - * @property x - * @type Int - */ - - this.x = this.right = this.left = this[0] = x; - - /** - * The Y position of the point, which is also the top, bottom and index one (for Dom.getXY symmetry) - * @property y - * @type Int - */ - this.y = this.top = this.bottom = this[1] = y; -}; - -YAHOO.util.Point.prototype = new YAHOO.util.Region(); - diff --git a/reports/site_media/yui/dom/dom-min.js b/reports/site_media/yui/dom/dom-min.js deleted file mode 100644 index 36e62f93a..000000000 --- a/reports/site_media/yui/dom/dom-min.js +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ - -(function(){var Y=YAHOO.util,getStyle,setStyle,id_counter=0,propertyCache={};var ua=navigator.userAgent.toLowerCase(),isOpera=(ua.indexOf('opera')>-1),isSafari=(ua.indexOf('safari')>-1),isGecko=(!isOpera&&!isSafari&&ua.indexOf('gecko')>-1),isIE=(!isOpera&&ua.indexOf('msie')>-1);var patterns={HYPHEN:/(-[a-z])/i};var toCamel=function(property){if(!patterns.HYPHEN.test(property)){return property;} -if(propertyCache[property]){return propertyCache[property];} -while(patterns.HYPHEN.exec(property)){property=property.replace(RegExp.$1,RegExp.$1.substr(1).toUpperCase());} -propertyCache[property]=property;return property;};if(document.defaultView&&document.defaultView.getComputedStyle){getStyle=function(el,property){var value=null;var computed=document.defaultView.getComputedStyle(el,'');if(computed){value=computed[toCamel(property)];} -return el.style[property]||value;};}else if(document.documentElement.currentStyle&&isIE){getStyle=function(el,property){switch(toCamel(property)){case'opacity':var val=100;try{val=el.filters['DXImageTransform.Microsoft.Alpha'].opacity;}catch(e){try{val=el.filters('alpha').opacity;}catch(e){}} -return val/100;break;default:var value=el.currentStyle?el.currentStyle[property]:null;return(el.style[property]||value);}};}else{getStyle=function(el,property){return el.style[property];};} -if(isIE){setStyle=function(el,property,val){switch(property){case'opacity':if(typeof el.style.filter=='string'){el.style.filter='alpha(opacity='+val*100+')';if(!el.currentStyle||!el.currentStyle.hasLayout){el.style.zoom=1;}} -break;default:el.style[property]=val;}};}else{setStyle=function(el,property,val){el.style[property]=val;};} -YAHOO.util.Dom={get:function(el){if(!el){return null;} -if(typeof el!='string'&&!(el instanceof Array)){return el;} -if(typeof el=='string'){return document.getElementById(el);} -else{var collection=[];for(var i=0,len=el.length;i<len;++i){collection[collection.length]=Y.Dom.get(el[i]);} -return collection;} -return null;},getStyle:function(el,property){property=toCamel(property);var f=function(element){return getStyle(element,property);};return Y.Dom.batch(el,f,Y.Dom,true);},setStyle:function(el,property,val){property=toCamel(property);var f=function(element){setStyle(element,property,val);};Y.Dom.batch(el,f,Y.Dom,true);},getXY:function(el){var f=function(el){if(el.parentNode===null||el.offsetParent===null||this.getStyle(el,'display')=='none'){return false;} -var parentNode=null;var pos=[];var box;if(el.getBoundingClientRect){box=el.getBoundingClientRect();var doc=document;if(!this.inDocument(el)&&parent.document!=document){doc=parent.document;if(!this.isAncestor(doc.documentElement,el)){return false;}} -var scrollTop=Math.max(doc.documentElement.scrollTop,doc.body.scrollTop);var scrollLeft=Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft);return[box.left+scrollLeft,box.top+scrollTop];} -else{pos=[el.offsetLeft,el.offsetTop];parentNode=el.offsetParent;if(parentNode!=el){while(parentNode){pos[0]+=parentNode.offsetLeft;pos[1]+=parentNode.offsetTop;parentNode=parentNode.offsetParent;}} -if(isSafari&&this.getStyle(el,'position')=='absolute'){pos[0]-=document.body.offsetLeft;pos[1]-=document.body.offsetTop;}} -if(el.parentNode){parentNode=el.parentNode;} -else{parentNode=null;} -while(parentNode&&parentNode.tagName.toUpperCase()!='BODY'&&parentNode.tagName.toUpperCase()!='HTML') -{if(Y.Dom.getStyle(parentNode,'display')!='inline'){pos[0]-=parentNode.scrollLeft;pos[1]-=parentNode.scrollTop;} -if(parentNode.parentNode){parentNode=parentNode.parentNode;}else{parentNode=null;}} -return pos;};return Y.Dom.batch(el,f,Y.Dom,true);},getX:function(el){var f=function(el){return Y.Dom.getXY(el)[0];};return Y.Dom.batch(el,f,Y.Dom,true);},getY:function(el){var f=function(el){return Y.Dom.getXY(el)[1];};return Y.Dom.batch(el,f,Y.Dom,true);},setXY:function(el,pos,noRetry){var f=function(el){var style_pos=this.getStyle(el,'position');if(style_pos=='static'){this.setStyle(el,'position','relative');style_pos='relative';} -var pageXY=this.getXY(el);if(pageXY===false){return false;} -var delta=[parseInt(this.getStyle(el,'left'),10),parseInt(this.getStyle(el,'top'),10)];if(isNaN(delta[0])){delta[0]=(style_pos=='relative')?0:el.offsetLeft;} -if(isNaN(delta[1])){delta[1]=(style_pos=='relative')?0:el.offsetTop;} -if(pos[0]!==null){el.style.left=pos[0]-pageXY[0]+delta[0]+'px';} -if(pos[1]!==null){el.style.top=pos[1]-pageXY[1]+delta[1]+'px';} -if(!noRetry){var newXY=this.getXY(el);if((pos[0]!==null&&newXY[0]!=pos[0])||(pos[1]!==null&&newXY[1]!=pos[1])){this.setXY(el,pos,true);}}};Y.Dom.batch(el,f,Y.Dom,true);},setX:function(el,x){Y.Dom.setXY(el,[x,null]);},setY:function(el,y){Y.Dom.setXY(el,[null,y]);},getRegion:function(el){var f=function(el){var region=new Y.Region.getRegion(el);return region;};return Y.Dom.batch(el,f,Y.Dom,true);},getClientWidth:function(){return Y.Dom.getViewportWidth();},getClientHeight:function(){return Y.Dom.getViewportHeight();},getElementsByClassName:function(className,tag,root){var method=function(el){return Y.Dom.hasClass(el,className);};return Y.Dom.getElementsBy(method,tag,root);},hasClass:function(el,className){var re=new RegExp('(?:^|\\s+)'+className+'(?:\\s+|$)');var f=function(el){return re.test(el['className']);};return Y.Dom.batch(el,f,Y.Dom,true);},addClass:function(el,className){var f=function(el){if(this.hasClass(el,className)){return;} -el['className']=[el['className'],className].join(' ');};Y.Dom.batch(el,f,Y.Dom,true);},removeClass:function(el,className){var re=new RegExp('(?:^|\\s+)'+className+'(?:\\s+|$)','g');var f=function(el){if(!this.hasClass(el,className)){return;} -var c=el['className'];el['className']=c.replace(re,' ');if(this.hasClass(el,className)){this.removeClass(el,className);}};Y.Dom.batch(el,f,Y.Dom,true);},replaceClass:function(el,oldClassName,newClassName){if(oldClassName===newClassName){return false;} -var re=new RegExp('(?:^|\\s+)'+oldClassName+'(?:\\s+|$)','g');var f=function(el){if(!this.hasClass(el,oldClassName)){this.addClass(el,newClassName);return;} -el['className']=el['className'].replace(re,' '+newClassName+' ');if(this.hasClass(el,oldClassName)){this.replaceClass(el,oldClassName,newClassName);}};Y.Dom.batch(el,f,Y.Dom,true);},generateId:function(el,prefix){prefix=prefix||'yui-gen';el=el||{};var f=function(el){if(el){el=Y.Dom.get(el);}else{el={};} -if(!el.id){el.id=prefix+id_counter++;} -return el.id;};return Y.Dom.batch(el,f,Y.Dom,true);},isAncestor:function(haystack,needle){haystack=Y.Dom.get(haystack);if(!haystack||!needle){return false;} -var f=function(needle){if(haystack.contains&&!isSafari){return haystack.contains(needle);} -else if(haystack.compareDocumentPosition){return!!(haystack.compareDocumentPosition(needle)&16);} -else{var parent=needle.parentNode;while(parent){if(parent==haystack){return true;} -else if(!parent.tagName||parent.tagName.toUpperCase()=='HTML'){return false;} -parent=parent.parentNode;} -return false;}};return Y.Dom.batch(needle,f,Y.Dom,true);},inDocument:function(el){var f=function(el){return this.isAncestor(document.documentElement,el);};return Y.Dom.batch(el,f,Y.Dom,true);},getElementsBy:function(method,tag,root){tag=tag||'*';var nodes=[];if(root){root=Y.Dom.get(root);if(!root){return nodes;}}else{root=document;} -var elements=root.getElementsByTagName(tag);if(!elements.length&&(tag=='*'&&root.all)){elements=root.all;} -for(var i=0,len=elements.length;i<len;++i){if(method(elements[i])){nodes[nodes.length]=elements[i];}} -return nodes;},batch:function(el,method,o,override){var id=el;el=Y.Dom.get(el);var scope=(override)?o:window;if(!el||el.tagName||!el.length){if(!el){return false;} -return method.call(scope,el,o);} -var collection=[];for(var i=0,len=el.length;i<len;++i){if(!el[i]){id=el[i];} -collection[collection.length]=method.call(scope,el[i],o);} -return collection;},getDocumentHeight:function(){var scrollHeight=(document.compatMode!='CSS1Compat')?document.body.scrollHeight:document.documentElement.scrollHeight;var h=Math.max(scrollHeight,Y.Dom.getViewportHeight());return h;},getDocumentWidth:function(){var scrollWidth=(document.compatMode!='CSS1Compat')?document.body.scrollWidth:document.documentElement.scrollWidth;var w=Math.max(scrollWidth,Y.Dom.getViewportWidth());return w;},getViewportHeight:function(){var height=self.innerHeight;var mode=document.compatMode;if((mode||isIE)&&!isOpera){height=(mode=='CSS1Compat')?document.documentElement.clientHeight:document.body.clientHeight;} -return height;},getViewportWidth:function(){var width=self.innerWidth;var mode=document.compatMode;if(mode||isIE){width=(mode=='CSS1Compat')?document.documentElement.clientWidth:document.body.clientWidth;} -return width;}};})();YAHOO.util.Region=function(t,r,b,l){this.top=t;this[1]=t;this.right=r;this.bottom=b;this.left=l;this[0]=l;};YAHOO.util.Region.prototype.contains=function(region){return(region.left>=this.left&®ion.right<=this.right&®ion.top>=this.top&®ion.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(region){var t=Math.max(this.top,region.top);var r=Math.min(this.right,region.right);var b=Math.min(this.bottom,region.bottom);var l=Math.max(this.left,region.left);if(b>=t&&r>=l){return new YAHOO.util.Region(t,r,b,l);}else{return null;}};YAHOO.util.Region.prototype.union=function(region){var t=Math.min(this.top,region.top);var r=Math.max(this.right,region.right);var b=Math.max(this.bottom,region.bottom);var l=Math.min(this.left,region.left);return new YAHOO.util.Region(t,r,b,l);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+"}");};YAHOO.util.Region.getRegion=function(el){var p=YAHOO.util.Dom.getXY(el);var t=p[1];var r=p[0]+el.offsetWidth;var b=p[1]+el.offsetHeight;var l=p[0];return new YAHOO.util.Region(t,r,b,l);};YAHOO.util.Point=function(x,y){if(x instanceof Array){y=x[1];x=x[0];} -this.x=this.right=this.left=this[0]=x;this.y=this.top=this.bottom=this[1]=y;};YAHOO.util.Point.prototype=new YAHOO.util.Region();
\ No newline at end of file diff --git a/reports/site_media/yui/dom/dom.js b/reports/site_media/yui/dom/dom.js deleted file mode 100644 index c37bd1b04..000000000 --- a/reports/site_media/yui/dom/dom.js +++ /dev/null @@ -1,892 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ -/** - * The dom module provides helper methods for manipulating Dom elements. - * @module dom - * - */ - -(function() { - var Y = YAHOO.util, // internal shorthand - getStyle, // for load time browser branching - setStyle, // ditto - id_counter = 0, // for use with generateId - propertyCache = {}; // for faster hyphen converts - - // brower detection - var ua = navigator.userAgent.toLowerCase(), - isOpera = (ua.indexOf('opera') > -1), - isSafari = (ua.indexOf('safari') > -1), - isGecko = (!isOpera && !isSafari && ua.indexOf('gecko') > -1), - isIE = (!isOpera && ua.indexOf('msie') > -1); - - // regex cache - var patterns = { - HYPHEN: /(-[a-z])/i - }; - - - var toCamel = function(property) { - if ( !patterns.HYPHEN.test(property) ) { - return property; // no hyphens - } - - if (propertyCache[property]) { // already converted - return propertyCache[property]; - } - - while( patterns.HYPHEN.exec(property) ) { - property = property.replace(RegExp.$1, - RegExp.$1.substr(1).toUpperCase()); - } - - propertyCache[property] = property; - return property; - //return property.replace(/-([a-z])/gi, function(m0, m1) {return m1.toUpperCase()}) // cant use function as 2nd arg yet due to safari bug - }; - - // branching at load instead of runtime - if (document.defaultView && document.defaultView.getComputedStyle) { // W3C DOM method - getStyle = function(el, property) { - var value = null; - - var computed = document.defaultView.getComputedStyle(el, ''); - if (computed) { // test computed before touching for safari - value = computed[toCamel(property)]; - } - - return el.style[property] || value; - }; - } else if (document.documentElement.currentStyle && isIE) { // IE method - getStyle = function(el, property) { - switch( toCamel(property) ) { - case 'opacity' :// IE opacity uses filter - var val = 100; - try { // will error if no DXImageTransform - val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity; - - } catch(e) { - try { // make sure its in the document - val = el.filters('alpha').opacity; - } catch(e) { - } - } - return val / 100; - break; - default: - // test currentStyle before touching - var value = el.currentStyle ? el.currentStyle[property] : null; - return ( el.style[property] || value ); - } - }; - } else { // default to inline only - getStyle = function(el, property) { return el.style[property]; }; - } - - if (isIE) { - setStyle = function(el, property, val) { - switch (property) { - case 'opacity': - if ( typeof el.style.filter == 'string' ) { // in case not appended - el.style.filter = 'alpha(opacity=' + val * 100 + ')'; - - if (!el.currentStyle || !el.currentStyle.hasLayout) { - el.style.zoom = 1; // when no layout or cant tell - } - } - break; - default: - el.style[property] = val; - } - }; - } else { - setStyle = function(el, property, val) { - el.style[property] = val; - }; - } - - /** - * Provides helper methods for DOM elements. - * @namespace YAHOO.util - * @class Dom - */ - YAHOO.util.Dom = { - /** - * Returns an HTMLElement reference. - * @method get - * @param {String | HTMLElement |Array} el Accepts a string to use as an ID for getting a DOM reference, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @return {HTMLElement | Array} A DOM reference to an HTML element or an array of HTMLElements. - */ - get: function(el) { - if (!el) { return null; } // nothing to work with - - if (typeof el != 'string' && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is - return el; - } - - if (typeof el == 'string') { // ID - return document.getElementById(el); - } - else { // array of ID's and/or elements - var collection = []; - for (var i = 0, len = el.length; i < len; ++i) { - collection[collection.length] = Y.Dom.get(el[i]); - } - - return collection; - } - - return null; // safety, should never happen - }, - - /** - * Normalizes currentStyle and ComputedStyle. - * @method getStyle - * @param {String | HTMLElement |Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {String} property The style property whose value is returned. - * @return {String | Array} The current value of the style property for the element(s). - */ - getStyle: function(el, property) { - property = toCamel(property); - - var f = function(element) { - return getStyle(element, property); - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Wrapper for setting style properties of HTMLElements. Normalizes "opacity" across modern browsers. - * @method setStyle - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {String} property The style property to be set. - * @param {String} val The value to apply to the given property. - */ - setStyle: function(el, property, val) { - property = toCamel(property); - - var f = function(element) { - setStyle(element, property, val); - - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Gets the current position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method getXY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @return {Array} The XY position of the element(s) - */ - getXY: function(el) { - var f = function(el) { - - // has to be part of document to have pageXY - if (el.parentNode === null || el.offsetParent === null || - this.getStyle(el, 'display') == 'none') { - return false; - } - - var parentNode = null; - var pos = []; - var box; - - if (el.getBoundingClientRect) { // IE - box = el.getBoundingClientRect(); - var doc = document; - if ( !this.inDocument(el) && parent.document != document) {// might be in a frame, need to get its scroll - doc = parent.document; - - if ( !this.isAncestor(doc.documentElement, el) ) { - return false; - } - - } - - var scrollTop = Math.max(doc.documentElement.scrollTop, doc.body.scrollTop); - var scrollLeft = Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft); - - return [box.left + scrollLeft, box.top + scrollTop]; - } - else { // safari, opera, & gecko - pos = [el.offsetLeft, el.offsetTop]; - parentNode = el.offsetParent; - if (parentNode != el) { - while (parentNode) { - pos[0] += parentNode.offsetLeft; - pos[1] += parentNode.offsetTop; - parentNode = parentNode.offsetParent; - } - } - if (isSafari && this.getStyle(el, 'position') == 'absolute' ) { // safari doubles in some cases - pos[0] -= document.body.offsetLeft; - pos[1] -= document.body.offsetTop; - } - } - - if (el.parentNode) { parentNode = el.parentNode; } - else { parentNode = null; } - - while (parentNode && parentNode.tagName.toUpperCase() != 'BODY' && parentNode.tagName.toUpperCase() != 'HTML') - { // account for any scrolled ancestors - if (Y.Dom.getStyle(parentNode, 'display') != 'inline') { // work around opera inline scrollLeft/Top bug - pos[0] -= parentNode.scrollLeft; - pos[1] -= parentNode.scrollTop; - } - - if (parentNode.parentNode) { - parentNode = parentNode.parentNode; - } else { parentNode = null; } - } - - - return pos; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Gets the current X position of an element based on page coordinates. The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method getX - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @return {String | Array} The X position of the element(s) - */ - getX: function(el) { - var f = function(el) { - return Y.Dom.getXY(el)[0]; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Gets the current Y position of an element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method getY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @return {String | Array} The Y position of the element(s) - */ - getY: function(el) { - var f = function(el) { - return Y.Dom.getXY(el)[1]; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Set the position of an html element in page coordinates, regardless of how the element is positioned. - * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setXY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements - * @param {Array} pos Contains X & Y values for new position (coordinates are page-based) - * @param {Boolean} noRetry By default we try and set the position a second time if the first fails - */ - setXY: function(el, pos, noRetry) { - var f = function(el) { - var style_pos = this.getStyle(el, 'position'); - if (style_pos == 'static') { // default to relative - this.setStyle(el, 'position', 'relative'); - style_pos = 'relative'; - } - - var pageXY = this.getXY(el); - if (pageXY === false) { // has to be part of doc to have pageXY - return false; - } - - var delta = [ // assuming pixels; if not we will have to retry - parseInt( this.getStyle(el, 'left'), 10 ), - parseInt( this.getStyle(el, 'top'), 10 ) - ]; - - if ( isNaN(delta[0]) ) {// in case of 'auto' - delta[0] = (style_pos == 'relative') ? 0 : el.offsetLeft; - } - if ( isNaN(delta[1]) ) { // in case of 'auto' - delta[1] = (style_pos == 'relative') ? 0 : el.offsetTop; - } - - if (pos[0] !== null) { el.style.left = pos[0] - pageXY[0] + delta[0] + 'px'; } - if (pos[1] !== null) { el.style.top = pos[1] - pageXY[1] + delta[1] + 'px'; } - - if (!noRetry) { - var newXY = this.getXY(el); - - // if retry is true, try one more time if we miss - if ( (pos[0] !== null && newXY[0] != pos[0]) || - (pos[1] !== null && newXY[1] != pos[1]) ) { - this.setXY(el, pos, true); - } - } - - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Set the X position of an html element in page coordinates, regardless of how the element is positioned. - * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setX - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {Int} x The value to use as the X coordinate for the element(s). - */ - setX: function(el, x) { - Y.Dom.setXY(el, [x, null]); - }, - - /** - * Set the Y position of an html element in page coordinates, regardless of how the element is positioned. - * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setY - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @param {Int} x To use as the Y coordinate for the element(s). - */ - setY: function(el, y) { - Y.Dom.setXY(el, [null, y]); - }, - - /** - * Returns the region position of the given element. - * The element must be part of the DOM tree to have a region (display:none or elements not appended return false). - * @method getRegion - * @param {String | HTMLElement | Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements. - * @return {Region | Array} A Region or array of Region instances containing "top, left, bottom, right" member data. - */ - getRegion: function(el) { - var f = function(el) { - var region = new Y.Region.getRegion(el); - return region; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Returns the width of the client (viewport). - * @method getClientWidth - * @deprecated Now using getViewportWidth. This interface left intact for back compat. - * @return {Int} The width of the viewable area of the page. - */ - getClientWidth: function() { - return Y.Dom.getViewportWidth(); - }, - - /** - * Returns the height of the client (viewport). - * @method getClientHeight - * @deprecated Now using getViewportHeight. This interface left intact for back compat. - * @return {Int} The height of the viewable area of the page. - */ - getClientHeight: function() { - return Y.Dom.getViewportHeight(); - }, - - /** - * Returns a array of HTMLElements with the given class. - * For optimized performance, include a tag and/or root node when possible. - * @method getElementsByClassName - * @param {String} className The class name to match against - * @param {String} tag (optional) The tag name of the elements being collected - * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point - * @return {Array} An array of elements that have the given class name - */ - getElementsByClassName: function(className, tag, root) { - var method = function(el) { return Y.Dom.hasClass(el, className); }; - return Y.Dom.getElementsBy(method, tag, root); - }, - - /** - * Determines whether an HTMLElement has the given className. - * @method hasClass - * @param {String | HTMLElement | Array} el The element or collection to test - * @param {String} className the class name to search for - * @return {Boolean | Array} A boolean value or array of boolean values - */ - hasClass: function(el, className) { - var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'); - - var f = function(el) { - return re.test(el['className']); - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Adds a class name to a given element or collection of elements. - * @method addClass - * @param {String | HTMLElement | Array} el The element or collection to add the class to - * @param {String} className the class name to add to the class attribute - */ - addClass: function(el, className) { - var f = function(el) { - if (this.hasClass(el, className)) { return; } // already present - - - el['className'] = [el['className'], className].join(' '); - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Removes a class name from a given element or collection of elements. - * @method removeClass - * @param {String | HTMLElement | Array} el The element or collection to remove the class from - * @param {String} className the class name to remove from the class attribute - */ - removeClass: function(el, className) { - var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', 'g'); - - var f = function(el) { - if (!this.hasClass(el, className)) { return; } // not present - - - var c = el['className']; - el['className'] = c.replace(re, ' '); - if ( this.hasClass(el, className) ) { // in case of multiple adjacent - this.removeClass(el, className); - } - - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Replace a class with another class for a given element or collection of elements. - * If no oldClassName is present, the newClassName is simply added. - * @method replaceClass - * @param {String | HTMLElement | Array} el The element or collection to remove the class from - * @param {String} oldClassName the class name to be replaced - * @param {String} newClassName the class name that will be replacing the old class name - */ - replaceClass: function(el, oldClassName, newClassName) { - if (oldClassName === newClassName) { // avoid infinite loop - return false; - } - - var re = new RegExp('(?:^|\\s+)' + oldClassName + '(?:\\s+|$)', 'g'); - - var f = function(el) { - - if ( !this.hasClass(el, oldClassName) ) { - this.addClass(el, newClassName); // just add it if nothing to replace - return; // note return - } - - el['className'] = el['className'].replace(re, ' ' + newClassName + ' '); - - if ( this.hasClass(el, oldClassName) ) { // in case of multiple adjacent - this.replaceClass(el, oldClassName, newClassName); - } - }; - - Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Generates a unique ID - * @method generateId - * @param {String | HTMLElement | Array} el (optional) An optional element array of elements to add an ID to (no ID is added if one is already present). - * @param {String} prefix (optional) an optional prefix to use (defaults to "yui-gen"). - * @return {String | Array} The generated ID, or array of generated IDs (or original ID if already present on an element) - */ - generateId: function(el, prefix) { - prefix = prefix || 'yui-gen'; - el = el || {}; - - var f = function(el) { - if (el) { - el = Y.Dom.get(el); - } else { - el = {}; // just generating ID in this case - } - - if (!el.id) { - el.id = prefix + id_counter++; - } // dont override existing - - - return el.id; - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Determines whether an HTMLElement is an ancestor of another HTML element in the DOM hierarchy. - * @method isAncestor - * @param {String | HTMLElement} haystack The possible ancestor - * @param {String | HTMLElement} needle The possible descendent - * @return {Boolean} Whether or not the haystack is an ancestor of needle - */ - isAncestor: function(haystack, needle) { - haystack = Y.Dom.get(haystack); - if (!haystack || !needle) { return false; } - - var f = function(needle) { - if (haystack.contains && !isSafari) { // safari "contains" is broken - return haystack.contains(needle); - } - else if ( haystack.compareDocumentPosition ) { - return !!(haystack.compareDocumentPosition(needle) & 16); - } - else { // loop up and test each parent - var parent = needle.parentNode; - - while (parent) { - if (parent == haystack) { - return true; - } - else if (!parent.tagName || parent.tagName.toUpperCase() == 'HTML') { - return false; - } - - parent = parent.parentNode; - } - return false; - } - }; - - return Y.Dom.batch(needle, f, Y.Dom, true); - }, - - /** - * Determines whether an HTMLElement is present in the current document. - * @method inDocument - * @param {String | HTMLElement} el The element to search for - * @return {Boolean} Whether or not the element is present in the current document - */ - inDocument: function(el) { - var f = function(el) { - return this.isAncestor(document.documentElement, el); - }; - - return Y.Dom.batch(el, f, Y.Dom, true); - }, - - /** - * Returns a array of HTMLElements that pass the test applied by supplied boolean method. - * For optimized performance, include a tag and/or root node when possible. - * @method getElementsBy - * @param {Function} method - A boolean method for testing elements which receives the element as its only argument. - - * @param {String} tag (optional) The tag name of the elements being collected - * @param {String | HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point - */ - getElementsBy: function(method, tag, root) { - tag = tag || '*'; - - var nodes = []; - - if (root) { - root = Y.Dom.get(root); - if (!root) { // if no root node, then no children - return nodes; - } - } else { - root = document; - } - - var elements = root.getElementsByTagName(tag); - - if ( !elements.length && (tag == '*' && root.all) ) { - elements = root.all; // IE < 6 - } - - for (var i = 0, len = elements.length; i < len; ++i) { - if ( method(elements[i]) ) { nodes[nodes.length] = elements[i]; } - } - - - return nodes; - }, - - /** - * Returns an array of elements that have had the supplied method applied. - * The method is called with the element(s) as the first arg, and the optional param as the second ( method(el, o) ). - * @method batch - * @param {String | HTMLElement | Array} el (optional) An element or array of elements to apply the method to - * @param {Function} method The method to apply to the element(s) - * @param {Any} o (optional) An optional arg that is passed to the supplied method - * @param {Boolean} override (optional) Whether or not to override the scope of "method" with "o" - * @return {HTMLElement | Array} The element(s) with the method applied - */ - batch: function(el, method, o, override) { - var id = el; - el = Y.Dom.get(el); - - var scope = (override) ? o : window; - - if (!el || el.tagName || !el.length) { // is null or not a collection (tagName for SELECT and others that can be both an element and a collection) - if (!el) { - return false; - } - return method.call(scope, el, o); - } - - var collection = []; - - for (var i = 0, len = el.length; i < len; ++i) { - if (!el[i]) { - id = el[i]; - } - collection[collection.length] = method.call(scope, el[i], o); - } - - return collection; - }, - - /** - * Returns the height of the document. - * @method getDocumentHeight - * @return {Int} The height of the actual document (which includes the body and its margin). - */ - getDocumentHeight: function() { - var scrollHeight = (document.compatMode != 'CSS1Compat') ? document.body.scrollHeight : document.documentElement.scrollHeight; - - var h = Math.max(scrollHeight, Y.Dom.getViewportHeight()); - return h; - }, - - /** - * Returns the width of the document. - * @method getDocumentWidth - * @return {Int} The width of the actual document (which includes the body and its margin). - */ - getDocumentWidth: function() { - var scrollWidth = (document.compatMode != 'CSS1Compat') ? document.body.scrollWidth : document.documentElement.scrollWidth; - var w = Math.max(scrollWidth, Y.Dom.getViewportWidth()); - return w; - }, - - /** - * Returns the current height of the viewport. - * @method getViewportHeight - * @return {Int} The height of the viewable area of the page (excludes scrollbars). - */ - getViewportHeight: function() { - var height = self.innerHeight; // Safari, Opera - var mode = document.compatMode; - - if ( (mode || isIE) && !isOpera ) { // IE, Gecko - height = (mode == 'CSS1Compat') ? - document.documentElement.clientHeight : // Standards - document.body.clientHeight; // Quirks - } - - return height; - }, - - /** - * Returns the current width of the viewport. - * @method getViewportWidth - * @return {Int} The width of the viewable area of the page (excludes scrollbars). - */ - - getViewportWidth: function() { - var width = self.innerWidth; // Safari - var mode = document.compatMode; - - if (mode || isIE) { // IE, Gecko, Opera - width = (mode == 'CSS1Compat') ? - document.documentElement.clientWidth : // Standards - document.body.clientWidth; // Quirks - } - return width; - } - }; -})(); -/** - * A region is a representation of an object on a grid. It is defined - * by the top, right, bottom, left extents, so is rectangular by default. If - * other shapes are required, this class could be extended to support it. - * @namespace YAHOO.util - * @class Region - * @param {Int} t the top extent - * @param {Int} r the right extent - * @param {Int} b the bottom extent - * @param {Int} l the left extent - * @constructor - */ -YAHOO.util.Region = function(t, r, b, l) { - - /** - * The region's top extent - * @property top - * @type Int - */ - this.top = t; - - /** - * The region's top extent as index, for symmetry with set/getXY - * @property 1 - * @type Int - */ - this[1] = t; - - /** - * The region's right extent - * @property right - * @type int - */ - this.right = r; - - /** - * The region's bottom extent - * @property bottom - * @type Int - */ - this.bottom = b; - - /** - * The region's left extent - * @property left - * @type Int - */ - this.left = l; - - /** - * The region's left extent as index, for symmetry with set/getXY - * @property 0 - * @type Int - */ - this[0] = l; -}; - -/** - * Returns true if this region contains the region passed in - * @method contains - * @param {Region} region The region to evaluate - * @return {Boolean} True if the region is contained with this region, - * else false - */ -YAHOO.util.Region.prototype.contains = function(region) { - return ( region.left >= this.left && - region.right <= this.right && - region.top >= this.top && - region.bottom <= this.bottom ); - -}; - -/** - * Returns the area of the region - * @method getArea - * @return {Int} the region's area - */ -YAHOO.util.Region.prototype.getArea = function() { - return ( (this.bottom - this.top) * (this.right - this.left) ); -}; - -/** - * Returns the region where the passed in region overlaps with this one - * @method intersect - * @param {Region} region The region that intersects - * @return {Region} The overlap region, or null if there is no overlap - */ -YAHOO.util.Region.prototype.intersect = function(region) { - var t = Math.max( this.top, region.top ); - var r = Math.min( this.right, region.right ); - var b = Math.min( this.bottom, region.bottom ); - var l = Math.max( this.left, region.left ); - - if (b >= t && r >= l) { - return new YAHOO.util.Region(t, r, b, l); - } else { - return null; - } -}; - -/** - * Returns the region representing the smallest region that can contain both - * the passed in region and this region. - * @method union - * @param {Region} region The region that to create the union with - * @return {Region} The union region - */ -YAHOO.util.Region.prototype.union = function(region) { - var t = Math.min( this.top, region.top ); - var r = Math.max( this.right, region.right ); - var b = Math.max( this.bottom, region.bottom ); - var l = Math.min( this.left, region.left ); - - return new YAHOO.util.Region(t, r, b, l); -}; - -/** - * toString - * @method toString - * @return string the region properties - */ -YAHOO.util.Region.prototype.toString = function() { - return ( "Region {" + - "top: " + this.top + - ", right: " + this.right + - ", bottom: " + this.bottom + - ", left: " + this.left + - "}" ); -}; - -/** - * Returns a region that is occupied by the DOM element - * @method getRegion - * @param {HTMLElement} el The element - * @return {Region} The region that the element occupies - * @static - */ -YAHOO.util.Region.getRegion = function(el) { - var p = YAHOO.util.Dom.getXY(el); - - var t = p[1]; - var r = p[0] + el.offsetWidth; - var b = p[1] + el.offsetHeight; - var l = p[0]; - - return new YAHOO.util.Region(t, r, b, l); -}; - -///////////////////////////////////////////////////////////////////////////// - -/** - * A point is a region that is special in that it represents a single point on - * the grid. - * @namespace YAHOO.util - * @class Point - * @param {Int} x The X position of the point - * @param {Int} y The Y position of the point - * @constructor - * @extends YAHOO.util.Region - */ -YAHOO.util.Point = function(x, y) { - if (x instanceof Array) { // accept output from Dom.getXY - y = x[1]; - x = x[0]; - } - - /** - * The X position of the point, which is also the right, left and index zero (for Dom.getXY symmetry) - * @property x - * @type Int - */ - - this.x = this.right = this.left = this[0] = x; - - /** - * The Y position of the point, which is also the top, bottom and index one (for Dom.getXY symmetry) - * @property y - * @type Int - */ - this.y = this.top = this.bottom = this[1] = y; -}; - -YAHOO.util.Point.prototype = new YAHOO.util.Region(); - diff --git a/reports/site_media/yui/event/README b/reports/site_media/yui/event/README deleted file mode 100644 index 18defb61c..000000000 --- a/reports/site_media/yui/event/README +++ /dev/null @@ -1,135 +0,0 @@ - -YUI Library - Event - Release Notes - -0.12.2 - - * Fixed a bug introduced in 0.12.1 release caused nested onAvailable - calls to fail. - -0.12.1 - - * If an error is thrown during the browser-specific add/remove lister call, - addListener/removeListener will catch the error and return false. - - * onAvailable array items are nulled out instead of deleted when completed to - get around an Opera issue introduced in a recent version of the browser. - -0.12.0 - - * If the function argument is not provided to Event.removeListener, all - all listeners for the specified event type on the element will be removed. - - * CustomEvent now has an optional parameter that defines the signature of - the listeners for this event. Two signatures are supported: - - YAHOO.util.CustomEvent.LIST: - param1: event name - param2: array of arguments provided to fire() - param3: <optional> the custom object supplied to subscribe() - - YAHOO.util.CustomEvent.FLAT: - param1: the first argument provided to fire() - param2: <optional> the custom object supplied to subscribe() - - The new flat signature makes it possible to provide a better API - when using custom events, and it makes it possible to transparently - wrap DOM events. - - * The parameters for overriding scope in both Event.addListener, and - CustomEvent.subscribe have been augmented. In addition to the - previous behavior where a true value would make the previous parameter - the execution scope, an object can be supplied instead. If an object - is provided, that object becomes the scope obj. This makes it possible - to pass a both a custom object and adjust the scope to a different object. - - * Added EventProvider, which is a wrapper for CustomEvent that makes it - possible to subscribe to events by name, whether or not the event has - been created. This class was designed to be used with YAHOO.augment. - EventProvider custom events are created with the new FLAT listener - signature. - - * CustomEvent subscribers can return false to stop the propagation of - the event. - - * CustomEvents now have an onSubscribe custom event that can used to the - case where a subscriber subscribes to an one-time event that has already - happened. Also provides a way for the implementer to defer initialization - logic until after the first subscription. - - * Event.getCharCode now always returns keyCode if charCode is not available. - - * Added Event.onContentReady, which is similar to onAvailable, but it also - checks simblings to try to determine when the element's children are - available. - -0.11.4 - - * Fixed a memory leak in IE6 that occurred when the utility was hosted in - an iframe. - - * Fixed an issue with Safari click listeners when listeners were removed. - -0.11.3 - - * The listener cache is now pruned when events are removed. This fixes - a performance issue when adding many listeners, removing them, and - adding them again repeatedly. - - * Safari click listeners will work correctly if a bound element is removed - from the DOM and a new element with the same ID is added. - - * Removed the code that automatically unsubscribed custom event listeners. - -0.11.0 - - * Added Event.purgeElement which will remove all listeners added via - addListener from the supplied element. If an optional "type" parameter - is supplied, only events of that type will be removed. Optionally, the - purge can be performed recursively on the element's children as well. - - * Added Event.getListeners which will return all listeners attached to - a given element.. either all listeners or listeners of a specific type. - - * getTarget now automatically resolves text nodes. The optional parameter - for this feature is now deprecated. - - * getRelatedTarget now resolves text nodes for the browsers that return the - text node rather than its host HTML element. - - * CustomEvent now logs the custom event activity if the logger widget is available - -0.10.0 - - * Added Safari dblclick to the list of legacy events. - - * When multiple identical event handlers are defined, multiple calls - to removeListener can now remove all of them. - - * removeListener works properly for unload events - - * Legacy event bookkeeping is more efficient, improving the performance for - adding Safari click events. - - * _unload() is more efficient, improving the page transition experience in - Safari in particular. - - * addListener, removeListener now return false if the function argument is - not valid. - - * Fixed an operator precedence issue in getCharCode. - - * Added Event.getXY, which returns [Event.getPageX(e), Event.getPageY(e)] - - * Added Event.onAvailable, which will execute the callback when the element - with the supplied id is found. Currently searches periodically until the - window load event or for up to 10 seconds after the onAvailable method - was executed. - - * The lazy listener attachment process now will poll beyond the window load - event in order to better handle the case when a listener is defined - late in the page but before the element is in the dom. - - * Fixed browser detection for Opera installations reporting as IE. - - * It is now possible to remove and re-add legacy events (Safari click event). - diff --git a/reports/site_media/yui/event/event-debug.js b/reports/site_media/yui/event/event-debug.js deleted file mode 100644 index 468e592e7..000000000 --- a/reports/site_media/yui/event/event-debug.js +++ /dev/null @@ -1,1797 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ - - -/** - * The CustomEvent class lets you define events for your application - * that can be subscribed to by one or more independent component. - * - * @param {String} type The type of event, which is passed to the callback - * when the event fires - * @param {Object} oScope The context the event will fire from. "this" will - * refer to this object in the callback. Default value: - * the window object. The listener can override this. - * @param {boolean} silent pass true to prevent the event from writing to - * the debugsystem - * @param {int} signature the signature that the custom event subscriber - * will receive. YAHOO.util.CustomEvent.LIST or - * YAHOO.util.CustomEvent.FLAT. The default is - * YAHOO.util.CustomEvent.LIST. - * @namespace YAHOO.util - * @class CustomEvent - * @constructor - */ -YAHOO.util.CustomEvent = function(type, oScope, silent, signature) { - - /** - * The type of event, returned to subscribers when the event fires - * @property type - * @type string - */ - this.type = type; - - /** - * The scope the the event will fire from by default. Defaults to the window - * obj - * @property scope - * @type object - */ - this.scope = oScope || window; - - /** - * By default all custom events are logged in the debug build, set silent - * to true to disable debug outpu for this event. - * @property silent - * @type boolean - */ - this.silent = silent; - - /** - * Custom events support two styles of arguments provided to the event - * subscribers. - * <ul> - * <li>YAHOO.util.CustomEvent.LIST: - * <ul> - * <li>param1: event name</li> - * <li>param2: array of arguments sent to fire</li> - * <li>param3: <optional> a custom object supplied by the subscriber</li> - * </ul> - * </li> - * <li>YAHOO.util.CustomEvent.FLAT - * <ul> - * <li>param1: the first argument passed to fire. If you need to - * pass multiple parameters, use and array or object literal</li> - * <li>param2: <optional> a custom object supplied by the subscriber</li> - * </ul> - * </li> - * </ul> - * @property signature - * @type int - */ - this.signature = signature || YAHOO.util.CustomEvent.LIST; - - /** - * The subscribers to this event - * @property subscribers - * @type Subscriber[] - */ - this.subscribers = []; - - if (!this.silent) { - YAHOO.log( "Creating " + this, "info", "Event" ); - } - - var onsubscribeType = "_YUICEOnSubscribe"; - - // Only add subscribe events for events that are not generated by - // CustomEvent - if (type !== onsubscribeType) { - - /** - * Custom events provide a custom event that fires whenever there is - * a new subscriber to the event. This provides an opportunity to - * handle the case where there is a non-repeating event that has - * already fired has a new subscriber. - * - * @event subscribeEvent - * @type YAHOO.util.CustomEvent - * @param {Function} fn The function to execute - * @param {Object} obj An object to be passed along when the event - * fires - * @param {boolean|Object} override If true, the obj passed in becomes - * the execution scope of the listener. - * if an object, that object becomes the - * the execution scope. - */ - this.subscribeEvent = - new YAHOO.util.CustomEvent(onsubscribeType, this, true); - - } -}; - -/** - * Subscriber listener sigature constant. The LIST type returns three - * parameters: the event type, the array of args passed to fire, and - * the optional custom object - * @property YAHOO.util.CustomEvent.LIST - * @static - * @type int - */ -YAHOO.util.CustomEvent.LIST = 0; - -/** - * Subscriber listener sigature constant. The FLAT type returns two - * parameters: the first argument passed to fire and the optional - * custom object - * @property YAHOO.util.CustomEvent.FLAT - * @static - * @type int - */ -YAHOO.util.CustomEvent.FLAT = 1; - -YAHOO.util.CustomEvent.prototype = { - - /** - * Subscribes the caller to this event - * @method subscribe - * @param {Function} fn The function to execute - * @param {Object} obj An object to be passed along when the event - * fires - * @param {boolean|Object} override If true, the obj passed in becomes - * the execution scope of the listener. - * if an object, that object becomes the - * the execution scope. - */ - subscribe: function(fn, obj, override) { - if (this.subscribeEvent) { - this.subscribeEvent.fire(fn, obj, override); - } - - this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, override) ); - }, - - /** - * Unsubscribes the caller from this event - * @method unsubscribe - * @param {Function} fn The function to execute - * @param {Object} obj The custom object passed to subscribe (optional) - * @return {boolean} True if the subscriber was found and detached. - */ - unsubscribe: function(fn, obj) { - var found = false; - for (var i=0, len=this.subscribers.length; i<len; ++i) { - var s = this.subscribers[i]; - if (s && s.contains(fn, obj)) { - this._delete(i); - found = true; - } - } - - return found; - }, - - /** - * Notifies the subscribers. The callback functions will be executed - * from the scope specified when the event was created, and with the - * following parameters: - * <ul> - * <li>The type of event</li> - * <li>All of the arguments fire() was executed with as an array</li> - * <li>The custom object (if any) that was passed into the subscribe() - * method</li> - * </ul> - * @method fire - * @param {Object*} arguments an arbitrary set of parameters to pass to - * the handler. - * @return {boolean} false if one of the subscribers returned false, - * true otherwise - */ - fire: function() { - var len=this.subscribers.length; - if (!len && this.silent) { - return true; - } - - var args=[], ret=true, i; - - for (i=0; i<arguments.length; ++i) { - args.push(arguments[i]); - } - - var argslength = args.length; - - if (!this.silent) { - YAHOO.log( "Firing " + this + ", " + - "args: " + args + ", " + - "subscribers: " + len, - "info", "Event" ); - } - - for (i=0; i<len; ++i) { - var s = this.subscribers[i]; - if (s) { - if (!this.silent) { - YAHOO.log( this.type + "->" + (i+1) + ": " + s, - "info", "Event" ); - } - - var scope = s.getScope(this.scope); - - if (this.signature == YAHOO.util.CustomEvent.FLAT) { - var param = null; - if (args.length > 0) { - param = args[0]; - } - ret = s.fn.call(scope, param, s.obj); - } else { - ret = s.fn.call(scope, this.type, args, s.obj); - } - if (false === ret) { - if (!this.silent) { - YAHOO.log("Event cancelled, subscriber " + i + - " of " + len); - } - - //break; - return false; - } - } - } - - return true; - }, - - /** - * Removes all listeners - * @method unsubscribeAll - */ - unsubscribeAll: function() { - for (var i=0, len=this.subscribers.length; i<len; ++i) { - this._delete(len - 1 - i); - } - }, - - /** - * @method _delete - * @private - */ - _delete: function(index) { - var s = this.subscribers[index]; - if (s) { - delete s.fn; - delete s.obj; - } - - // delete this.subscribers[index]; - this.subscribers.splice(index, 1); - }, - - /** - * @method toString - */ - toString: function() { - return "CustomEvent: " + "'" + this.type + "', " + - "scope: " + this.scope; - - } -}; - -///////////////////////////////////////////////////////////////////// - -/** - * Stores the subscriber information to be used when the event fires. - * @param {Function} fn The function to execute - * @param {Object} obj An object to be passed along when the event fires - * @param {boolean} override If true, the obj passed in becomes the execution - * scope of the listener - * @class Subscriber - * @constructor - */ -YAHOO.util.Subscriber = function(fn, obj, override) { - - /** - * The callback that will be execute when the event fires - * @property fn - * @type function - */ - this.fn = fn; - - /** - * An optional custom object that will passed to the callback when - * the event fires - * @property obj - * @type object - */ - this.obj = obj || null; - - /** - * The default execution scope for the event listener is defined when the - * event is created (usually the object which contains the event). - * By setting override to true, the execution scope becomes the custom - * object passed in by the subscriber. If override is an object, that - * object becomes the scope. - * @property override - * @type boolean|object - */ - this.override = override; - -}; - -/** - * Returns the execution scope for this listener. If override was set to true - * the custom obj will be the scope. If override is an object, that is the - * scope, otherwise the default scope will be used. - * @method getScope - * @param {Object} defaultScope the scope to use if this listener does not - * override it. - */ -YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) { - if (this.override) { - if (this.override === true) { - return this.obj; - } else { - return this.override; - } - } - return defaultScope; -}; - -/** - * Returns true if the fn and obj match this objects properties. - * Used by the unsubscribe method to match the right subscriber. - * - * @method contains - * @param {Function} fn the function to execute - * @param {Object} obj an object to be passed along when the event fires - * @return {boolean} true if the supplied arguments match this - * subscriber's signature. - */ -YAHOO.util.Subscriber.prototype.contains = function(fn, obj) { - if (obj) { - return (this.fn == fn && this.obj == obj); - } else { - return (this.fn == fn); - } -}; - -/** - * @method toString - */ -YAHOO.util.Subscriber.prototype.toString = function() { - return "Subscriber { obj: " + (this.obj || "") + - ", override: " + (this.override || "no") + " }"; -}; - -/** - * The Event Utility provides utilities for managing DOM Events and tools - * for building event systems - * - * @module event - * @title Event Utility - * @namespace YAHOO.util - * @requires yahoo - */ - -// The first instance of Event will win if it is loaded more than once. -if (!YAHOO.util.Event) { - -/** - * The event utility provides functions to add and remove event listeners, - * event cleansing. It also tries to automatically remove listeners it - * registers during the unload event. - * - * @class Event - * @static - */ - YAHOO.util.Event = function() { - - /** - * True after the onload event has fired - * @property loadComplete - * @type boolean - * @static - * @private - */ - var loadComplete = false; - - /** - * Cache of wrapped listeners - * @property listeners - * @type array - * @static - * @private - */ - var listeners = []; - - /** - * User-defined unload function that will be fired before all events - * are detached - * @property unloadListeners - * @type array - * @static - * @private - */ - var unloadListeners = []; - - /** - * Cache of DOM0 event handlers to work around issues with DOM2 events - * in Safari - * @property legacyEvents - * @static - * @private - */ - var legacyEvents = []; - - /** - * Listener stack for DOM0 events - * @property legacyHandlers - * @static - * @private - */ - var legacyHandlers = []; - - /** - * The number of times to poll after window.onload. This number is - * increased if additional late-bound handlers are requested after - * the page load. - * @property retryCount - * @static - * @private - */ - var retryCount = 0; - - /** - * onAvailable listeners - * @property onAvailStack - * @static - * @private - */ - var onAvailStack = []; - - /** - * Lookup table for legacy events - * @property legacyMap - * @static - * @private - */ - var legacyMap = []; - - /** - * Counter for auto id generation - * @property counter - * @static - * @private - */ - var counter = 0; - - return { // PREPROCESS - - /** - * The number of times we should look for elements that are not - * in the DOM at the time the event is requested after the document - * has been loaded. The default is 200@amp;50 ms, so it will poll - * for 10 seconds or until all outstanding handlers are bound - * (whichever comes first). - * @property POLL_RETRYS - * @type int - * @static - * @final - */ - POLL_RETRYS: 200, - - /** - * The poll interval in milliseconds - * @property POLL_INTERVAL - * @type int - * @static - * @final - */ - POLL_INTERVAL: 20, - - /** - * Element to bind, int constant - * @property EL - * @type int - * @static - * @final - */ - EL: 0, - - /** - * Type of event, int constant - * @property TYPE - * @type int - * @static - * @final - */ - TYPE: 1, - - /** - * Function to execute, int constant - * @property FN - * @type int - * @static - * @final - */ - FN: 2, - - /** - * Function wrapped for scope correction and cleanup, int constant - * @property WFN - * @type int - * @static - * @final - */ - WFN: 3, - - /** - * Object passed in by the user that will be returned as a - * parameter to the callback, int constant - * @property OBJ - * @type int - * @static - * @final - */ - OBJ: 3, - - /** - * Adjusted scope, either the element we are registering the event - * on or the custom object passed in by the listener, int constant - * @property ADJ_SCOPE - * @type int - * @static - * @final - */ - ADJ_SCOPE: 4, - - /** - * Safari detection is necessary to work around the preventDefault - * bug that makes it so you can't cancel a href click from the - * handler. There is not a capabilities check we can use here. - * @property isSafari - * @private - * @static - */ - isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent), - - /** - * IE detection needed to properly calculate pageX and pageY. - * capabilities checking didn't seem to work because another - * browser that does not provide the properties have the values - * calculated in a different manner than IE. - * @property isIE - * @private - * @static - */ - isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) && - navigator.userAgent.match(/msie/gi)), - - /** - * poll handle - * @property _interval - * @private - */ - _interval: null, - - /** - * @method startInterval - * @static - * @private - */ - startInterval: function() { - if (!this._interval) { - var self = this; - var callback = function() { self._tryPreloadAttach(); }; - this._interval = setInterval(callback, this.POLL_INTERVAL); - // this.timeout = setTimeout(callback, i); - } - }, - - /** - * Executes the supplied callback when the item with the supplied - * id is found. This is meant to be used to execute behavior as - * soon as possible as the page loads. If you use this after the - * initial page load it will poll for a fixed time for the element. - * The number of times it will poll and the frequency are - * configurable. By default it will poll for 10 seconds. - * - * @method onAvailable - * - * @param {string} p_id the id of the element to look for. - * @param {function} p_fn what to execute when the element is found. - * @param {object} p_obj an optional object to be passed back as - * a parameter to p_fn. - * @param {boolean} p_override If set to true, p_fn will execute - * in the scope of p_obj - * - * @static - */ - onAvailable: function(p_id, p_fn, p_obj, p_override) { - onAvailStack.push( { id: p_id, - fn: p_fn, - obj: p_obj, - override: p_override, - checkReady: false } ); - - retryCount = this.POLL_RETRYS; - this.startInterval(); - }, - - /** - * Works the same way as onAvailable, but additionally checks the - * state of sibling elements to determine if the content of the - * available element is safe to modify. - * - * @method onContentReady - * - * @param {string} p_id the id of the element to look for. - * @param {function} p_fn what to execute when the element is ready. - * @param {object} p_obj an optional object to be passed back as - * a parameter to p_fn. - * @param {boolean} p_override If set to true, p_fn will execute - * in the scope of p_obj - * - * @static - */ - onContentReady: function(p_id, p_fn, p_obj, p_override) { - onAvailStack.push( { id: p_id, - fn: p_fn, - obj: p_obj, - override: p_override, - checkReady: true } ); - - retryCount = this.POLL_RETRYS; - this.startInterval(); - }, - - /** - * Appends an event handler - * - * @method addListener - * - * @param {Object} el The html element to assign the - * event to - * @param {String} sType The type of event to append - * @param {Function} fn The method the event invokes - * @param {Object} obj An arbitrary object that will be - * passed as a parameter to the handler - * @param {boolean} override If true, the obj passed in becomes - * the execution scope of the listener - * @return {boolean} True if the action was successful or defered, - * false if one or more of the elements - * could not have the listener attached, - * or if the operation throws an exception. - * @static - */ - addListener: function(el, sType, fn, obj, override) { - - - if (!fn || !fn.call) { - // this.logger.debug("Error, function is not valid " + fn); - return false; - } - - // The el argument can be an array of elements or element ids. - if ( this._isValidCollection(el)) { - var ok = true; - for (var i=0,len=el.length; i<len; ++i) { - ok = this.on(el[i], - sType, - fn, - obj, - override) && ok; - } - return ok; - - } else if (typeof el == "string") { - var oEl = this.getEl(el); - // If the el argument is a string, we assume it is - // actually the id of the element. If the page is loaded - // we convert el to the actual element, otherwise we - // defer attaching the event until onload event fires - - // check to see if we need to delay hooking up the event - // until after the page loads. - if (oEl) { - el = oEl; - } else { - // defer adding the event until the element is available - this.onAvailable(el, function() { - YAHOO.util.Event.on(el, sType, fn, obj, override); - }); - - return true; - } - } - - // Element should be an html element or an array if we get - // here. - if (!el) { - // this.logger.debug("unable to attach event " + sType); - return false; - } - - // we need to make sure we fire registered unload events - // prior to automatically unhooking them. So we hang on to - // these instead of attaching them to the window and fire the - // handles explicitly during our one unload event. - if ("unload" == sType && obj !== this) { - unloadListeners[unloadListeners.length] = - [el, sType, fn, obj, override]; - return true; - } - - // this.logger.debug("Adding handler: " + el + ", " + sType); - - // if the user chooses to override the scope, we use the custom - // object passed in, otherwise the executing scope will be the - // HTML element that the event is registered on - var scope = el; - if (override) { - if (override === true) { - scope = obj; - } else { - scope = override; - } - } - - // wrap the function so we can return the obj object when - // the event fires; - var wrappedFn = function(e) { - return fn.call(scope, YAHOO.util.Event.getEvent(e), - obj); - }; - - var li = [el, sType, fn, wrappedFn, scope]; - var index = listeners.length; - // cache the listener so we can try to automatically unload - listeners[index] = li; - - if (this.useLegacyEvent(el, sType)) { - var legacyIndex = this.getLegacyIndex(el, sType); - - // Add a new dom0 wrapper if one is not detected for this - // element - if ( legacyIndex == -1 || - el != legacyEvents[legacyIndex][0] ) { - - legacyIndex = legacyEvents.length; - legacyMap[el.id + sType] = legacyIndex; - - // cache the signature for the DOM0 event, and - // include the existing handler for the event, if any - legacyEvents[legacyIndex] = - [el, sType, el["on" + sType]]; - legacyHandlers[legacyIndex] = []; - - el["on" + sType] = - function(e) { - YAHOO.util.Event.fireLegacyEvent( - YAHOO.util.Event.getEvent(e), legacyIndex); - }; - } - - // add a reference to the wrapped listener to our custom - // stack of events - //legacyHandlers[legacyIndex].push(index); - legacyHandlers[legacyIndex].push(li); - - } else { - try { - this._simpleAdd(el, sType, wrappedFn, false); - } catch(e) { - // handle an error trying to attach an event. If it fails - // we need to clean up the cache - this.removeListener(el, sType, fn); - return false; - } - } - - return true; - - }, - - /** - * When using legacy events, the handler is routed to this object - * so we can fire our custom listener stack. - * @method fireLegacyEvent - * @static - * @private - */ - fireLegacyEvent: function(e, legacyIndex) { - // this.logger.debug("fireLegacyEvent " + legacyIndex); - var ok = true; - - var le = legacyHandlers[legacyIndex]; - for (var i=0,len=le.length; i<len; ++i) { - var li = le[i]; - if ( li && li[this.WFN] ) { - var scope = li[this.ADJ_SCOPE]; - var ret = li[this.WFN].call(scope, e); - ok = (ok && ret); - } - } - - return ok; - }, - - /** - * Returns the legacy event index that matches the supplied - * signature - * @method getLegacyIndex - * @static - * @private - */ - getLegacyIndex: function(el, sType) { - var key = this.generateId(el) + sType; - if (typeof legacyMap[key] == "undefined") { - return -1; - } else { - return legacyMap[key]; - } - }, - - /** - * Logic that determines when we should automatically use legacy - * events instead of DOM2 events. - * @method useLegacyEvent - * @static - * @private - */ - useLegacyEvent: function(el, sType) { - if (!el.addEventListener && !el.attachEvent) { - return true; - } else if (this.isSafari) { - if ("click" == sType || "dblclick" == sType) { - return true; - } - } - return false; - }, - - /** - * Removes an event handler - * - * @method removeListener - * - * @param {Object} el the html element or the id of the element to - * assign the event to. - * @param {String} sType the type of event to remove. - * @param {Function} fn the method the event invokes. If fn is - * undefined, then all event handlers for the type of event are - * removed. - * @return {boolean} true if the unbind was successful, false - * otherwise. - * @static - */ - removeListener: function(el, sType, fn) { - var i, len; - - // The el argument can be a string - if (typeof el == "string") { - el = this.getEl(el); - // The el argument can be an array of elements or element ids. - } else if ( this._isValidCollection(el)) { - var ok = true; - for (i=0,len=el.length; i<len; ++i) { - ok = ( this.removeListener(el[i], sType, fn) && ok ); - } - return ok; - } - - if (!fn || !fn.call) { - // this.logger.debug("Error, function is not valid " + fn); - //return false; - return this.purgeElement(el, false, sType); - } - - - if ("unload" == sType) { - - for (i=0, len=unloadListeners.length; i<len; i++) { - var li = unloadListeners[i]; - if (li && - li[0] == el && - li[1] == sType && - li[2] == fn) { - unloadListeners.splice(i, 1); - return true; - } - } - - return false; - } - - var cacheItem = null; - - // The index is a hidden parameter; needed to remove it from - // the method signature because it was tempting users to - // try and take advantage of it, which is not possible. - var index = arguments[3]; - - if ("undefined" == typeof index) { - index = this._getCacheIndex(el, sType, fn); - } - - if (index >= 0) { - cacheItem = listeners[index]; - } - - if (!el || !cacheItem) { - // this.logger.debug("cached listener not found"); - return false; - } - - // this.logger.debug("Removing handler: " + el + ", " + sType); - - if (this.useLegacyEvent(el, sType)) { - var legacyIndex = this.getLegacyIndex(el, sType); - var llist = legacyHandlers[legacyIndex]; - if (llist) { - for (i=0, len=llist.length; i<len; ++i) { - li = llist[i]; - if (li && - li[this.EL] == el && - li[this.TYPE] == sType && - li[this.FN] == fn) { - llist.splice(i, 1); - break; - } - } - } - - } else { - try { - this._simpleRemove(el, sType, cacheItem[this.WFN], false); - } catch(e) { - return false; - } - } - - // removed the wrapped handler - delete listeners[index][this.WFN]; - delete listeners[index][this.FN]; - listeners.splice(index, 1); - - return true; - - }, - - /** - * Returns the event's target element - * @method getTarget - * @param {Event} ev the event - * @param {boolean} resolveTextNode when set to true the target's - * parent will be returned if the target is a - * text node. @deprecated, the text node is - * now resolved automatically - * @return {HTMLElement} the event's target - * @static - */ - getTarget: function(ev, resolveTextNode) { - var t = ev.target || ev.srcElement; - return this.resolveTextNode(t); - }, - - /** - * In some cases, some browsers will return a text node inside - * the actual element that was targeted. This normalizes the - * return value for getTarget and getRelatedTarget. - * @method resolveTextNode - * @param {HTMLElement} node node to resolve - * @return {HTMLElement} the normized node - * @static - */ - resolveTextNode: function(node) { - // if (node && node.nodeName && - // "#TEXT" == node.nodeName.toUpperCase()) { - if (node && 3 == node.nodeType) { - return node.parentNode; - } else { - return node; - } - }, - - /** - * Returns the event's pageX - * @method getPageX - * @param {Event} ev the event - * @return {int} the event's pageX - * @static - */ - getPageX: function(ev) { - var x = ev.pageX; - if (!x && 0 !== x) { - x = ev.clientX || 0; - - if ( this.isIE ) { - x += this._getScrollLeft(); - } - } - - return x; - }, - - /** - * Returns the event's pageY - * @method getPageY - * @param {Event} ev the event - * @return {int} the event's pageY - * @static - */ - getPageY: function(ev) { - var y = ev.pageY; - if (!y && 0 !== y) { - y = ev.clientY || 0; - - if ( this.isIE ) { - y += this._getScrollTop(); - } - } - - - return y; - }, - - /** - * Returns the pageX and pageY properties as an indexed array. - * @method getXY - * @param {Event} ev the event - * @return {[x, y]} the pageX and pageY properties of the event - * @static - */ - getXY: function(ev) { - return [this.getPageX(ev), this.getPageY(ev)]; - }, - - /** - * Returns the event's related target - * @method getRelatedTarget - * @param {Event} ev the event - * @return {HTMLElement} the event's relatedTarget - * @static - */ - getRelatedTarget: function(ev) { - var t = ev.relatedTarget; - if (!t) { - if (ev.type == "mouseout") { - t = ev.toElement; - } else if (ev.type == "mouseover") { - t = ev.fromElement; - } - } - - return this.resolveTextNode(t); - }, - - /** - * Returns the time of the event. If the time is not included, the - * event is modified using the current time. - * @method getTime - * @param {Event} ev the event - * @return {Date} the time of the event - * @static - */ - getTime: function(ev) { - if (!ev.time) { - var t = new Date().getTime(); - try { - ev.time = t; - } catch(e) { - return t; - } - } - - return ev.time; - }, - - /** - * Convenience method for stopPropagation + preventDefault - * @method stopEvent - * @param {Event} ev the event - * @static - */ - stopEvent: function(ev) { - this.stopPropagation(ev); - this.preventDefault(ev); - }, - - /** - * Stops event propagation - * @method stopPropagation - * @param {Event} ev the event - * @static - */ - stopPropagation: function(ev) { - if (ev.stopPropagation) { - ev.stopPropagation(); - } else { - ev.cancelBubble = true; - } - }, - - /** - * Prevents the default behavior of the event - * @method preventDefault - * @param {Event} ev the event - * @static - */ - preventDefault: function(ev) { - if (ev.preventDefault) { - ev.preventDefault(); - } else { - ev.returnValue = false; - } - }, - - /** - * Finds the event in the window object, the caller's arguments, or - * in the arguments of another method in the callstack. This is - * executed automatically for events registered through the event - * manager, so the implementer should not normally need to execute - * this function at all. - * @method getEvent - * @param {Event} e the event parameter from the handler - * @return {Event} the event - * @static - */ - getEvent: function(e) { - var ev = e || window.event; - - if (!ev) { - var c = this.getEvent.caller; - while (c) { - ev = c.arguments[0]; - if (ev && Event == ev.constructor) { - break; - } - c = c.caller; - } - } - - return ev; - }, - - /** - * Returns the charcode for an event - * @method getCharCode - * @param {Event} ev the event - * @return {int} the event's charCode - * @static - */ - getCharCode: function(ev) { - return ev.charCode || ev.keyCode || 0; - }, - - /** - * Locating the saved event handler data by function ref - * - * @method _getCacheIndex - * @static - * @private - */ - _getCacheIndex: function(el, sType, fn) { - for (var i=0,len=listeners.length; i<len; ++i) { - var li = listeners[i]; - if ( li && - li[this.FN] == fn && - li[this.EL] == el && - li[this.TYPE] == sType ) { - return i; - } - } - - return -1; - }, - - /** - * Generates an unique ID for the element if it does not already - * have one. - * @method generateId - * @param el the element to create the id for - * @return {string} the resulting id of the element - * @static - */ - generateId: function(el) { - var id = el.id; - - if (!id) { - id = "yuievtautoid-" + counter; - ++counter; - el.id = id; - } - - return id; - }, - - - /** - * We want to be able to use getElementsByTagName as a collection - * to attach a group of events to. Unfortunately, different - * browsers return different types of collections. This function - * tests to determine if the object is array-like. It will also - * fail if the object is an array, but is empty. - * @method _isValidCollection - * @param o the object to test - * @return {boolean} true if the object is array-like and populated - * @static - * @private - */ - _isValidCollection: function(o) { - // this.logger.debug(o.constructor.toString()) - // this.logger.debug(typeof o) - - return ( o && // o is something - o.length && // o is indexed - typeof o != "string" && // o is not a string - !o.tagName && // o is not an HTML element - !o.alert && // o is not a window - typeof o[0] != "undefined" ); - - }, - - /** - * @private - * @property elCache - * DOM element cache - * @static - */ - elCache: {}, - - /** - * We cache elements bound by id because when the unload event - * fires, we can no longer use document.getElementById - * @method getEl - * @static - * @private - */ - getEl: function(id) { - return document.getElementById(id); - }, - - /** - * Clears the element cache - * @deprecated Elements are not cached any longer - * @method clearCache - * @static - * @private - */ - clearCache: function() { }, - - /** - * hook up any deferred listeners - * @method _load - * @static - * @private - */ - _load: function(e) { - loadComplete = true; - var EU = YAHOO.util.Event; - // Remove the listener to assist with the IE memory issue, but not - // for other browsers because FF 1.0x does not like it. - if (this.isIE) { - EU._simpleRemove(window, "load", EU._load); - } - }, - - /** - * Polling function that runs before the onload event fires, - * attempting to attach to DOM Nodes as soon as they are - * available - * @method _tryPreloadAttach - * @static - * @private - */ - _tryPreloadAttach: function() { - - if (this.locked) { - return false; - } - - this.locked = true; - - // this.logger.debug("tryPreloadAttach"); - - // keep trying until after the page is loaded. We need to - // check the page load state prior to trying to bind the - // elements so that we can be certain all elements have been - // tested appropriately - var tryAgain = !loadComplete; - if (!tryAgain) { - tryAgain = (retryCount > 0); - } - - // onAvailable - var notAvail = []; - for (var i=0,len=onAvailStack.length; i<len ; ++i) { - var item = onAvailStack[i]; - if (item) { - var el = this.getEl(item.id); - - if (el) { - // The element is available, but not necessarily ready - // @todo verify IE7 compatibility - // @todo should we test parentNode.nextSibling? - // @todo re-evaluate global content ready - if ( !item.checkReady || - loadComplete || - el.nextSibling || - (document && document.body) ) { - - var scope = el; - if (item.override) { - if (item.override === true) { - scope = item.obj; - } else { - scope = item.override; - } - } - item.fn.call(scope, item.obj); - //delete onAvailStack[i]; - // null out instead of delete for Opera - onAvailStack[i] = null; - } - } else { - notAvail.push(item); - } - } - } - - retryCount = (notAvail.length === 0) ? 0 : retryCount - 1; - - if (tryAgain) { - // we may need to strip the nulled out items here - this.startInterval(); - } else { - clearInterval(this._interval); - this._interval = null; - } - - this.locked = false; - - return true; - - }, - - /** - * Removes all listeners attached to the given element via addListener. - * Optionally, the node's children can also be purged. - * Optionally, you can specify a specific type of event to remove. - * @method purgeElement - * @param {HTMLElement} el the element to purge - * @param {boolean} recurse recursively purge this element's children - * as well. Use with caution. - * @param {string} sType optional type of listener to purge. If - * left out, all listeners will be removed - * @static - */ - purgeElement: function(el, recurse, sType) { - var elListeners = this.getListeners(el, sType); - if (elListeners) { - for (var i=0,len=elListeners.length; i<len ; ++i) { - var l = elListeners[i]; - // can't use the index on the changing collection - //this.removeListener(el, l.type, l.fn, l.index); - this.removeListener(el, l.type, l.fn); - } - } - - if (recurse && el && el.childNodes) { - for (i=0,len=el.childNodes.length; i<len ; ++i) { - this.purgeElement(el.childNodes[i], recurse, sType); - } - } - }, - - /** - * Returns all listeners attached to the given element via addListener. - * Optionally, you can specify a specific type of event to return. - * @method getListeners - * @param el {HTMLElement} the element to inspect - * @param sType {string} optional type of listener to return. If - * left out, all listeners will be returned - * @return {Object} the listener. Contains the following fields: - * type: (string) the type of event - * fn: (function) the callback supplied to addListener - * obj: (object) the custom object supplied to addListener - * adjust: (boolean) whether or not to adjust the default scope - * index: (int) its position in the Event util listener cache - * @static - */ - getListeners: function(el, sType) { - var elListeners = []; - if (listeners && listeners.length > 0) { - for (var i=0,len=listeners.length; i<len ; ++i) { - var l = listeners[i]; - if ( l && l[this.EL] === el && - (!sType || sType === l[this.TYPE]) ) { - elListeners.push({ - type: l[this.TYPE], - fn: l[this.FN], - obj: l[this.OBJ], - adjust: l[this.ADJ_SCOPE], - index: i - }); - } - } - } - - return (elListeners.length) ? elListeners : null; - }, - - /** - * Removes all listeners registered by pe.event. Called - * automatically during the unload event. - * @method _unload - * @static - * @private - */ - _unload: function(e) { - - var EU = YAHOO.util.Event, i, j, l, len, index; - - for (i=0,len=unloadListeners.length; i<len; ++i) { - l = unloadListeners[i]; - if (l) { - var scope = window; - if (l[EU.ADJ_SCOPE]) { - if (l[EU.ADJ_SCOPE] === true) { - scope = l[EU.OBJ]; - } else { - scope = l[EU.ADJ_SCOPE]; - } - } - l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ] ); - unloadListeners[i] = null; - l=null; - scope=null; - } - } - - unloadListeners = null; - - if (listeners && listeners.length > 0) { - j = listeners.length; - while (j) { - index = j-1; - l = listeners[index]; - if (l) { - EU.removeListener(l[EU.EL], l[EU.TYPE], - l[EU.FN], index); - } - j = j - 1; - } - l=null; - - EU.clearCache(); - } - - for (i=0,len=legacyEvents.length; i<len; ++i) { - // dereference the element - //delete legacyEvents[i][0]; - legacyEvents[i][0] = null; - - // delete the array item - //delete legacyEvents[i]; - legacyEvents[i] = null; - } - - legacyEvents = null; - - EU._simpleRemove(window, "unload", EU._unload); - - }, - - /** - * Returns scrollLeft - * @method _getScrollLeft - * @static - * @private - */ - _getScrollLeft: function() { - return this._getScroll()[1]; - }, - - /** - * Returns scrollTop - * @method _getScrollTop - * @static - * @private - */ - _getScrollTop: function() { - return this._getScroll()[0]; - }, - - /** - * Returns the scrollTop and scrollLeft. Used to calculate the - * pageX and pageY in Internet Explorer - * @method _getScroll - * @static - * @private - */ - _getScroll: function() { - var dd = document.documentElement, db = document.body; - if (dd && (dd.scrollTop || dd.scrollLeft)) { - return [dd.scrollTop, dd.scrollLeft]; - } else if (db) { - return [db.scrollTop, db.scrollLeft]; - } else { - return [0, 0]; - } - }, - - /** - * Adds a DOM event directly without the caching, cleanup, scope adj, etc - * - * @method _simpleAdd - * @param {HTMLElement} el the element to bind the handler to - * @param {string} sType the type of event handler - * @param {function} fn the callback to invoke - * @param {boolen} capture capture or bubble phase - * @static - * @private - */ - _simpleAdd: function () { - if (window.addEventListener) { - return function(el, sType, fn, capture) { - el.addEventListener(sType, fn, (capture)); - }; - } else if (window.attachEvent) { - return function(el, sType, fn, capture) { - el.attachEvent("on" + sType, fn); - }; - } else { - return function(){}; - } - }(), - - /** - * Basic remove listener - * - * @method _simpleRemove - * @param {HTMLElement} el the element to bind the handler to - * @param {string} sType the type of event handler - * @param {function} fn the callback to invoke - * @param {boolen} capture capture or bubble phase - * @static - * @private - */ - _simpleRemove: function() { - if (window.removeEventListener) { - return function (el, sType, fn, capture) { - el.removeEventListener(sType, fn, (capture)); - }; - } else if (window.detachEvent) { - return function (el, sType, fn) { - el.detachEvent("on" + sType, fn); - }; - } else { - return function(){}; - } - }() - }; - - }(); - - (function() { - var EU = YAHOO.util.Event; - - /** - * YAHOO.util.Event.on is an alias for addListener - * @method on - * @see addListener - * @static - */ - EU.on = EU.addListener; - - // YAHOO.mix(EU, YAHOO.util.EventProvider.prototype); - // EU.createEvent("DOMContentReady"); - // EU.subscribe("DOMContentReady", EU._load); - - if (document && document.body) { - EU._load(); - } else { - // EU._simpleAdd(document, "DOMContentLoaded", EU._load); - EU._simpleAdd(window, "load", EU._load); - } - EU._simpleAdd(window, "unload", EU._unload); - EU._tryPreloadAttach(); - })(); -} - -/** - * EventProvider is designed to be used with YAHOO.augment to wrap - * CustomEvents in an interface that allows events to be subscribed to - * and fired by name. This makes it possible for implementing code to - * subscribe to an event that either has not been created yet, or will - * not be created at all. - * - * @Class EventProvider - */ -YAHOO.util.EventProvider = function() { }; - -YAHOO.util.EventProvider.prototype = { - - /** - * Private storage of custom events - * @property __yui_events - * @type Object[] - * @private - */ - __yui_events: null, - - /** - * Private storage of custom event subscribers - * @property __yui_subscribers - * @type Object[] - * @private - */ - __yui_subscribers: null, - - /** - * Subscribe to a CustomEvent by event type - * - * @method subscribe - * @param p_type {string} the type, or name of the event - * @param p_fn {function} the function to exectute when the event fires - * @param p_obj - * @param p_obj {Object} An object to be passed along when the event - * fires - * @param p_override {boolean} If true, the obj passed in becomes the - * execution scope of the listener - */ - subscribe: function(p_type, p_fn, p_obj, p_override) { - - this.__yui_events = this.__yui_events || {}; - var ce = this.__yui_events[p_type]; - - if (ce) { - ce.subscribe(p_fn, p_obj, p_override); - } else { - this.__yui_subscribers = this.__yui_subscribers || {}; - var subs = this.__yui_subscribers; - if (!subs[p_type]) { - subs[p_type] = []; - } - subs[p_type].push( - { fn: p_fn, obj: p_obj, override: p_override } ); - } - }, - - /** - * Unsubscribes the from the specified event - * @method unsubscribe - * @param p_type {string} The type, or name of the event - * @param p_fn {Function} The function to execute - * @param p_obj {Object} The custom object passed to subscribe (optional) - * @return {boolean} true if the subscriber was found and detached. - */ - unsubscribe: function(p_type, p_fn, p_obj) { - this.__yui_events = this.__yui_events || {}; - var ce = this.__yui_events[p_type]; - if (ce) { - return ce.unsubscribe(p_fn, p_obj); - } else { - return false; - } - }, - - /** - * Creates a new custom event of the specified type. If a custom event - * by that name already exists, it will not be re-created. In either - * case the custom event is returned. - * - * @method createEvent - * - * @param p_type {string} the type, or name of the event - * @param p_config {object} optional config params. Valid properties are: - * - * <ul> - * <li> - * scope: defines the default execution scope. If not defined - * the default scope will be this instance. - * </li> - * <li> - * silent: if true, the custom event will not generate log messages. - * This is false by default. - * </li> - * <li> - * onSubscribeCallback: specifies a callback to execute when the - * event has a new subscriber. This will fire immediately for - * each queued subscriber if any exist prior to the creation of - * the event. - * </li> - * </ul> - * - * @return {CustomEvent} the custom event - * - */ - createEvent: function(p_type, p_config) { - - this.__yui_events = this.__yui_events || {}; - var opts = p_config || {}; - var events = this.__yui_events; - - if (events[p_type]) { - YAHOO.log("EventProvider: error, event already exists"); - } else { - - var scope = opts.scope || this; - var silent = opts.silent || null; - - var ce = new YAHOO.util.CustomEvent(p_type, scope, silent, - YAHOO.util.CustomEvent.FLAT); - events[p_type] = ce; - - if (opts.onSubscribeCallback) { - ce.subscribeEvent.subscribe(opts.onSubscribeCallback); - } - - this.__yui_subscribers = this.__yui_subscribers || {}; - var qs = this.__yui_subscribers[p_type]; - - if (qs) { - for (var i=0; i<qs.length; ++i) { - ce.subscribe(qs[i].fn, qs[i].obj, qs[i].override); - } - } - } - - return events[p_type]; - }, - - - /** - * Fire a custom event by name. The callback functions will be executed - * from the scope specified when the event was created, and with the - * following parameters: - * <ul> - * <li>The first argument fire() was executed with</li> - * <li>The custom object (if any) that was passed into the subscribe() - * method</li> - * </ul> - * @method fireEvent - * @param p_type {string} the type, or name of the event - * @param arguments {Object*} an arbitrary set of parameters to pass to - * the handler. - * @return {boolean} the return value from CustomEvent.fire, or null if - * the custom event does not exist. - */ - fireEvent: function(p_type, arg1, arg2, etc) { - - this.__yui_events = this.__yui_events || {}; - var ce = this.__yui_events[p_type]; - - if (ce) { - var args = []; - for (var i=1; i<arguments.length; ++i) { - args.push(arguments[i]); - } - return ce.fire.apply(ce, args); - } else { - YAHOO.log("EventProvider.fire could not find event: " + p_type); - return null; - } - }, - - /** - * Returns true if the custom event of the provided type has been created - * with createEvent. - * @method hasEvent - * @param type {string} the type, or name of the event - */ - hasEvent: function(type) { - if (this.__yui_events) { - if (this.__yui_events[type]) { - return true; - } - } - return false; - } - -}; - diff --git a/reports/site_media/yui/event/event-min.js b/reports/site_media/yui/event/event-min.js deleted file mode 100644 index 1bb595a73..000000000 --- a/reports/site_media/yui/event/event-min.js +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ - - -YAHOO.util.CustomEvent=function(type,oScope,silent,signature){this.type=type;this.scope=oScope||window;this.silent=silent;this.signature=signature||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){} -var onsubscribeType="_YUICEOnSubscribe";if(type!==onsubscribeType){this.subscribeEvent=new YAHOO.util.CustomEvent(onsubscribeType,this,true);}};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(fn,obj,override){if(this.subscribeEvent){this.subscribeEvent.fire(fn,obj,override);} -this.subscribers.push(new YAHOO.util.Subscriber(fn,obj,override));},unsubscribe:function(fn,obj){var found=false;for(var i=0,len=this.subscribers.length;i<len;++i){var s=this.subscribers[i];if(s&&s.contains(fn,obj)){this._delete(i);found=true;}} -return found;},fire:function(){var len=this.subscribers.length;if(!len&&this.silent){return true;} -var args=[],ret=true,i;for(i=0;i<arguments.length;++i){args.push(arguments[i]);} -var argslength=args.length;if(!this.silent){} -for(i=0;i<len;++i){var s=this.subscribers[i];if(s){if(!this.silent){} -var scope=s.getScope(this.scope);if(this.signature==YAHOO.util.CustomEvent.FLAT){var param=null;if(args.length>0){param=args[0];} -ret=s.fn.call(scope,param,s.obj);}else{ret=s.fn.call(scope,this.type,args,s.obj);} -if(false===ret){if(!this.silent){} -return false;}}} -return true;},unsubscribeAll:function(){for(var i=0,len=this.subscribers.length;i<len;++i){this._delete(len-1-i);}},_delete:function(index){var s=this.subscribers[index];if(s){delete s.fn;delete s.obj;} -this.subscribers.splice(index,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"scope: "+this.scope;}};YAHOO.util.Subscriber=function(fn,obj,override){this.fn=fn;this.obj=obj||null;this.override=override;};YAHOO.util.Subscriber.prototype.getScope=function(defaultScope){if(this.override){if(this.override===true){return this.obj;}else{return this.override;}} -return defaultScope;};YAHOO.util.Subscriber.prototype.contains=function(fn,obj){if(obj){return(this.fn==fn&&this.obj==obj);}else{return(this.fn==fn);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+(this.obj||"")+", override: "+(this.override||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var loadComplete=false;var listeners=[];var unloadListeners=[];var legacyEvents=[];var legacyHandlers=[];var retryCount=0;var onAvailStack=[];var legacyMap=[];var counter=0;return{POLL_RETRYS:200,POLL_INTERVAL:20,EL:0,TYPE:1,FN:2,WFN:3,OBJ:3,ADJ_SCOPE:4,isSafari:(/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),isIE:(!this.isSafari&&!navigator.userAgent.match(/opera/gi)&&navigator.userAgent.match(/msie/gi)),_interval:null,startInterval:function(){if(!this._interval){var self=this;var callback=function(){self._tryPreloadAttach();};this._interval=setInterval(callback,this.POLL_INTERVAL);}},onAvailable:function(p_id,p_fn,p_obj,p_override){onAvailStack.push({id:p_id,fn:p_fn,obj:p_obj,override:p_override,checkReady:false});retryCount=this.POLL_RETRYS;this.startInterval();},onContentReady:function(p_id,p_fn,p_obj,p_override){onAvailStack.push({id:p_id,fn:p_fn,obj:p_obj,override:p_override,checkReady:true});retryCount=this.POLL_RETRYS;this.startInterval();},addListener:function(el,sType,fn,obj,override){if(!fn||!fn.call){return false;} -if(this._isValidCollection(el)){var ok=true;for(var i=0,len=el.length;i<len;++i){ok=this.on(el[i],sType,fn,obj,override)&&ok;} -return ok;}else if(typeof el=="string"){var oEl=this.getEl(el);if(oEl){el=oEl;}else{this.onAvailable(el,function(){YAHOO.util.Event.on(el,sType,fn,obj,override);});return true;}} -if(!el){return false;} -if("unload"==sType&&obj!==this){unloadListeners[unloadListeners.length]=[el,sType,fn,obj,override];return true;} -var scope=el;if(override){if(override===true){scope=obj;}else{scope=override;}} -var wrappedFn=function(e){return fn.call(scope,YAHOO.util.Event.getEvent(e),obj);};var li=[el,sType,fn,wrappedFn,scope];var index=listeners.length;listeners[index]=li;if(this.useLegacyEvent(el,sType)){var legacyIndex=this.getLegacyIndex(el,sType);if(legacyIndex==-1||el!=legacyEvents[legacyIndex][0]){legacyIndex=legacyEvents.length;legacyMap[el.id+sType]=legacyIndex;legacyEvents[legacyIndex]=[el,sType,el["on"+sType]];legacyHandlers[legacyIndex]=[];el["on"+sType]=function(e){YAHOO.util.Event.fireLegacyEvent(YAHOO.util.Event.getEvent(e),legacyIndex);};} -legacyHandlers[legacyIndex].push(li);}else{try{this._simpleAdd(el,sType,wrappedFn,false);}catch(e){this.removeListener(el,sType,fn);return false;}} -return true;},fireLegacyEvent:function(e,legacyIndex){var ok=true;var le=legacyHandlers[legacyIndex];for(var i=0,len=le.length;i<len;++i){var li=le[i];if(li&&li[this.WFN]){var scope=li[this.ADJ_SCOPE];var ret=li[this.WFN].call(scope,e);ok=(ok&&ret);}} -return ok;},getLegacyIndex:function(el,sType){var key=this.generateId(el)+sType;if(typeof legacyMap[key]=="undefined"){return-1;}else{return legacyMap[key];}},useLegacyEvent:function(el,sType){if(!el.addEventListener&&!el.attachEvent){return true;}else if(this.isSafari){if("click"==sType||"dblclick"==sType){return true;}} -return false;},removeListener:function(el,sType,fn){var i,len;if(typeof el=="string"){el=this.getEl(el);}else if(this._isValidCollection(el)){var ok=true;for(i=0,len=el.length;i<len;++i){ok=(this.removeListener(el[i],sType,fn)&&ok);} -return ok;} -if(!fn||!fn.call){return this.purgeElement(el,false,sType);} -if("unload"==sType){for(i=0,len=unloadListeners.length;i<len;i++){var li=unloadListeners[i];if(li&&li[0]==el&&li[1]==sType&&li[2]==fn){unloadListeners.splice(i,1);return true;}} -return false;} -var cacheItem=null;var index=arguments[3];if("undefined"==typeof index){index=this._getCacheIndex(el,sType,fn);} -if(index>=0){cacheItem=listeners[index];} -if(!el||!cacheItem){return false;} -if(this.useLegacyEvent(el,sType)){var legacyIndex=this.getLegacyIndex(el,sType);var llist=legacyHandlers[legacyIndex];if(llist){for(i=0,len=llist.length;i<len;++i){li=llist[i];if(li&&li[this.EL]==el&&li[this.TYPE]==sType&&li[this.FN]==fn){llist.splice(i,1);break;}}}}else{try{this._simpleRemove(el,sType,cacheItem[this.WFN],false);}catch(e){return false;}} -delete listeners[index][this.WFN];delete listeners[index][this.FN];listeners.splice(index,1);return true;},getTarget:function(ev,resolveTextNode){var t=ev.target||ev.srcElement;return this.resolveTextNode(t);},resolveTextNode:function(node){if(node&&3==node.nodeType){return node.parentNode;}else{return node;}},getPageX:function(ev){var x=ev.pageX;if(!x&&0!==x){x=ev.clientX||0;if(this.isIE){x+=this._getScrollLeft();}} -return x;},getPageY:function(ev){var y=ev.pageY;if(!y&&0!==y){y=ev.clientY||0;if(this.isIE){y+=this._getScrollTop();}} -return y;},getXY:function(ev){return[this.getPageX(ev),this.getPageY(ev)];},getRelatedTarget:function(ev){var t=ev.relatedTarget;if(!t){if(ev.type=="mouseout"){t=ev.toElement;}else if(ev.type=="mouseover"){t=ev.fromElement;}} -return this.resolveTextNode(t);},getTime:function(ev){if(!ev.time){var t=new Date().getTime();try{ev.time=t;}catch(e){return t;}} -return ev.time;},stopEvent:function(ev){this.stopPropagation(ev);this.preventDefault(ev);},stopPropagation:function(ev){if(ev.stopPropagation){ev.stopPropagation();}else{ev.cancelBubble=true;}},preventDefault:function(ev){if(ev.preventDefault){ev.preventDefault();}else{ev.returnValue=false;}},getEvent:function(e){var ev=e||window.event;if(!ev){var c=this.getEvent.caller;while(c){ev=c.arguments[0];if(ev&&Event==ev.constructor){break;} -c=c.caller;}} -return ev;},getCharCode:function(ev){return ev.charCode||ev.keyCode||0;},_getCacheIndex:function(el,sType,fn){for(var i=0,len=listeners.length;i<len;++i){var li=listeners[i];if(li&&li[this.FN]==fn&&li[this.EL]==el&&li[this.TYPE]==sType){return i;}} -return-1;},generateId:function(el){var id=el.id;if(!id){id="yuievtautoid-"+counter;++counter;el.id=id;} -return id;},_isValidCollection:function(o){return(o&&o.length&&typeof o!="string"&&!o.tagName&&!o.alert&&typeof o[0]!="undefined");},elCache:{},getEl:function(id){return document.getElementById(id);},clearCache:function(){},_load:function(e){loadComplete=true;var EU=YAHOO.util.Event;if(this.isIE){EU._simpleRemove(window,"load",EU._load);}},_tryPreloadAttach:function(){if(this.locked){return false;} -this.locked=true;var tryAgain=!loadComplete;if(!tryAgain){tryAgain=(retryCount>0);} -var notAvail=[];for(var i=0,len=onAvailStack.length;i<len;++i){var item=onAvailStack[i];if(item){var el=this.getEl(item.id);if(el){if(!item.checkReady||loadComplete||el.nextSibling||(document&&document.body)){var scope=el;if(item.override){if(item.override===true){scope=item.obj;}else{scope=item.override;}} -item.fn.call(scope,item.obj);onAvailStack[i]=null;}}else{notAvail.push(item);}}} -retryCount=(notAvail.length===0)?0:retryCount-1;if(tryAgain){this.startInterval();}else{clearInterval(this._interval);this._interval=null;} -this.locked=false;return true;},purgeElement:function(el,recurse,sType){var elListeners=this.getListeners(el,sType);if(elListeners){for(var i=0,len=elListeners.length;i<len;++i){var l=elListeners[i];this.removeListener(el,l.type,l.fn);}} -if(recurse&&el&&el.childNodes){for(i=0,len=el.childNodes.length;i<len;++i){this.purgeElement(el.childNodes[i],recurse,sType);}}},getListeners:function(el,sType){var elListeners=[];if(listeners&&listeners.length>0){for(var i=0,len=listeners.length;i<len;++i){var l=listeners[i];if(l&&l[this.EL]===el&&(!sType||sType===l[this.TYPE])){elListeners.push({type:l[this.TYPE],fn:l[this.FN],obj:l[this.OBJ],adjust:l[this.ADJ_SCOPE],index:i});}}} -return(elListeners.length)?elListeners:null;},_unload:function(e){var EU=YAHOO.util.Event,i,j,l,len,index;for(i=0,len=unloadListeners.length;i<len;++i){l=unloadListeners[i];if(l){var scope=window;if(l[EU.ADJ_SCOPE]){if(l[EU.ADJ_SCOPE]===true){scope=l[EU.OBJ];}else{scope=l[EU.ADJ_SCOPE];}} -l[EU.FN].call(scope,EU.getEvent(e),l[EU.OBJ]);unloadListeners[i]=null;l=null;scope=null;}} -unloadListeners=null;if(listeners&&listeners.length>0){j=listeners.length;while(j){index=j-1;l=listeners[index];if(l){EU.removeListener(l[EU.EL],l[EU.TYPE],l[EU.FN],index);} -j=j-1;} -l=null;EU.clearCache();} -for(i=0,len=legacyEvents.length;i<len;++i){legacyEvents[i][0]=null;legacyEvents[i]=null;} -legacyEvents=null;EU._simpleRemove(window,"unload",EU._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var dd=document.documentElement,db=document.body;if(dd&&(dd.scrollTop||dd.scrollLeft)){return[dd.scrollTop,dd.scrollLeft];}else if(db){return[db.scrollTop,db.scrollLeft];}else{return[0,0];}},_simpleAdd:function(){if(window.addEventListener){return function(el,sType,fn,capture){el.addEventListener(sType,fn,(capture));};}else if(window.attachEvent){return function(el,sType,fn,capture){el.attachEvent("on"+sType,fn);};}else{return function(){};}}(),_simpleRemove:function(){if(window.removeEventListener){return function(el,sType,fn,capture){el.removeEventListener(sType,fn,(capture));};}else if(window.detachEvent){return function(el,sType,fn){el.detachEvent("on"+sType,fn);};}else{return function(){};}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;if(document&&document.body){EU._load();}else{EU._simpleAdd(window,"load",EU._load);} -EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();} -YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(p_type,p_fn,p_obj,p_override){this.__yui_events=this.__yui_events||{};var ce=this.__yui_events[p_type];if(ce){ce.subscribe(p_fn,p_obj,p_override);}else{this.__yui_subscribers=this.__yui_subscribers||{};var subs=this.__yui_subscribers;if(!subs[p_type]){subs[p_type]=[];} -subs[p_type].push({fn:p_fn,obj:p_obj,override:p_override});}},unsubscribe:function(p_type,p_fn,p_obj){this.__yui_events=this.__yui_events||{};var ce=this.__yui_events[p_type];if(ce){return ce.unsubscribe(p_fn,p_obj);}else{return false;}},createEvent:function(p_type,p_config){this.__yui_events=this.__yui_events||{};var opts=p_config||{};var events=this.__yui_events;if(events[p_type]){}else{var scope=opts.scope||this;var silent=opts.silent||null;var ce=new YAHOO.util.CustomEvent(p_type,scope,silent,YAHOO.util.CustomEvent.FLAT);events[p_type]=ce;if(opts.onSubscribeCallback){ce.subscribeEvent.subscribe(opts.onSubscribeCallback);} -this.__yui_subscribers=this.__yui_subscribers||{};var qs=this.__yui_subscribers[p_type];if(qs){for(var i=0;i<qs.length;++i){ce.subscribe(qs[i].fn,qs[i].obj,qs[i].override);}}} -return events[p_type];},fireEvent:function(p_type,arg1,arg2,etc){this.__yui_events=this.__yui_events||{};var ce=this.__yui_events[p_type];if(ce){var args=[];for(var i=1;i<arguments.length;++i){args.push(arguments[i]);} -return ce.fire.apply(ce,args);}else{return null;}},hasEvent:function(type){if(this.__yui_events){if(this.__yui_events[type]){return true;}} -return false;}};
\ No newline at end of file diff --git a/reports/site_media/yui/event/event.js b/reports/site_media/yui/event/event.js deleted file mode 100644 index 22c97ca2b..000000000 --- a/reports/site_media/yui/event/event.js +++ /dev/null @@ -1,1771 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ -/** - * The CustomEvent class lets you define events for your application - * that can be subscribed to by one or more independent component. - * - * @param {String} type The type of event, which is passed to the callback - * when the event fires - * @param {Object} oScope The context the event will fire from. "this" will - * refer to this object in the callback. Default value: - * the window object. The listener can override this. - * @param {boolean} silent pass true to prevent the event from writing to - * the debugsystem - * @param {int} signature the signature that the custom event subscriber - * will receive. YAHOO.util.CustomEvent.LIST or - * YAHOO.util.CustomEvent.FLAT. The default is - * YAHOO.util.CustomEvent.LIST. - * @namespace YAHOO.util - * @class CustomEvent - * @constructor - */ -YAHOO.util.CustomEvent = function(type, oScope, silent, signature) { - - /** - * The type of event, returned to subscribers when the event fires - * @property type - * @type string - */ - this.type = type; - - /** - * The scope the the event will fire from by default. Defaults to the window - * obj - * @property scope - * @type object - */ - this.scope = oScope || window; - - /** - * By default all custom events are logged in the debug build, set silent - * to true to disable debug outpu for this event. - * @property silent - * @type boolean - */ - this.silent = silent; - - /** - * Custom events support two styles of arguments provided to the event - * subscribers. - * <ul> - * <li>YAHOO.util.CustomEvent.LIST: - * <ul> - * <li>param1: event name</li> - * <li>param2: array of arguments sent to fire</li> - * <li>param3: <optional> a custom object supplied by the subscriber</li> - * </ul> - * </li> - * <li>YAHOO.util.CustomEvent.FLAT - * <ul> - * <li>param1: the first argument passed to fire. If you need to - * pass multiple parameters, use and array or object literal</li> - * <li>param2: <optional> a custom object supplied by the subscriber</li> - * </ul> - * </li> - * </ul> - * @property signature - * @type int - */ - this.signature = signature || YAHOO.util.CustomEvent.LIST; - - /** - * The subscribers to this event - * @property subscribers - * @type Subscriber[] - */ - this.subscribers = []; - - if (!this.silent) { - } - - var onsubscribeType = "_YUICEOnSubscribe"; - - // Only add subscribe events for events that are not generated by - // CustomEvent - if (type !== onsubscribeType) { - - /** - * Custom events provide a custom event that fires whenever there is - * a new subscriber to the event. This provides an opportunity to - * handle the case where there is a non-repeating event that has - * already fired has a new subscriber. - * - * @event subscribeEvent - * @type YAHOO.util.CustomEvent - * @param {Function} fn The function to execute - * @param {Object} obj An object to be passed along when the event - * fires - * @param {boolean|Object} override If true, the obj passed in becomes - * the execution scope of the listener. - * if an object, that object becomes the - * the execution scope. - */ - this.subscribeEvent = - new YAHOO.util.CustomEvent(onsubscribeType, this, true); - - } -}; - -/** - * Subscriber listener sigature constant. The LIST type returns three - * parameters: the event type, the array of args passed to fire, and - * the optional custom object - * @property YAHOO.util.CustomEvent.LIST - * @static - * @type int - */ -YAHOO.util.CustomEvent.LIST = 0; - -/** - * Subscriber listener sigature constant. The FLAT type returns two - * parameters: the first argument passed to fire and the optional - * custom object - * @property YAHOO.util.CustomEvent.FLAT - * @static - * @type int - */ -YAHOO.util.CustomEvent.FLAT = 1; - -YAHOO.util.CustomEvent.prototype = { - - /** - * Subscribes the caller to this event - * @method subscribe - * @param {Function} fn The function to execute - * @param {Object} obj An object to be passed along when the event - * fires - * @param {boolean|Object} override If true, the obj passed in becomes - * the execution scope of the listener. - * if an object, that object becomes the - * the execution scope. - */ - subscribe: function(fn, obj, override) { - if (this.subscribeEvent) { - this.subscribeEvent.fire(fn, obj, override); - } - - this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, override) ); - }, - - /** - * Unsubscribes the caller from this event - * @method unsubscribe - * @param {Function} fn The function to execute - * @param {Object} obj The custom object passed to subscribe (optional) - * @return {boolean} True if the subscriber was found and detached. - */ - unsubscribe: function(fn, obj) { - var found = false; - for (var i=0, len=this.subscribers.length; i<len; ++i) { - var s = this.subscribers[i]; - if (s && s.contains(fn, obj)) { - this._delete(i); - found = true; - } - } - - return found; - }, - - /** - * Notifies the subscribers. The callback functions will be executed - * from the scope specified when the event was created, and with the - * following parameters: - * <ul> - * <li>The type of event</li> - * <li>All of the arguments fire() was executed with as an array</li> - * <li>The custom object (if any) that was passed into the subscribe() - * method</li> - * </ul> - * @method fire - * @param {Object*} arguments an arbitrary set of parameters to pass to - * the handler. - * @return {boolean} false if one of the subscribers returned false, - * true otherwise - */ - fire: function() { - var len=this.subscribers.length; - if (!len && this.silent) { - return true; - } - - var args=[], ret=true, i; - - for (i=0; i<arguments.length; ++i) { - args.push(arguments[i]); - } - - var argslength = args.length; - - if (!this.silent) { - } - - for (i=0; i<len; ++i) { - var s = this.subscribers[i]; - if (s) { - if (!this.silent) { - } - - var scope = s.getScope(this.scope); - - if (this.signature == YAHOO.util.CustomEvent.FLAT) { - var param = null; - if (args.length > 0) { - param = args[0]; - } - ret = s.fn.call(scope, param, s.obj); - } else { - ret = s.fn.call(scope, this.type, args, s.obj); - } - if (false === ret) { - if (!this.silent) { - } - - //break; - return false; - } - } - } - - return true; - }, - - /** - * Removes all listeners - * @method unsubscribeAll - */ - unsubscribeAll: function() { - for (var i=0, len=this.subscribers.length; i<len; ++i) { - this._delete(len - 1 - i); - } - }, - - /** - * @method _delete - * @private - */ - _delete: function(index) { - var s = this.subscribers[index]; - if (s) { - delete s.fn; - delete s.obj; - } - - // delete this.subscribers[index]; - this.subscribers.splice(index, 1); - }, - - /** - * @method toString - */ - toString: function() { - return "CustomEvent: " + "'" + this.type + "', " + - "scope: " + this.scope; - - } -}; - -///////////////////////////////////////////////////////////////////// - -/** - * Stores the subscriber information to be used when the event fires. - * @param {Function} fn The function to execute - * @param {Object} obj An object to be passed along when the event fires - * @param {boolean} override If true, the obj passed in becomes the execution - * scope of the listener - * @class Subscriber - * @constructor - */ -YAHOO.util.Subscriber = function(fn, obj, override) { - - /** - * The callback that will be execute when the event fires - * @property fn - * @type function - */ - this.fn = fn; - - /** - * An optional custom object that will passed to the callback when - * the event fires - * @property obj - * @type object - */ - this.obj = obj || null; - - /** - * The default execution scope for the event listener is defined when the - * event is created (usually the object which contains the event). - * By setting override to true, the execution scope becomes the custom - * object passed in by the subscriber. If override is an object, that - * object becomes the scope. - * @property override - * @type boolean|object - */ - this.override = override; - -}; - -/** - * Returns the execution scope for this listener. If override was set to true - * the custom obj will be the scope. If override is an object, that is the - * scope, otherwise the default scope will be used. - * @method getScope - * @param {Object} defaultScope the scope to use if this listener does not - * override it. - */ -YAHOO.util.Subscriber.prototype.getScope = function(defaultScope) { - if (this.override) { - if (this.override === true) { - return this.obj; - } else { - return this.override; - } - } - return defaultScope; -}; - -/** - * Returns true if the fn and obj match this objects properties. - * Used by the unsubscribe method to match the right subscriber. - * - * @method contains - * @param {Function} fn the function to execute - * @param {Object} obj an object to be passed along when the event fires - * @return {boolean} true if the supplied arguments match this - * subscriber's signature. - */ -YAHOO.util.Subscriber.prototype.contains = function(fn, obj) { - if (obj) { - return (this.fn == fn && this.obj == obj); - } else { - return (this.fn == fn); - } -}; - -/** - * @method toString - */ -YAHOO.util.Subscriber.prototype.toString = function() { - return "Subscriber { obj: " + (this.obj || "") + - ", override: " + (this.override || "no") + " }"; -}; - -/** - * The Event Utility provides utilities for managing DOM Events and tools - * for building event systems - * - * @module event - * @title Event Utility - * @namespace YAHOO.util - * @requires yahoo - */ - -// The first instance of Event will win if it is loaded more than once. -if (!YAHOO.util.Event) { - -/** - * The event utility provides functions to add and remove event listeners, - * event cleansing. It also tries to automatically remove listeners it - * registers during the unload event. - * - * @class Event - * @static - */ - YAHOO.util.Event = function() { - - /** - * True after the onload event has fired - * @property loadComplete - * @type boolean - * @static - * @private - */ - var loadComplete = false; - - /** - * Cache of wrapped listeners - * @property listeners - * @type array - * @static - * @private - */ - var listeners = []; - - /** - * User-defined unload function that will be fired before all events - * are detached - * @property unloadListeners - * @type array - * @static - * @private - */ - var unloadListeners = []; - - /** - * Cache of DOM0 event handlers to work around issues with DOM2 events - * in Safari - * @property legacyEvents - * @static - * @private - */ - var legacyEvents = []; - - /** - * Listener stack for DOM0 events - * @property legacyHandlers - * @static - * @private - */ - var legacyHandlers = []; - - /** - * The number of times to poll after window.onload. This number is - * increased if additional late-bound handlers are requested after - * the page load. - * @property retryCount - * @static - * @private - */ - var retryCount = 0; - - /** - * onAvailable listeners - * @property onAvailStack - * @static - * @private - */ - var onAvailStack = []; - - /** - * Lookup table for legacy events - * @property legacyMap - * @static - * @private - */ - var legacyMap = []; - - /** - * Counter for auto id generation - * @property counter - * @static - * @private - */ - var counter = 0; - - return { // PREPROCESS - - /** - * The number of times we should look for elements that are not - * in the DOM at the time the event is requested after the document - * has been loaded. The default is 200@amp;50 ms, so it will poll - * for 10 seconds or until all outstanding handlers are bound - * (whichever comes first). - * @property POLL_RETRYS - * @type int - * @static - * @final - */ - POLL_RETRYS: 200, - - /** - * The poll interval in milliseconds - * @property POLL_INTERVAL - * @type int - * @static - * @final - */ - POLL_INTERVAL: 20, - - /** - * Element to bind, int constant - * @property EL - * @type int - * @static - * @final - */ - EL: 0, - - /** - * Type of event, int constant - * @property TYPE - * @type int - * @static - * @final - */ - TYPE: 1, - - /** - * Function to execute, int constant - * @property FN - * @type int - * @static - * @final - */ - FN: 2, - - /** - * Function wrapped for scope correction and cleanup, int constant - * @property WFN - * @type int - * @static - * @final - */ - WFN: 3, - - /** - * Object passed in by the user that will be returned as a - * parameter to the callback, int constant - * @property OBJ - * @type int - * @static - * @final - */ - OBJ: 3, - - /** - * Adjusted scope, either the element we are registering the event - * on or the custom object passed in by the listener, int constant - * @property ADJ_SCOPE - * @type int - * @static - * @final - */ - ADJ_SCOPE: 4, - - /** - * Safari detection is necessary to work around the preventDefault - * bug that makes it so you can't cancel a href click from the - * handler. There is not a capabilities check we can use here. - * @property isSafari - * @private - * @static - */ - isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent), - - /** - * IE detection needed to properly calculate pageX and pageY. - * capabilities checking didn't seem to work because another - * browser that does not provide the properties have the values - * calculated in a different manner than IE. - * @property isIE - * @private - * @static - */ - isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) && - navigator.userAgent.match(/msie/gi)), - - /** - * poll handle - * @property _interval - * @private - */ - _interval: null, - - /** - * @method startInterval - * @static - * @private - */ - startInterval: function() { - if (!this._interval) { - var self = this; - var callback = function() { self._tryPreloadAttach(); }; - this._interval = setInterval(callback, this.POLL_INTERVAL); - // this.timeout = setTimeout(callback, i); - } - }, - - /** - * Executes the supplied callback when the item with the supplied - * id is found. This is meant to be used to execute behavior as - * soon as possible as the page loads. If you use this after the - * initial page load it will poll for a fixed time for the element. - * The number of times it will poll and the frequency are - * configurable. By default it will poll for 10 seconds. - * - * @method onAvailable - * - * @param {string} p_id the id of the element to look for. - * @param {function} p_fn what to execute when the element is found. - * @param {object} p_obj an optional object to be passed back as - * a parameter to p_fn. - * @param {boolean} p_override If set to true, p_fn will execute - * in the scope of p_obj - * - * @static - */ - onAvailable: function(p_id, p_fn, p_obj, p_override) { - onAvailStack.push( { id: p_id, - fn: p_fn, - obj: p_obj, - override: p_override, - checkReady: false } ); - - retryCount = this.POLL_RETRYS; - this.startInterval(); - }, - - /** - * Works the same way as onAvailable, but additionally checks the - * state of sibling elements to determine if the content of the - * available element is safe to modify. - * - * @method onContentReady - * - * @param {string} p_id the id of the element to look for. - * @param {function} p_fn what to execute when the element is ready. - * @param {object} p_obj an optional object to be passed back as - * a parameter to p_fn. - * @param {boolean} p_override If set to true, p_fn will execute - * in the scope of p_obj - * - * @static - */ - onContentReady: function(p_id, p_fn, p_obj, p_override) { - onAvailStack.push( { id: p_id, - fn: p_fn, - obj: p_obj, - override: p_override, - checkReady: true } ); - - retryCount = this.POLL_RETRYS; - this.startInterval(); - }, - - /** - * Appends an event handler - * - * @method addListener - * - * @param {Object} el The html element to assign the - * event to - * @param {String} sType The type of event to append - * @param {Function} fn The method the event invokes - * @param {Object} obj An arbitrary object that will be - * passed as a parameter to the handler - * @param {boolean} override If true, the obj passed in becomes - * the execution scope of the listener - * @return {boolean} True if the action was successful or defered, - * false if one or more of the elements - * could not have the listener attached, - * or if the operation throws an exception. - * @static - */ - addListener: function(el, sType, fn, obj, override) { - - if (!fn || !fn.call) { - return false; - } - - // The el argument can be an array of elements or element ids. - if ( this._isValidCollection(el)) { - var ok = true; - for (var i=0,len=el.length; i<len; ++i) { - ok = this.on(el[i], - sType, - fn, - obj, - override) && ok; - } - return ok; - - } else if (typeof el == "string") { - var oEl = this.getEl(el); - // If the el argument is a string, we assume it is - // actually the id of the element. If the page is loaded - // we convert el to the actual element, otherwise we - // defer attaching the event until onload event fires - - // check to see if we need to delay hooking up the event - // until after the page loads. - if (oEl) { - el = oEl; - } else { - // defer adding the event until the element is available - this.onAvailable(el, function() { - YAHOO.util.Event.on(el, sType, fn, obj, override); - }); - - return true; - } - } - - // Element should be an html element or an array if we get - // here. - if (!el) { - return false; - } - - // we need to make sure we fire registered unload events - // prior to automatically unhooking them. So we hang on to - // these instead of attaching them to the window and fire the - // handles explicitly during our one unload event. - if ("unload" == sType && obj !== this) { - unloadListeners[unloadListeners.length] = - [el, sType, fn, obj, override]; - return true; - } - - - // if the user chooses to override the scope, we use the custom - // object passed in, otherwise the executing scope will be the - // HTML element that the event is registered on - var scope = el; - if (override) { - if (override === true) { - scope = obj; - } else { - scope = override; - } - } - - // wrap the function so we can return the obj object when - // the event fires; - var wrappedFn = function(e) { - return fn.call(scope, YAHOO.util.Event.getEvent(e), - obj); - }; - - var li = [el, sType, fn, wrappedFn, scope]; - var index = listeners.length; - // cache the listener so we can try to automatically unload - listeners[index] = li; - - if (this.useLegacyEvent(el, sType)) { - var legacyIndex = this.getLegacyIndex(el, sType); - - // Add a new dom0 wrapper if one is not detected for this - // element - if ( legacyIndex == -1 || - el != legacyEvents[legacyIndex][0] ) { - - legacyIndex = legacyEvents.length; - legacyMap[el.id + sType] = legacyIndex; - - // cache the signature for the DOM0 event, and - // include the existing handler for the event, if any - legacyEvents[legacyIndex] = - [el, sType, el["on" + sType]]; - legacyHandlers[legacyIndex] = []; - - el["on" + sType] = - function(e) { - YAHOO.util.Event.fireLegacyEvent( - YAHOO.util.Event.getEvent(e), legacyIndex); - }; - } - - // add a reference to the wrapped listener to our custom - // stack of events - //legacyHandlers[legacyIndex].push(index); - legacyHandlers[legacyIndex].push(li); - - } else { - try { - this._simpleAdd(el, sType, wrappedFn, false); - } catch(e) { - // handle an error trying to attach an event. If it fails - // we need to clean up the cache - this.removeListener(el, sType, fn); - return false; - } - } - - return true; - - }, - - /** - * When using legacy events, the handler is routed to this object - * so we can fire our custom listener stack. - * @method fireLegacyEvent - * @static - * @private - */ - fireLegacyEvent: function(e, legacyIndex) { - var ok = true; - - var le = legacyHandlers[legacyIndex]; - for (var i=0,len=le.length; i<len; ++i) { - var li = le[i]; - if ( li && li[this.WFN] ) { - var scope = li[this.ADJ_SCOPE]; - var ret = li[this.WFN].call(scope, e); - ok = (ok && ret); - } - } - - return ok; - }, - - /** - * Returns the legacy event index that matches the supplied - * signature - * @method getLegacyIndex - * @static - * @private - */ - getLegacyIndex: function(el, sType) { - var key = this.generateId(el) + sType; - if (typeof legacyMap[key] == "undefined") { - return -1; - } else { - return legacyMap[key]; - } - }, - - /** - * Logic that determines when we should automatically use legacy - * events instead of DOM2 events. - * @method useLegacyEvent - * @static - * @private - */ - useLegacyEvent: function(el, sType) { - if (!el.addEventListener && !el.attachEvent) { - return true; - } else if (this.isSafari) { - if ("click" == sType || "dblclick" == sType) { - return true; - } - } - return false; - }, - - /** - * Removes an event handler - * - * @method removeListener - * - * @param {Object} el the html element or the id of the element to - * assign the event to. - * @param {String} sType the type of event to remove. - * @param {Function} fn the method the event invokes. If fn is - * undefined, then all event handlers for the type of event are - * removed. - * @return {boolean} true if the unbind was successful, false - * otherwise. - * @static - */ - removeListener: function(el, sType, fn) { - var i, len; - - // The el argument can be a string - if (typeof el == "string") { - el = this.getEl(el); - // The el argument can be an array of elements or element ids. - } else if ( this._isValidCollection(el)) { - var ok = true; - for (i=0,len=el.length; i<len; ++i) { - ok = ( this.removeListener(el[i], sType, fn) && ok ); - } - return ok; - } - - if (!fn || !fn.call) { - //return false; - return this.purgeElement(el, false, sType); - } - - if ("unload" == sType) { - - for (i=0, len=unloadListeners.length; i<len; i++) { - var li = unloadListeners[i]; - if (li && - li[0] == el && - li[1] == sType && - li[2] == fn) { - unloadListeners.splice(i, 1); - return true; - } - } - - return false; - } - - var cacheItem = null; - - // The index is a hidden parameter; needed to remove it from - // the method signature because it was tempting users to - // try and take advantage of it, which is not possible. - var index = arguments[3]; - - if ("undefined" == typeof index) { - index = this._getCacheIndex(el, sType, fn); - } - - if (index >= 0) { - cacheItem = listeners[index]; - } - - if (!el || !cacheItem) { - return false; - } - - - if (this.useLegacyEvent(el, sType)) { - var legacyIndex = this.getLegacyIndex(el, sType); - var llist = legacyHandlers[legacyIndex]; - if (llist) { - for (i=0, len=llist.length; i<len; ++i) { - li = llist[i]; - if (li && - li[this.EL] == el && - li[this.TYPE] == sType && - li[this.FN] == fn) { - llist.splice(i, 1); - break; - } - } - } - - } else { - try { - this._simpleRemove(el, sType, cacheItem[this.WFN], false); - } catch(e) { - return false; - } - } - - // removed the wrapped handler - delete listeners[index][this.WFN]; - delete listeners[index][this.FN]; - listeners.splice(index, 1); - - return true; - - }, - - /** - * Returns the event's target element - * @method getTarget - * @param {Event} ev the event - * @param {boolean} resolveTextNode when set to true the target's - * parent will be returned if the target is a - * text node. @deprecated, the text node is - * now resolved automatically - * @return {HTMLElement} the event's target - * @static - */ - getTarget: function(ev, resolveTextNode) { - var t = ev.target || ev.srcElement; - return this.resolveTextNode(t); - }, - - /** - * In some cases, some browsers will return a text node inside - * the actual element that was targeted. This normalizes the - * return value for getTarget and getRelatedTarget. - * @method resolveTextNode - * @param {HTMLElement} node node to resolve - * @return {HTMLElement} the normized node - * @static - */ - resolveTextNode: function(node) { - // if (node && node.nodeName && - // "#TEXT" == node.nodeName.toUpperCase()) { - if (node && 3 == node.nodeType) { - return node.parentNode; - } else { - return node; - } - }, - - /** - * Returns the event's pageX - * @method getPageX - * @param {Event} ev the event - * @return {int} the event's pageX - * @static - */ - getPageX: function(ev) { - var x = ev.pageX; - if (!x && 0 !== x) { - x = ev.clientX || 0; - - if ( this.isIE ) { - x += this._getScrollLeft(); - } - } - - return x; - }, - - /** - * Returns the event's pageY - * @method getPageY - * @param {Event} ev the event - * @return {int} the event's pageY - * @static - */ - getPageY: function(ev) { - var y = ev.pageY; - if (!y && 0 !== y) { - y = ev.clientY || 0; - - if ( this.isIE ) { - y += this._getScrollTop(); - } - } - - return y; - }, - - /** - * Returns the pageX and pageY properties as an indexed array. - * @method getXY - * @param {Event} ev the event - * @return {[x, y]} the pageX and pageY properties of the event - * @static - */ - getXY: function(ev) { - return [this.getPageX(ev), this.getPageY(ev)]; - }, - - /** - * Returns the event's related target - * @method getRelatedTarget - * @param {Event} ev the event - * @return {HTMLElement} the event's relatedTarget - * @static - */ - getRelatedTarget: function(ev) { - var t = ev.relatedTarget; - if (!t) { - if (ev.type == "mouseout") { - t = ev.toElement; - } else if (ev.type == "mouseover") { - t = ev.fromElement; - } - } - - return this.resolveTextNode(t); - }, - - /** - * Returns the time of the event. If the time is not included, the - * event is modified using the current time. - * @method getTime - * @param {Event} ev the event - * @return {Date} the time of the event - * @static - */ - getTime: function(ev) { - if (!ev.time) { - var t = new Date().getTime(); - try { - ev.time = t; - } catch(e) { - return t; - } - } - - return ev.time; - }, - - /** - * Convenience method for stopPropagation + preventDefault - * @method stopEvent - * @param {Event} ev the event - * @static - */ - stopEvent: function(ev) { - this.stopPropagation(ev); - this.preventDefault(ev); - }, - - /** - * Stops event propagation - * @method stopPropagation - * @param {Event} ev the event - * @static - */ - stopPropagation: function(ev) { - if (ev.stopPropagation) { - ev.stopPropagation(); - } else { - ev.cancelBubble = true; - } - }, - - /** - * Prevents the default behavior of the event - * @method preventDefault - * @param {Event} ev the event - * @static - */ - preventDefault: function(ev) { - if (ev.preventDefault) { - ev.preventDefault(); - } else { - ev.returnValue = false; - } - }, - - /** - * Finds the event in the window object, the caller's arguments, or - * in the arguments of another method in the callstack. This is - * executed automatically for events registered through the event - * manager, so the implementer should not normally need to execute - * this function at all. - * @method getEvent - * @param {Event} e the event parameter from the handler - * @return {Event} the event - * @static - */ - getEvent: function(e) { - var ev = e || window.event; - - if (!ev) { - var c = this.getEvent.caller; - while (c) { - ev = c.arguments[0]; - if (ev && Event == ev.constructor) { - break; - } - c = c.caller; - } - } - - return ev; - }, - - /** - * Returns the charcode for an event - * @method getCharCode - * @param {Event} ev the event - * @return {int} the event's charCode - * @static - */ - getCharCode: function(ev) { - return ev.charCode || ev.keyCode || 0; - }, - - /** - * Locating the saved event handler data by function ref - * - * @method _getCacheIndex - * @static - * @private - */ - _getCacheIndex: function(el, sType, fn) { - for (var i=0,len=listeners.length; i<len; ++i) { - var li = listeners[i]; - if ( li && - li[this.FN] == fn && - li[this.EL] == el && - li[this.TYPE] == sType ) { - return i; - } - } - - return -1; - }, - - /** - * Generates an unique ID for the element if it does not already - * have one. - * @method generateId - * @param el the element to create the id for - * @return {string} the resulting id of the element - * @static - */ - generateId: function(el) { - var id = el.id; - - if (!id) { - id = "yuievtautoid-" + counter; - ++counter; - el.id = id; - } - - return id; - }, - - /** - * We want to be able to use getElementsByTagName as a collection - * to attach a group of events to. Unfortunately, different - * browsers return different types of collections. This function - * tests to determine if the object is array-like. It will also - * fail if the object is an array, but is empty. - * @method _isValidCollection - * @param o the object to test - * @return {boolean} true if the object is array-like and populated - * @static - * @private - */ - _isValidCollection: function(o) { - // this.logger.debug(o.constructor.toString()) - // this.logger.debug(typeof o) - - return ( o && // o is something - o.length && // o is indexed - typeof o != "string" && // o is not a string - !o.tagName && // o is not an HTML element - !o.alert && // o is not a window - typeof o[0] != "undefined" ); - - }, - - /** - * @private - * @property elCache - * DOM element cache - * @static - */ - elCache: {}, - - /** - * We cache elements bound by id because when the unload event - * fires, we can no longer use document.getElementById - * @method getEl - * @static - * @private - */ - getEl: function(id) { - return document.getElementById(id); - }, - - /** - * Clears the element cache - * @deprecated Elements are not cached any longer - * @method clearCache - * @static - * @private - */ - clearCache: function() { }, - - /** - * hook up any deferred listeners - * @method _load - * @static - * @private - */ - _load: function(e) { - loadComplete = true; - var EU = YAHOO.util.Event; - // Remove the listener to assist with the IE memory issue, but not - // for other browsers because FF 1.0x does not like it. - if (this.isIE) { - EU._simpleRemove(window, "load", EU._load); - } - }, - - /** - * Polling function that runs before the onload event fires, - * attempting to attach to DOM Nodes as soon as they are - * available - * @method _tryPreloadAttach - * @static - * @private - */ - _tryPreloadAttach: function() { - - if (this.locked) { - return false; - } - - this.locked = true; - - - // keep trying until after the page is loaded. We need to - // check the page load state prior to trying to bind the - // elements so that we can be certain all elements have been - // tested appropriately - var tryAgain = !loadComplete; - if (!tryAgain) { - tryAgain = (retryCount > 0); - } - - // onAvailable - var notAvail = []; - for (var i=0,len=onAvailStack.length; i<len ; ++i) { - var item = onAvailStack[i]; - if (item) { - var el = this.getEl(item.id); - - if (el) { - // The element is available, but not necessarily ready - // @todo verify IE7 compatibility - // @todo should we test parentNode.nextSibling? - // @todo re-evaluate global content ready - if ( !item.checkReady || - loadComplete || - el.nextSibling || - (document && document.body) ) { - - var scope = el; - if (item.override) { - if (item.override === true) { - scope = item.obj; - } else { - scope = item.override; - } - } - item.fn.call(scope, item.obj); - //delete onAvailStack[i]; - // null out instead of delete for Opera - onAvailStack[i] = null; - } - } else { - notAvail.push(item); - } - } - } - - retryCount = (notAvail.length === 0) ? 0 : retryCount - 1; - - if (tryAgain) { - // we may need to strip the nulled out items here - this.startInterval(); - } else { - clearInterval(this._interval); - this._interval = null; - } - - this.locked = false; - - return true; - - }, - - /** - * Removes all listeners attached to the given element via addListener. - * Optionally, the node's children can also be purged. - * Optionally, you can specify a specific type of event to remove. - * @method purgeElement - * @param {HTMLElement} el the element to purge - * @param {boolean} recurse recursively purge this element's children - * as well. Use with caution. - * @param {string} sType optional type of listener to purge. If - * left out, all listeners will be removed - * @static - */ - purgeElement: function(el, recurse, sType) { - var elListeners = this.getListeners(el, sType); - if (elListeners) { - for (var i=0,len=elListeners.length; i<len ; ++i) { - var l = elListeners[i]; - // can't use the index on the changing collection - //this.removeListener(el, l.type, l.fn, l.index); - this.removeListener(el, l.type, l.fn); - } - } - - if (recurse && el && el.childNodes) { - for (i=0,len=el.childNodes.length; i<len ; ++i) { - this.purgeElement(el.childNodes[i], recurse, sType); - } - } - }, - - /** - * Returns all listeners attached to the given element via addListener. - * Optionally, you can specify a specific type of event to return. - * @method getListeners - * @param el {HTMLElement} the element to inspect - * @param sType {string} optional type of listener to return. If - * left out, all listeners will be returned - * @return {Object} the listener. Contains the following fields: - * type: (string) the type of event - * fn: (function) the callback supplied to addListener - * obj: (object) the custom object supplied to addListener - * adjust: (boolean) whether or not to adjust the default scope - * index: (int) its position in the Event util listener cache - * @static - */ - getListeners: function(el, sType) { - var elListeners = []; - if (listeners && listeners.length > 0) { - for (var i=0,len=listeners.length; i<len ; ++i) { - var l = listeners[i]; - if ( l && l[this.EL] === el && - (!sType || sType === l[this.TYPE]) ) { - elListeners.push({ - type: l[this.TYPE], - fn: l[this.FN], - obj: l[this.OBJ], - adjust: l[this.ADJ_SCOPE], - index: i - }); - } - } - } - - return (elListeners.length) ? elListeners : null; - }, - - /** - * Removes all listeners registered by pe.event. Called - * automatically during the unload event. - * @method _unload - * @static - * @private - */ - _unload: function(e) { - - var EU = YAHOO.util.Event, i, j, l, len, index; - - for (i=0,len=unloadListeners.length; i<len; ++i) { - l = unloadListeners[i]; - if (l) { - var scope = window; - if (l[EU.ADJ_SCOPE]) { - if (l[EU.ADJ_SCOPE] === true) { - scope = l[EU.OBJ]; - } else { - scope = l[EU.ADJ_SCOPE]; - } - } - l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ] ); - unloadListeners[i] = null; - l=null; - scope=null; - } - } - - unloadListeners = null; - - if (listeners && listeners.length > 0) { - j = listeners.length; - while (j) { - index = j-1; - l = listeners[index]; - if (l) { - EU.removeListener(l[EU.EL], l[EU.TYPE], - l[EU.FN], index); - } - j = j - 1; - } - l=null; - - EU.clearCache(); - } - - for (i=0,len=legacyEvents.length; i<len; ++i) { - // dereference the element - //delete legacyEvents[i][0]; - legacyEvents[i][0] = null; - - // delete the array item - //delete legacyEvents[i]; - legacyEvents[i] = null; - } - - legacyEvents = null; - - EU._simpleRemove(window, "unload", EU._unload); - - }, - - /** - * Returns scrollLeft - * @method _getScrollLeft - * @static - * @private - */ - _getScrollLeft: function() { - return this._getScroll()[1]; - }, - - /** - * Returns scrollTop - * @method _getScrollTop - * @static - * @private - */ - _getScrollTop: function() { - return this._getScroll()[0]; - }, - - /** - * Returns the scrollTop and scrollLeft. Used to calculate the - * pageX and pageY in Internet Explorer - * @method _getScroll - * @static - * @private - */ - _getScroll: function() { - var dd = document.documentElement, db = document.body; - if (dd && (dd.scrollTop || dd.scrollLeft)) { - return [dd.scrollTop, dd.scrollLeft]; - } else if (db) { - return [db.scrollTop, db.scrollLeft]; - } else { - return [0, 0]; - } - }, - - /** - * Adds a DOM event directly without the caching, cleanup, scope adj, etc - * - * @method _simpleAdd - * @param {HTMLElement} el the element to bind the handler to - * @param {string} sType the type of event handler - * @param {function} fn the callback to invoke - * @param {boolen} capture capture or bubble phase - * @static - * @private - */ - _simpleAdd: function () { - if (window.addEventListener) { - return function(el, sType, fn, capture) { - el.addEventListener(sType, fn, (capture)); - }; - } else if (window.attachEvent) { - return function(el, sType, fn, capture) { - el.attachEvent("on" + sType, fn); - }; - } else { - return function(){}; - } - }(), - - /** - * Basic remove listener - * - * @method _simpleRemove - * @param {HTMLElement} el the element to bind the handler to - * @param {string} sType the type of event handler - * @param {function} fn the callback to invoke - * @param {boolen} capture capture or bubble phase - * @static - * @private - */ - _simpleRemove: function() { - if (window.removeEventListener) { - return function (el, sType, fn, capture) { - el.removeEventListener(sType, fn, (capture)); - }; - } else if (window.detachEvent) { - return function (el, sType, fn) { - el.detachEvent("on" + sType, fn); - }; - } else { - return function(){}; - } - }() - }; - - }(); - - (function() { - var EU = YAHOO.util.Event; - - /** - * YAHOO.util.Event.on is an alias for addListener - * @method on - * @see addListener - * @static - */ - EU.on = EU.addListener; - - // YAHOO.mix(EU, YAHOO.util.EventProvider.prototype); - // EU.createEvent("DOMContentReady"); - // EU.subscribe("DOMContentReady", EU._load); - - if (document && document.body) { - EU._load(); - } else { - // EU._simpleAdd(document, "DOMContentLoaded", EU._load); - EU._simpleAdd(window, "load", EU._load); - } - EU._simpleAdd(window, "unload", EU._unload); - EU._tryPreloadAttach(); - })(); -} - -/** - * EventProvider is designed to be used with YAHOO.augment to wrap - * CustomEvents in an interface that allows events to be subscribed to - * and fired by name. This makes it possible for implementing code to - * subscribe to an event that either has not been created yet, or will - * not be created at all. - * - * @Class EventProvider - */ -YAHOO.util.EventProvider = function() { }; - -YAHOO.util.EventProvider.prototype = { - - /** - * Private storage of custom events - * @property __yui_events - * @type Object[] - * @private - */ - __yui_events: null, - - /** - * Private storage of custom event subscribers - * @property __yui_subscribers - * @type Object[] - * @private - */ - __yui_subscribers: null, - - /** - * Subscribe to a CustomEvent by event type - * - * @method subscribe - * @param p_type {string} the type, or name of the event - * @param p_fn {function} the function to exectute when the event fires - * @param p_obj - * @param p_obj {Object} An object to be passed along when the event - * fires - * @param p_override {boolean} If true, the obj passed in becomes the - * execution scope of the listener - */ - subscribe: function(p_type, p_fn, p_obj, p_override) { - - this.__yui_events = this.__yui_events || {}; - var ce = this.__yui_events[p_type]; - - if (ce) { - ce.subscribe(p_fn, p_obj, p_override); - } else { - this.__yui_subscribers = this.__yui_subscribers || {}; - var subs = this.__yui_subscribers; - if (!subs[p_type]) { - subs[p_type] = []; - } - subs[p_type].push( - { fn: p_fn, obj: p_obj, override: p_override } ); - } - }, - - /** - * Unsubscribes the from the specified event - * @method unsubscribe - * @param p_type {string} The type, or name of the event - * @param p_fn {Function} The function to execute - * @param p_obj {Object} The custom object passed to subscribe (optional) - * @return {boolean} true if the subscriber was found and detached. - */ - unsubscribe: function(p_type, p_fn, p_obj) { - this.__yui_events = this.__yui_events || {}; - var ce = this.__yui_events[p_type]; - if (ce) { - return ce.unsubscribe(p_fn, p_obj); - } else { - return false; - } - }, - - /** - * Creates a new custom event of the specified type. If a custom event - * by that name already exists, it will not be re-created. In either - * case the custom event is returned. - * - * @method createEvent - * - * @param p_type {string} the type, or name of the event - * @param p_config {object} optional config params. Valid properties are: - * - * <ul> - * <li> - * scope: defines the default execution scope. If not defined - * the default scope will be this instance. - * </li> - * <li> - * silent: if true, the custom event will not generate log messages. - * This is false by default. - * </li> - * <li> - * onSubscribeCallback: specifies a callback to execute when the - * event has a new subscriber. This will fire immediately for - * each queued subscriber if any exist prior to the creation of - * the event. - * </li> - * </ul> - * - * @return {CustomEvent} the custom event - * - */ - createEvent: function(p_type, p_config) { - - this.__yui_events = this.__yui_events || {}; - var opts = p_config || {}; - var events = this.__yui_events; - - if (events[p_type]) { - } else { - - var scope = opts.scope || this; - var silent = opts.silent || null; - - var ce = new YAHOO.util.CustomEvent(p_type, scope, silent, - YAHOO.util.CustomEvent.FLAT); - events[p_type] = ce; - - if (opts.onSubscribeCallback) { - ce.subscribeEvent.subscribe(opts.onSubscribeCallback); - } - - this.__yui_subscribers = this.__yui_subscribers || {}; - var qs = this.__yui_subscribers[p_type]; - - if (qs) { - for (var i=0; i<qs.length; ++i) { - ce.subscribe(qs[i].fn, qs[i].obj, qs[i].override); - } - } - } - - return events[p_type]; - }, - - /** - * Fire a custom event by name. The callback functions will be executed - * from the scope specified when the event was created, and with the - * following parameters: - * <ul> - * <li>The first argument fire() was executed with</li> - * <li>The custom object (if any) that was passed into the subscribe() - * method</li> - * </ul> - * @method fireEvent - * @param p_type {string} the type, or name of the event - * @param arguments {Object*} an arbitrary set of parameters to pass to - * the handler. - * @return {boolean} the return value from CustomEvent.fire, or null if - * the custom event does not exist. - */ - fireEvent: function(p_type, arg1, arg2, etc) { - - this.__yui_events = this.__yui_events || {}; - var ce = this.__yui_events[p_type]; - - if (ce) { - var args = []; - for (var i=1; i<arguments.length; ++i) { - args.push(arguments[i]); - } - return ce.fire.apply(ce, args); - } else { - return null; - } - }, - - /** - * Returns true if the custom event of the provided type has been created - * with createEvent. - * @method hasEvent - * @param type {string} the type, or name of the event - */ - hasEvent: function(type) { - if (this.__yui_events) { - if (this.__yui_events[type]) { - return true; - } - } - return false; - } - -}; - diff --git a/reports/site_media/yui/round_tabs.css b/reports/site_media/yui/round_tabs.css deleted file mode 100644 index 6fb094980..000000000 --- a/reports/site_media/yui/round_tabs.css +++ /dev/null @@ -1,76 +0,0 @@ -.yui-navset .yui-content { - border:1px solid #ccc; -} -.yui-navset .yui-nav .selected a, .yui-navset .yui-nav a:hover { - background-color:#fff; -} - -.yui-navset .yui-nav li a { - background:#e5e5e5 url(../img/round_4px_trans_gray.gif) no-repeat; -} -.yui-navset .yui-nav li a em { - background:transparent url(../img/round_4px_trans_gray.gif) no-repeat top right; - padding:0.5em; -} - -/* top oriented */ - -.yui-navset-top .yui-nav { margin-bottom:-1px; } /* for overlap, based on content border-width */ -.yui-navset-top .yui-nav li a { - border-bottom:1px solid #ccc; -} - -.yui-navset-top .yui-nav .selected a { border-bottom:0; } -.yui-navset-top .yui-nav .selected a em { padding-bottom:0.6em; } /* adjust height */ - -/* top & bottom oriented */ -.yui-navset-top .yui-nav li a em, .yui-navset-bottom .yui-nav li a em { - margin-left:4px; /* based on border-radius */ - padding-right:8px; /* based on border-radius (2x left to balance margin) */ - padding-left:4px; -} - -/* bottom oriented */ - -.yui-navset-bottom .yui-nav { margin-top:-1px; } /* for overlap, based on content border-width */ -.yui-navset-bottom .yui-nav li a { border-top:1px solid #ccc; } - -.yui-navset-bottom .yui-nav .selected a { border-top:0; } -.yui-navset-bottom .yui-nav .selected a em { padding-top:0.6em; } /* adjust height */ - -.yui-navset-bottom .yui-nav li a { background-position:bottom left; } -.yui-navset-bottom .yui-nav li a em { background-position:bottom right; } - -/* left oriented */ - -.yui-navset-left .yui-content { margin-left:-1px; } /* for overlap, based on content border-width */ - -.yui-navset-left .yui-nav li a { - border-right:1px solid #ccc; - padding-bottom:4px; -} - -.yui-navset-left .yui-nav li a em, .yui-navset-right .yui-nav li a em { - padding-top:8px; /* based on border-radius (2x left to balance margin) */ -} - -.yui-navset-left .yui-nav .selected a { border-right:0; } -.yui-navset-left .yui-nav .selected a em { padding-left:0.6em; } /* adjust width */ - -.yui-navset-left .yui-nav li a { background-position:bottom left; } -.yui-navset-left .yui-nav li a em { background-position:top left; } - -/* right oriented */ - -.yui-navset-right .yui-content { margin-right:-1px; } /* for overlap, based on content border-width */ - -.yui-navset-right .yui-nav li a { - border-left:1px solid #ccc; - padding-bottom:4px; -} - -.yui-navset-right .yui-nav .selected a { border-left:0; } -.yui-navset-right .yui-nav .selected a em { padding-left:0.6em; } /* adjust width */ - -.yui-navset-right .yui-nav li a { background-position:bottom right; } -.yui-navset-right .yui-nav li a em { background-position:top right; }
\ No newline at end of file diff --git a/reports/site_media/yui/tabview/README b/reports/site_media/yui/tabview/README deleted file mode 100644 index e49ec56d0..000000000 --- a/reports/site_media/yui/tabview/README +++ /dev/null @@ -1,16 +0,0 @@ -*** version 0.12.2 *** - -* var Tab is now private -* fixed Element.configureAttribute - -*** version 0.12.1 *** - -* tabs.css renamed to tabview.css -* calls to "set" now queued so they can be made before "contentReady" - - -*** version 0.12.0 *** - -* TabView widget introduced - -* Note: border_tabs.css included as basic skin to enable "tabs" look diff --git a/reports/site_media/yui/tabview/assets/border_tabs.css b/reports/site_media/yui/tabview/assets/border_tabs.css deleted file mode 100644 index 28b1967dd..000000000 --- a/reports/site_media/yui/tabview/assets/border_tabs.css +++ /dev/null @@ -1,48 +0,0 @@ -.yui-navset .yui-nav li a, .yui-navset .yui-content { - border:1px solid #000; /* label and content borders */ -} - -.yui-navset .yui-nav .selected a, .yui-navset .yui-nav a:hover, .yui-navset .yui-content { - background-color:#f6f7ee; /* active tab, tab hover, and content bgcolor */ -} - -.yui-navset .yui-nav li em { padding:.5em; } /* tab padding */ - -/* defaults to orientation "top" */ -.yui-navset .yui-nav .selected a { - border-bottom-width:0; /* no bottom border for active tab */ - padding-bottom:1px; /* to match height of other tabs */ -} - -.yui-navset .yui-content { - margin-top:-1px; /* for active tab overlap */ -} - -/* overrides for other orientations */ - -.yui-navset-bottom .yui-nav .selected a { - border-width:0 1px 1px; /* no top border for active tab */ - padding:1px 0 0; /* to match height of other tabs */ -} - -.yui-navset-bottom .yui-content { - margin:0 0 -1px; /* for active tab overlap */ -} - -.yui-navset-left .yui-nav li.selected a { - border-width:1px 0 1px 1px; /* no right border for active tab */ - padding:0 1px 0 0; /* to match width of other tabs */ -} - -.yui-navset-left .yui-content { - margin:0 0 0 -1px; /* for active tab overlap */ -} - -.yui-navset-right .yui-nav li.selected a { - border-width:1px 1px 1px 0; /* no left border for active tab */ - padding:0 0 0 1px; /* to match width of other tabs */ -} - -.yui-navset-right .yui-content { - margin:0 -1px 0 0; /* for active tab overlap */ -}
\ No newline at end of file diff --git a/reports/site_media/yui/tabview/assets/tabview.css b/reports/site_media/yui/tabview/assets/tabview.css deleted file mode 100644 index f82720ae4..000000000 --- a/reports/site_media/yui/tabview/assets/tabview.css +++ /dev/null @@ -1,69 +0,0 @@ -/* default space between tabs */ -.yui-navset .yui-nav li { - margin-right:0.5em; /* horizontal tabs */ -} -.yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li { - margin:0 0 0.5em; /* vertical tabs */ -} - -/* default width for side tabs */ -.yui-navset-left .yui-nav, .yui-navset-right .yui-nav { width:6em; } -.yui-navset-left { padding-left:6em; } /* map to nav width */ -.yui-navset-right { padding-right:6em; } /* ditto */ - -/* core */ - -.yui-nav, .yui-nav li { - margin:0; - padding:0; - list-style:none; -} -.yui-navset li em { font-style:normal; } - -.yui-navset { - position:relative; /* contain absolute positioned tabs (left/right) */ - zoom:1; -} - -.yui-navset .yui-content { zoom:1; } - -.yui-navset .yui-nav li { - display:inline-block; - display:-moz-inline-stack; - *display:inline; /* IE */ - vertical-align:bottom; /* safari: for overlap */ - cursor:pointer; /* gecko: due to -moz-inline-stack on anchor */ - zoom:1; /* IE: kill space between horizontal tabs */ -} - -.yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li { - display:block; -} - -.yui-navset .yui-nav a { - outline:0; /* gecko: keep from shifting */ -} - -.yui-navset .yui-nav a { position:relative; } /* IE: to allow overlap */ - -.yui-navset .yui-nav li a { - display:block; - display:inline-block; - vertical-align:bottom; /* safari: for overlap */ - zoom:1; -} - -.yui-navset-left .yui-nav li a, .yui-navset-right .yui-nav li a { - display:block; -} - -.yui-navset-bottom .yui-nav li a { - vertical-align:text-top; /* for inline overlap (reverse for Op border bug) */ -} - -.yui-navset .yui-nav li a em { display:block; } - -/* position left and right oriented tabs */ -.yui-navset-left .yui-nav, .yui-navset-right .yui-nav { position:absolute; z-index:1; } -.yui-navset-left .yui-nav { left:0; } -.yui-navset-right .yui-nav { right:0; } diff --git a/reports/site_media/yui/tabview/tabview-debug.js b/reports/site_media/yui/tabview/tabview-debug.js deleted file mode 100644 index 4dd2b0323..000000000 --- a/reports/site_media/yui/tabview/tabview-debug.js +++ /dev/null @@ -1,1964 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ -YAHOO.util.Lang = { - isArray: function(val) { // frames lose type, so test constructor string - if (val.constructor && val.constructor.toString().indexOf('Array') > -1) { - return true; - } else { - return YAHOO.util.Lang.isObject(val) && val.constructor == Array; - } - }, - - isBoolean: function(val) { - return typeof val == 'boolean'; - }, - - isFunction: function(val) { - return typeof val == 'function'; - }, - - isNull: function(val) { - return val === null; - }, - - isNumber: function(val) { - return !isNaN(val); - }, - - isObject: function(val) { - return typeof val == 'object' || YAHOO.util.Lang.isFunction(val); - }, - - isString: function(val) { - return typeof val == 'string'; - }, - - isUndefined: function(val) { - return typeof val == 'undefined'; - } -}; - -/** - * Provides Attribute configurations. - * @namespace YAHOO.util - * @class Attribute - * @constructor - * @param hash {Object} The intial Attribute. - * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance. - */ - -YAHOO.util.Attribute = function(hash, owner) { - if (owner) { - this.owner = owner; - this.configure(hash, true); - } -}; - -YAHOO.util.Attribute.prototype = { - /** - * The name of the attribute. - * @property name - * @type String - */ - name: undefined, - - /** - * The value of the attribute. - * @property value - * @type String - */ - value: null, - - /** - * The owner of the attribute. - * @property owner - * @type YAHOO.util.AttributeProvider - */ - owner: null, - - /** - * Whether or not the attribute is read only. - * @property readOnly - * @type Boolean - */ - readOnly: false, - - /** - * Whether or not the attribute can only be written once. - * @property writeOnce - * @type Boolean - */ - writeOnce: false, - - /** - * The attribute's initial configuration. - * @private - * @property _initialConfig - * @type Object - */ - _initialConfig: null, - - /** - * Whether or not the attribute's value has been set. - * @private - * @property _written - * @type Boolean - */ - _written: false, - - /** - * The method to use when setting the attribute's value. - * The method recieves the new value as the only argument. - * @property method - * @type Function - */ - method: null, - - /** - * The validator to use when setting the attribute's value. - * @property validator - * @type Function - * @return Boolean - */ - validator: null, - - /** - * Retrieves the current value of the attribute. - * @method getValue - * @return {any} The current value of the attribute. - */ - getValue: function() { - return this.value; - }, - - /** - * Sets the value of the attribute and fires beforeChange and change events. - * @method setValue - * @param {Any} value The value to apply to the attribute. - * @param {Boolean} silent If true the change events will not be fired. - * @return {Boolean} Whether or not the value was set. - */ - setValue: function(value, silent) { - var beforeRetVal; - var owner = this.owner; - var name = this.name; - - var event = { - type: name, - prevValue: this.getValue(), - newValue: value - }; - - if (this.readOnly || ( this.writeOnce && this._written) ) { - return false; // write not allowed - } - - if (this.validator && !this.validator.call(owner, value) ) { - return false; // invalid value - } - - if (!silent) { - beforeRetVal = owner.fireBeforeChangeEvent(event); - if (beforeRetVal === false) { - YAHOO.log('setValue ' + name + - 'cancelled by beforeChange event', 'info', 'Attribute'); - return false; - } - } - - if (this.method) { - this.method.call(owner, value); - } - - this.value = value; - this._written = true; - - event.type = name; - - if (!silent) { - this.owner.fireChangeEvent(event); - } - - return true; - }, - - /** - * Allows for configuring the Attribute's properties. - * @method configure - * @param {Object} map A key-value map of Attribute properties. - * @param {Boolean} init Whether or not this should become the initial config. - */ - configure: function(map, init) { - map = map || {}; - this._written = false; // reset writeOnce - this._initialConfig = this._initialConfig || {}; - - for (var key in map) { - if ( key && map.hasOwnProperty(key) ) { - this[key] = map[key]; - if (init) { - this._initialConfig[key] = map[key]; - } - } - } - }, - - /** - * Resets the value to the initial config value. - * @method resetValue - * @return {Boolean} Whether or not the value was set. - */ - resetValue: function() { - return this.setValue(this._initialConfig.value); - }, - - /** - * Resets the attribute config to the initial config state. - * @method resetConfig - */ - resetConfig: function() { - this.configure(this._initialConfig); - }, - - /** - * Resets the value to the current value. - * Useful when values may have gotten out of sync with actual properties. - * @method refresh - * @return {Boolean} Whether or not the value was set. - */ - refresh: function(silent) { - this.setValue(this.value, silent); - } -}; - -(function() { - var Lang = YAHOO.util.Lang; - - /* - Copyright (c) 2006, Yahoo! Inc. All rights reserved. - Code licensed under the BSD License: - http://developer.yahoo.net/yui/license.txt - */ - - /** - * Provides and manages YAHOO.util.Attribute instances - * @namespace YAHOO.util - * @class AttributeProvider - * @uses YAHOO.util.EventProvider - */ - YAHOO.util.AttributeProvider = function() {}; - - YAHOO.util.AttributeProvider.prototype = { - - /** - * A key-value map of Attribute configurations - * @property _configs - * @protected (may be used by subclasses and augmentors) - * @private - * @type {Object} - */ - _configs: null, - /** - * Returns the current value of the attribute. - * @method get - * @param {String} key The attribute whose value will be returned. - */ - get: function(key){ - var configs = this._configs || {}; - var config = configs[key]; - - if (!config) { - YAHOO.log(key + ' not found', 'error', 'AttributeProvider'); - return undefined; - } - - return config.value; - }, - - /** - * Sets the value of a config. - * @method set - * @param {String} key The name of the attribute - * @param {Any} value The value to apply to the attribute - * @param {Boolean} silent Whether or not to suppress change events - * @return {Boolean} Whether or not the value was set. - */ - set: function(key, value, silent){ - var configs = this._configs || {}; - var config = configs[key]; - - if (!config) { - YAHOO.log('set failed: ' + key + ' not found', - 'error', 'AttributeProvider'); - return false; - } - - return config.setValue(value, silent); - }, - - /** - * Returns an array of attribute names. - * @method getAttributeKeys - * @return {Array} An array of attribute names. - */ - getAttributeKeys: function(){ - var configs = this._configs; - var keys = []; - var config; - for (var key in configs) { - config = configs[key]; - if ( configs.hasOwnProperty(key) && - !Lang.isUndefined(config) ) { - keys[keys.length] = key; - } - } - - return keys; - }, - - /** - * Sets multiple attribute values. - * @method setAttributes - * @param {Object} map A key-value map of attributes - * @param {Boolean} silent Whether or not to suppress change events - */ - setAttributes: function(map, silent){ - for (var key in map) { - if ( map.hasOwnProperty(key) ) { - this.set(key, map[key], silent); - } - } - }, - - /** - * Resets the specified attribute's value to its initial value. - * @method resetValue - * @param {String} key The name of the attribute - * @param {Boolean} silent Whether or not to suppress change events - * @return {Boolean} Whether or not the value was set - */ - resetValue: function(key, silent){ - var configs = this._configs || {}; - if (configs[key]) { - this.set(key, configs[key]._initialConfig.value, silent); - return true; - } - return false; - }, - - /** - * Sets the attribute's value to its current value. - * @method refresh - * @param {String | Array} key The attribute(s) to refresh - * @param {Boolean} silent Whether or not to suppress change events - */ - refresh: function(key, silent){ - var configs = this._configs; - - key = ( ( Lang.isString(key) ) ? [key] : key ) || - this.getAttributeKeys(); - - for (var i = 0, len = key.length; i < len; ++i) { - if ( // only set if there is a value and not null - configs[key[i]] && - ! Lang.isUndefined(configs[key[i]].value) && - ! Lang.isNull(configs[key[i]].value) ) { - configs[key[i]].refresh(silent); - } - } - }, - - /** - * Adds an Attribute to the AttributeProvider instance. - * @method register - * @param {String} key The attribute's name - * @param {Object} map A key-value map containing the - * attribute's properties. - */ - register: function(key, map) { - this._configs = this._configs || {}; - - if (this._configs[key]) { // dont override - return false; - } - - map.name = key; - this._configs[key] = new YAHOO.util.Attribute(map, this); - return true; - }, - - /** - * Returns the attribute's properties. - * @method getAttributeConfig - * @param {String} key The attribute's name - * @private - * @return {object} A key-value map containing all of the - * attribute's properties. - */ - getAttributeConfig: function(key) { - var configs = this._configs || {}; - var config = configs[key] || {}; - var map = {}; // returning a copy to prevent overrides - - for (key in config) { - if ( config.hasOwnProperty(key) ) { - map[key] = config[key]; - } - } - - return map; - }, - - /** - * Sets or updates an Attribute instance's properties. - * @method configureAttribute - * @param {String} key The attribute's name. - * @param {Object} map A key-value map of attribute properties - * @param {Boolean} init Whether or not this should become the intial config. - */ - configureAttribute: function(key, map, init) { - var configs = this._configs || {}; - - if (!configs[key]) { - YAHOO.log('unable to configure, ' + key + ' not found', - 'error', 'AttributeProvider'); - return false; - } - - configs[key].configure(map, init); - }, - - /** - * Resets an attribute to its intial configuration. - * @method resetAttributeConfig - * @param {String} key The attribute's name. - * @private - */ - resetAttributeConfig: function(key){ - var configs = this._configs || {}; - configs[key].resetConfig(); - }, - - /** - * Fires the attribute's beforeChange event. - * @method fireBeforeChangeEvent - * @param {String} key The attribute's name. - * @param {Obj} e The event object to pass to handlers. - */ - fireBeforeChangeEvent: function(e) { - var type = 'before'; - type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change'; - e.type = type; - return this.fireEvent(e.type, e); - }, - - /** - * Fires the attribute's change event. - * @method fireChangeEvent - * @param {String} key The attribute's name. - * @param {Obj} e The event object to pass to the handlers. - */ - fireChangeEvent: function(e) { - e.type += 'Change'; - return this.fireEvent(e.type, e); - } - }; - - YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider); -})(); - -(function() { -// internal shorthand -var Dom = YAHOO.util.Dom, - Lang = YAHOO.util.Lang, - EventPublisher = YAHOO.util.EventPublisher, - AttributeProvider = YAHOO.util.AttributeProvider; - -/** - * Element provides an interface to an HTMLElement's attributes and common - * methods. Other commonly used attributes are added as well. - * @namespace YAHOO.util - * @class Element - * @uses YAHOO.util.AttributeProvider - * @constructor - * @param el {HTMLElement | String} The html element that - * represents the Element. - * @param {Object} map A key-value map of initial config names and values - */ -YAHOO.util.Element = function(el, map) { - if (arguments.length) { - this.init(el, map); - } -}; - -YAHOO.util.Element.prototype = { - /** - * Dom events supported by the Element instance. - * @property DOM_EVENTS - * @type Object - */ - DOM_EVENTS: null, - - /** - * Wrapper for HTMLElement method. - * @method appendChild - * @param {Boolean} deep Whether or not to do a deep clone - */ - appendChild: function(child) { - child = child.get ? child.get('element') : child; - this.get('element').appendChild(child); - }, - - /** - * Wrapper for HTMLElement method. - * @method getElementsByTagName - * @param {String} tag The tagName to collect - */ - getElementsByTagName: function(tag) { - return this.get('element').getElementsByTagName(tag); - }, - - /** - * Wrapper for HTMLElement method. - * @method hasChildNodes - * @return {Boolean} Whether or not the element has childNodes - */ - hasChildNodes: function() { - return this.get('element').hasChildNodes(); - }, - - /** - * Wrapper for HTMLElement method. - * @method insertBefore - * @param {HTMLElement} element The HTMLElement to insert - * @param {HTMLElement} before The HTMLElement to insert - * the element before. - */ - insertBefore: function(element, before) { - element = element.get ? element.get('element') : element; - before = (before && before.get) ? before.get('element') : before; - - this.get('element').insertBefore(element, before); - }, - - /** - * Wrapper for HTMLElement method. - * @method removeChild - * @param {HTMLElement} child The HTMLElement to remove - */ - removeChild: function(child) { - child = child.get ? child.get('element') : child; - this.get('element').removeChild(child); - return true; - }, - - /** - * Wrapper for HTMLElement method. - * @method replaceChild - * @param {HTMLElement} newNode The HTMLElement to insert - * @param {HTMLElement} oldNode The HTMLElement to replace - */ - replaceChild: function(newNode, oldNode) { - newNode = newNode.get ? newNode.get('element') : newNode; - oldNode = oldNode.get ? oldNode.get('element') : oldNode; - return this.get('element').replaceChild(newNode, oldNode); - }, - - - /** - * Registers Element specific attributes. - * @method initAttributes - * @param {Object} map A key-value map of initial attribute configs - */ - initAttributes: function(map) { - map = map || {}; - var element = Dom.get(map.element) || null; - - /** - * The HTMLElement the Element instance refers to. - * @config element - * @type HTMLElement - */ - this.register('element', { - value: element, - readOnly: true - }); - }, - - /** - * Adds a listener for the given event. These may be DOM or - * customEvent listeners. Any event that is fired via fireEvent - * can be listened for. All handlers receive an event object. - * @method addListener - * @param {String} type The name of the event to listen for - * @param {Function} fn The handler to call when the event fires - * @param {Any} obj A variable to pass to the handler - * @param {Object} scope The object to use for the scope of the handler - */ - addListener: function(type, fn, obj, scope) { - var el = this.get('element'); - var scope = scope || this; - - el = this.get('id') || el; - - if (!this._events[type]) { // create on the fly - if ( this.DOM_EVENTS[type] ) { - YAHOO.util.Event.addListener(el, type, function(e) { - if (e.srcElement && !e.target) { // supplement IE with target - e.target = e.srcElement; - } - this.fireEvent(type, e); - }, obj, scope); - } - - this.createEvent(type, this); - this._events[type] = true; - } - - this.subscribe.apply(this, arguments); // notify via customEvent - }, - - - /** - * Alias for addListener - * @method on - * @param {String} type The name of the event to listen for - * @param {Function} fn The function call when the event fires - * @param {Any} obj A variable to pass to the handler - * @param {Object} scope The object to use for the scope of the handler - */ - on: function() { this.addListener.apply(this, arguments); }, - - - /** - * Remove an event listener - * @method removeListener - * @param {String} type The name of the event to listen for - * @param {Function} fn The function call when the event fires - */ - removeListener: function(type, fn) { - this.unsubscribe.apply(this, arguments); - }, - - /** - * Wrapper for Dom method. - * @method addClass - * @param {String} className The className to add - */ - addClass: function(className) { - Dom.addClass(this.get('element'), className); - }, - - /** - * Wrapper for Dom method. - * @method getElementsByClassName - * @param {String} className The className to collect - * @param {String} tag (optional) The tag to use in - * conjunction with class name - * @return {Array} Array of HTMLElements - */ - getElementsByClassName: function(className, tag) { - return Dom.getElementsByClassName(className, tag, - this.get('element') ); - }, - - /** - * Wrapper for Dom method. - * @method hasClass - * @param {String} className The className to add - * @return {Boolean} Whether or not the element has the class name - */ - hasClass: function(className) { - return Dom.hasClass(this.get('element'), className); - }, - - /** - * Wrapper for Dom method. - * @method removeClass - * @param {String} className The className to remove - */ - removeClass: function(className) { - return Dom.removeClass(this.get('element'), className); - }, - - /** - * Wrapper for Dom method. - * @method replaceClass - * @param {String} oldClassName The className to replace - * @param {String} newClassName The className to add - */ - replaceClass: function(oldClassName, newClassName) { - return Dom.replaceClass(this.get('element'), - oldClassName, newClassName); - }, - - /** - * Wrapper for Dom method. - * @method setStyle - * @param {String} property The style property to set - * @param {String} value The value to apply to the style property - */ - setStyle: function(property, value) { - return Dom.setStyle(this.get('element'), property, value); - }, - - /** - * Wrapper for Dom method. - * @method getStyle - * @param {String} property The style property to retrieve - * @return {String} The current value of the property - */ - getStyle: function(property) { - return Dom.getStyle(this.get('element'), property); - }, - - /** - * Apply any queued set calls. - * @method fireQueue - */ - fireQueue: function() { - var queue = this._queue; - for (var i = 0, len = queue.length; i < len; ++i) { - this[queue[i][0]].apply(this, queue[i][1]); - } - }, - - /** - * Appends the HTMLElement into either the supplied parentNode. - * @method appendTo - * @param {HTMLElement | Element} parentNode The node to append to - * @param {HTMLElement | Element} before An optional node to insert before - */ - appendTo: function(parent, before) { - parent = (parent.get) ? parent.get('element') : Dom.get(parent); - - before = (before && before.get) ? - before.get('element') : Dom.get(before); - var element = this.get('element'); - - var newAddition = !Dom.inDocument(element); - - if (!element) { - YAHOO.log('appendTo failed: element not available', - 'error', 'Element'); - return false; - } - - if (!parent) { - YAHOO.log('appendTo failed: parent not available', - 'error', 'Element'); - return false; - } - - if (element.parent != parent) { - if (before) { - parent.insertBefore(element, before); - } else { - parent.appendChild(element); - } - } - - YAHOO.log(element + 'appended to ' + parent); - - if (!newAddition) { - return false; // note return; no refresh if in document - } - - // if a new addition, refresh HTMLElement any applied attributes - var keys = this.getAttributeKeys(); - - for (var key in keys) { // only refresh HTMLElement attributes - if ( !Lang.isUndefined(element[key]) ) { - this.refresh(key); - } - } - }, - - get: function(key) { - var configs = this._configs || {}; - var el = configs.element; // avoid loop due to 'element' - if (el && !configs[key] && !Lang.isUndefined(el.value[key]) ) { - return el.value[key]; - } - - return AttributeProvider.prototype.get.call(this, key); - }, - - set: function(key, value, silent) { - var el = this.get('element'); - if (!el) { - this._queue[this._queue.length] = ['set', arguments]; - return false; - } - - // set it on the element if not a property - if ( !this._configs[key] && !Lang.isUndefined(el[key]) ) { - _registerHTMLAttr.call(this, key); - } - - return AttributeProvider.prototype.set.apply(this, arguments); - }, - - register: function(key) { // protect html attributes - var configs = this._configs || {}; - var element = this.get('element') || null; - - if ( element && !Lang.isUndefined(element[key]) ) { - YAHOO.log(key + ' is reserved for ' + element, - 'error', 'Element'); - return false; - } - - return AttributeProvider.prototype.register.apply(this, arguments); - }, - - configureAttribute: function(property, map, init) { // protect html attributes - var el = this.get('element'); - if (!el) { - this._queue[this._queue.length] = ['configureAttribute', arguments]; - return; - } - - if (!this._configs[property] && !Lang.isUndefined(el[property]) ) { - _registerHTMLAttr.call(this, property, map); - } - - return AttributeProvider.prototype.configureAttribute.apply(this, arguments); - }, - - getAttributeKeys: function() { - var el = this.get('element'); - var keys = AttributeProvider.prototype.getAttributeKeys.call(this); - - //add any unconfigured element keys - for (var key in el) { - if (!this._configs[key]) { - keys[key] = keys[key] || el[key]; - } - } - - return keys; - }, - - init: function(el, attr) { - this._queue = this._queue || []; - this._events = this._events || {}; - this._configs = this._configs || {}; - attr = attr || {}; - attr.element = attr.element || el || null; - - this.DOM_EVENTS = { - 'click': true, - 'keydown': true, - 'keypress': true, - 'keyup': true, - 'mousedown': true, - 'mousemove': true, - 'mouseout': true, - 'mouseover': true, - 'mouseup': true - }; - - var readyHandler = function() { - this.initAttributes(attr); - - this.setAttributes(attr, true); - this.fireQueue(); - this.fireEvent('contentReady', { - type: 'contentReady', - target: attr.element - }); - }; - - if ( Lang.isString(el) ) { - _registerHTMLAttr.call(this, 'id', { value: el }); - YAHOO.util.Event.onAvailable(el, function() { - attr.element = Dom.get(el); - this.fireEvent('available', { - type: 'available', - target: attr.element - }); - }, this, true); - - YAHOO.util.Event.onContentReady(el, function() { - readyHandler.call(this); - }, this, true); - } else { - readyHandler.call(this); - } - } -}; - -/** - * Sets the value of the property and fires beforeChange and change events. - * @private - * @method _registerHTMLAttr - * @param {YAHOO.util.Element} element The Element instance to - * register the config to. - * @param {String} key The name of the config to register - * @param {Object} map A key-value map of the config's params - */ -var _registerHTMLAttr = function(key, map) { - var el = this.get('element'); - map = map || {}; - map.name = key; - map.method = map.method || function(value) { - el[key] = value; - }; - map.value = map.value || el[key]; - this._configs[key] = new YAHOO.util.Attribute(map, this); -}; - -/** - * Fires when the Element's HTMLElement can be retrieved by Id. - * <p>See: <a href="#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> available<br> - * <code><HTMLElement> - * target</code> the HTMLElement bound to this Element instance<br> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var target = e.target};<br> - * myTabs.addListener('available', handler);</code></p> - * @event available - */ - -/** - * Fires when the Element's HTMLElement subtree is rendered. - * <p>See: <a href="#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> contentReady<br> - * <code><HTMLElement> - * target</code> the HTMLElement bound to this Element instance<br> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var target = e.target};<br> - * myTabs.addListener('contentReady', handler);</code></p> - * @event contentReady - */ - - -YAHOO.augment(YAHOO.util.Element, AttributeProvider); -})(); - -(function() { - var Dom = YAHOO.util.Dom, - Event = YAHOO.util.Event, - Lang = YAHOO.util.Lang; - - /** - * A representation of a Tab's label and content. - * @namespace YAHOO.widget - * @class Tab - * @extends YAHOO.util.Element - * @constructor - * @param element {HTMLElement | String} (optional) The html element that - * represents the TabView. An element will be created if none provided. - * @param {Object} properties A key map of initial properties - */ - var Tab = function(el, attr) { - attr = attr || {}; - if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) { - attr = el; - el = attr.element; - } - - if (!el && !attr.element) { - el = _createTabElement.call(this, attr); - } - - this.loadHandler = { - success: function(o) { - this.set('content', o.responseText); - }, - failure: function(o) { - YAHOO.log('loading failed: ' + o.statusText, - 'error', 'Tab'); - } - }; - - Tab.superclass.constructor.call(this, el, attr); - - this.DOM_EVENTS = {}; // delegating to tabView - }; - - YAHOO.extend(Tab, YAHOO.util.Element); - var proto = Tab.prototype; - - /** - * The default tag name for a Tab's inner element. - * @property LABEL_INNER_TAGNAME - * @type String - * @default "em" - */ - proto.LABEL_TAGNAME = 'em'; - - /** - * The class name applied to active tabs. - * @property ACTIVE_CLASSNAME - * @type String - * @default "on" - */ - proto.ACTIVE_CLASSNAME = 'selected'; - - /** - * The class name applied to disabled tabs. - * @property DISABLED_CLASSNAME - * @type String - * @default "disabled" - */ - proto.DISABLED_CLASSNAME = 'disabled'; - - /** - * The class name applied to dynamic tabs while loading. - * @property LOADING_CLASSNAME - * @type String - * @default "disabled" - */ - proto.LOADING_CLASSNAME = 'loading'; - - /** - * Provides a reference to the connection request object when data is - * loaded dynamically. - * @property dataConnection - * @type Object - */ - proto.dataConnection = null; - - /** - * Object containing success and failure callbacks for loading data. - * @property loadHandler - * @type object - */ - proto.loadHandler = null; - - /** - * Provides a readable name for the tab. - * @method toString - * @return String - */ - proto.toString = function() { - var el = this.get('element'); - var id = el.id || el.tagName; - return "Tab " + id; - }; - - /** - * Registers TabView specific properties. - * @method initAttributes - * @param {Object} attr Hash of initial attributes - */ - proto.initAttributes = function(attr) { - attr = attr || {}; - Tab.superclass.initAttributes.call(this, attr); - - var el = this.get('element'); - - /** - * The event that triggers the tab's activation. - * @config activationEvent - * @type String - */ - this.register('activationEvent', { - value: attr.activationEvent || 'click' - }); - - /** - * The element that contains the tab's label. - * @config labelEl - * @type HTMLElement - */ - this.register('labelEl', { - value: attr.labelEl || _getlabelEl.call(this), - method: function(value) { - var current = this.get('labelEl'); - - if (current) { - if (current == value) { - return false; // already set - } - - this.replaceChild(value, current); - } else if (el.firstChild) { // ensure label is firstChild by default - this.insertBefore(value, el.firstChild); - } else { - this.appendChild(value); - } - } - }); - - /** - * The tab's label text (or innerHTML). - * @config label - * @type String - */ - this.register('label', { - value: attr.label || _getLabel.call(this), - method: function(value) { - var labelEl = this.get('labelEl'); - if (!labelEl) { // create if needed - this.set('labelEl', _createlabelEl.call(this)); - } - - _setLabel.call(this, value); - } - }); - - /** - * The HTMLElement that contains the tab's content. - * @config contentEl - * @type HTMLElement - */ - this.register('contentEl', { // TODO: apply className? - value: attr.contentEl || document.createElement('div'), - method: function(value) { - var current = this.get('contentEl'); - - if (current) { - if (current == value) { - return false; // already set - } - this.replaceChild(value, current); - } - } - }); - - /** - * The tab's content. - * @config content - * @type String - */ - this.register('content', { - value: attr.content, // TODO: what about existing? - method: function(value) { - this.get('contentEl').innerHTML = value; - } - }); - - var _dataLoaded = false; - - /** - * The tab's data source, used for loading content dynamically. - * @config dataSrc - * @type String - */ - this.register('dataSrc', { - value: attr.dataSrc - }); - - /** - * Whether or not content should be reloaded for every view. - * @config cacheData - * @type Boolean - * @default false - */ - this.register('cacheData', { - value: attr.cacheData || false, - validator: Lang.isBoolean - }); - - /** - * The method to use for the data request. - * @config loadMethod - * @type String - * @default "GET" - */ - this.register('loadMethod', { - value: attr.loadMethod || 'GET', - validator: Lang.isString - }); - - /** - * Whether or not any data has been loaded from the server. - * @config dataLoaded - * @type Boolean - */ - this.register('dataLoaded', { - value: false, - validator: Lang.isBoolean, - writeOnce: true - }); - - /** - * Number if milliseconds before aborting and calling failure handler. - * @config dataTimeout - * @type Number - * @default null - */ - this.register('dataTimeout', { - value: attr.dataTimeout || null, - validator: Lang.isNumber - }); - - /** - * Whether or not the tab is currently active. - * If a dataSrc is set for the tab, the content will be loaded from - * the given source. - * @config active - * @type Boolean - */ - this.register('active', { - value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME), - method: function(value) { - if (value === true) { - this.addClass(this.ACTIVE_CLASSNAME); - this.set('title', 'active'); - } else { - this.removeClass(this.ACTIVE_CLASSNAME); - this.set('title', ''); - } - }, - validator: function(value) { - return Lang.isBoolean(value) && !this.get('disabled') ; - } - }); - - /** - * Whether or not the tab is disabled. - * @config disabled - * @type Boolean - */ - this.register('disabled', { - value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME), - method: function(value) { - if (value === true) { - Dom.addClass(this.get('element'), this.DISABLED_CLASSNAME); - } else { - Dom.removeClass(this.get('element'), this.DISABLED_CLASSNAME); - } - }, - validator: Lang.isBoolean - }); - - /** - * The href of the tab's anchor element. - * @config href - * @type String - * @default '#' - */ - this.register('href', { - value: attr.href || '#', - method: function(value) { - this.getElementsByTagName('a')[0].href = value; - }, - validator: Lang.isString - }); - - /** - * The Whether or not the tab's content is visible. - * @config contentVisible - * @type Boolean - * @default false - */ - this.register('contentVisible', { - value: attr.contentVisible, - method: function(value) { - if (value == true) { - this.get('contentEl').style.display = 'block'; - - if ( this.get('dataSrc') ) { - // load dynamic content unless already loaded and caching - if ( !this.get('dataLoaded') || !this.get('cacheData') ) { - _dataConnect.call(this); - } - } - } else { - this.get('contentEl').style.display = 'none'; - } - }, - validator: Lang.isBoolean - }); - }; - - var _createTabElement = function(attr) { - var el = document.createElement('li'); - var a = document.createElement('a'); - - a.href = attr.href || '#'; - - el.appendChild(a); - - var label = attr.label || null; - var labelEl = attr.labelEl || null; - - if (labelEl) { // user supplied labelEl - if (!label) { // user supplied label - label = _getLabel.call(this, labelEl); - } - } else { - labelEl = _createlabelEl.call(this); - } - - a.appendChild(labelEl); - - return el; - }; - - var _getlabelEl = function() { - return this.getElementsByTagName(this.LABEL_TAGNAME)[0]; - }; - - var _createlabelEl = function() { - var el = document.createElement(this.LABEL_TAGNAME); - return el; - }; - - var _setLabel = function(label) { - var el = this.get('labelEl'); - el.innerHTML = label; - }; - - var _getLabel = function() { - var label, - el = this.get('labelEl'); - - if (!el) { - return undefined; - } - - return el.innerHTML; - }; - - var _dataConnect = function() { - if (!YAHOO.util.Connect) { - YAHOO.log('YAHOO.util.Connect dependency not met', - 'error', 'Tab'); - return false; - } - - Dom.addClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME); - - this.dataConnection = YAHOO.util.Connect.asyncRequest( - this.get('loadMethod'), - this.get('dataSrc'), - { - success: function(o) { - this.loadHandler.success.call(this, o); - this.set('dataLoaded', true); - this.dataConnection = null; - Dom.removeClass(this.get('contentEl').parentNode, - this.LOADING_CLASSNAME); - }, - failure: function(o) { - this.loadHandler.failure.call(this, o); - this.dataConnection = null; - Dom.removeClass(this.get('contentEl').parentNode, - this.LOADING_CLASSNAME); - }, - scope: this, - timeout: this.get('dataTimeout') - } - ); - }; - - YAHOO.widget.Tab = Tab; - - /** - * Fires before the active state is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeActiveChange<br> - * <code><Boolean> - * prevValue</code> the current value<br> - * <code><Boolean> - * newValue</code> the new value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeActiveChange', handler);</code></p> - * @event beforeActiveChange - */ - - /** - * Fires after the active state is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> activeChange<br> - * <code><Boolean> - * prevValue</code> the previous value<br> - * <code><Boolean> - * newValue</code> the updated value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('activeChange', handler);</code></p> - * @event activeChange - */ - - /** - * Fires before the tab label is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeLabelChange<br> - * <code><String> - * prevValue</code> the current value<br> - * <code><String> - * newValue</code> the new value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeLabelChange', handler);</code></p> - * @event beforeLabelChange - */ - - /** - * Fires after the tab label is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> labelChange<br> - * <code><String> - * prevValue</code> the previous value<br> - * <code><String> - * newValue</code> the updated value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('labelChange', handler);</code></p> - * @event labelChange - */ - - /** - * Fires before the tab content is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeContentChange<br> - * <code><String> - * prevValue</code> the current value<br> - * <code><String> - * newValue</code> the new value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeContentChange', handler);</code></p> - * @event beforeContentChange - */ - - /** - * Fires after the tab content is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> contentChange<br> - * <code><String> - * prevValue</code> the previous value<br> - * <code><Boolean> - * newValue</code> the updated value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('contentChange', handler);</code></p> - * @event contentChange - */ -})(); - -(function() { - - /** - * The tabview module provides a widget for managing content bound to tabs. - * @module tabview - * @requires yahoo, dom, event - * - */ - /** - * A widget to control tabbed views. - * @namespace YAHOO.widget - * @class TabView - * @extends YAHOO.util.Element - * @constructor - * @param {HTMLElement | String | Object} el(optional) The html - * element that represents the TabView, or the attribute object to use. - * An element will be created if none provided. - * @param {Object} attr (optional) A key map of the tabView's - * initial attributes. Ignored if first arg is attributes object. - */ - YAHOO.widget.TabView = function(el, attr) { - attr = attr || {}; - if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) { - attr = el; // treat first arg as attr object - el = attr.element || null; - } - - if (!el && !attr.element) { // create if we dont have one - el = _createTabViewElement.call(this, attr); - } - YAHOO.widget.TabView.superclass.constructor.call(this, el, attr); - }; - - YAHOO.extend(YAHOO.widget.TabView, YAHOO.util.Element); - - var proto = YAHOO.widget.TabView.prototype; - var Dom = YAHOO.util.Dom; - var Lang = YAHOO.util.Lang; - var Event = YAHOO.util.Event; - var Tab = YAHOO.widget.Tab; - - - /** - * The className to add when building from scratch. - * @property CLASSNAME - * @default "navset" - */ - proto.CLASSNAME = 'yui-navset'; - - /** - * The className of the HTMLElement containing the TabView's tab elements - * to look for when building from existing markup, or to add when building - * from scratch. - * All childNodes of the tab container are treated as Tabs when building - * from existing markup. - * @property TAB_PARENT_CLASSNAME - * @default "nav" - */ - proto.TAB_PARENT_CLASSNAME = 'yui-nav'; - - /** - * The className of the HTMLElement containing the TabView's label elements - * to look for when building from existing markup, or to add when building - * from scratch. - * All childNodes of the content container are treated as content elements when - * building from existing markup. - * @property CONTENT_PARENT_CLASSNAME - * @default "nav-content" - */ - proto.CONTENT_PARENT_CLASSNAME = 'yui-content'; - - proto._tabParent = null; - proto._contentParent = null; - - /** - * Adds a Tab to the TabView instance. - * If no index is specified, the tab is added to the end of the tab list. - * @method addTab - * @param {YAHOO.widget.Tab} tab A Tab instance to add. - * @param {Integer} index The position to add the tab. - * @return void - */ - proto.addTab = function(tab, index) { - var tabs = this.get('tabs'); - if (!tabs) { // not ready yet - this._queue[this._queue.length] = ['addTab', arguments]; - return false; - } - - index = (index === undefined) ? tabs.length : index; - - var before = this.getTab(index); - - var self = this; - var el = this.get('element'); - var tabParent = this._tabParent; - var contentParent = this._contentParent; - - var tabElement = tab.get('element'); - var contentEl = tab.get('contentEl'); - - if ( before ) { - tabParent.insertBefore(tabElement, before.get('element')); - } else { - tabParent.appendChild(tabElement); - } - - if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) { - contentParent.appendChild(contentEl); - } - - if ( !tab.get('active') ) { - tab.set('contentVisible', false, true); /* hide if not active */ - } else { - this.set('activeTab', tab, true); - - } - - var activate = function(e) { - YAHOO.util.Event.preventDefault(e); - self.set('activeTab', this); - }; - - tab.addListener( tab.get('activationEvent'), activate); - - tab.addListener('activationEventChange', function(e) { - if (e.prevValue != e.newValue) { - tab.removeListener(e.prevValue, activate); - tab.addListener(e.newValue, activate); - } - }); - - tabs.splice(index, 0, tab); - }; - - /** - * Routes childNode events. - * @method DOMEventHandler - * @param {event} e The Dom event that is being handled. - * @return void - */ - proto.DOMEventHandler = function(e) { - var el = this.get('element'); - var target = YAHOO.util.Event.getTarget(e); - var tabParent = this._tabParent; - - if (Dom.isAncestor(tabParent, target) ) { - var tabEl; - var tab = null; - var contentEl; - var tabs = this.get('tabs'); - - for (var i = 0, len = tabs.length; i < len; i++) { - tabEl = tabs[i].get('element'); - contentEl = tabs[i].get('contentEl'); - - if ( target == tabEl || Dom.isAncestor(tabEl, target) ) { - tab = tabs[i]; - break; // note break - } - } - - if (tab) { - tab.fireEvent(e.type, e); - } - } - }; - - /** - * Returns the Tab instance at the specified index. - * @method getTab - * @param {Integer} index The position of the Tab. - * @return YAHOO.widget.Tab - */ - proto.getTab = function(index) { - return this.get('tabs')[index]; - }; - - /** - * Returns the index of given tab. - * @method getTabIndex - * @param {YAHOO.widget.Tab} tab The tab whose index will be returned. - * @return int - */ - proto.getTabIndex = function(tab) { - var index = null; - var tabs = this.get('tabs'); - for (var i = 0, len = tabs.length; i < len; ++i) { - if (tab == tabs[i]) { - index = i; - break; - } - } - - return index; - }; - - /** - * Removes the specified Tab from the TabView. - * @method removeTab - * @param {YAHOO.widget.Tab} item The Tab instance to be removed. - * @return void - */ - proto.removeTab = function(tab) { - var tabCount = this.get('tabs').length; - - var index = this.getTabIndex(tab); - var nextIndex = index + 1; - if ( tab == this.get('activeTab') ) { // select next tab - if (tabCount > 1) { - if (index + 1 == tabCount) { - this.set('activeIndex', index - 1); - } else { - this.set('activeIndex', index + 1); - } - } - } - - this._tabParent.removeChild( tab.get('element') ); - this._contentParent.removeChild( tab.get('contentEl') ); - this._configs.tabs.value.splice(index, 1); - - }; - - /** - * Provides a readable name for the TabView instance. - * @method toString - * @return String - */ - proto.toString = function() { - var name = this.get('id') || this.get('tagName'); - return "TabView " + name; - }; - - /** - * The transiton to use when switching between tabs. - * @method contentTransition - */ - proto.contentTransition = function(newTab, oldTab) { - newTab.set('contentVisible', true); - oldTab.set('contentVisible', false); - }; - - /** - * Registers TabView specific properties. - * @method initAttributes - * @param {Object} attr Hash of initial attributes - */ - proto.initAttributes = function(attr) { - YAHOO.widget.TabView.superclass.initAttributes.call(this, attr); - - if (!attr.orientation) { - attr.orientation = 'top'; - } - - var el = this.get('element'); - - /** - * The Tabs belonging to the TabView instance. - * @config tabs - * @type Array - */ - this.register('tabs', { - value: [], - readOnly: true - }); - - /** - * The container of the tabView's label elements. - * @property _tabParent - * @private - * @type HTMLElement - */ - this._tabParent = - this.getElementsByClassName(this.TAB_PARENT_CLASSNAME, - 'ul' )[0] || _createTabParent.call(this); - - /** - * The container of the tabView's content elements. - * @property _contentParent - * @type HTMLElement - * @private - */ - this._contentParent = - this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME, - 'div')[0] || _createContentParent.call(this); - - /** - * How the Tabs should be oriented relative to the TabView. - * @config orientation - * @type String - * @default "top" - */ - this.register('orientation', { - value: attr.orientation, - method: function(value) { - var current = this.get('orientation'); - this.addClass('yui-navset-' + value); - - if (current != value) { - this.removeClass('yui-navset-' + current); - } - - switch(value) { - case 'bottom': - this.appendChild(this._tabParent); - break; - } - } - }); - - /** - * The index of the tab currently active. - * @config activeIndex - * @type Int - */ - this.register('activeIndex', { - value: attr.activeIndex, - method: function(value) { - this.set('activeTab', this.getTab(value)); - }, - validator: function(value) { - return !this.getTab(value).get('disabled'); // cannot activate if disabled - } - }); - - /** - * The tab currently active. - * @config activeTab - * @type YAHOO.widget.Tab - */ - this.register('activeTab', { - value: attr.activeTab, - method: function(tab) { - var activeTab = this.get('activeTab'); - - if (tab) { - tab.set('active', true); - } - - if (activeTab && activeTab != tab) { - activeTab.set('active', false); - } - - if (activeTab && tab != activeTab) { // no transition if only 1 - this.contentTransition(tab, activeTab); - } else if (tab) { - tab.set('contentVisible', true); - } - }, - validator: function(value) { - return !value.get('disabled'); // cannot activate if disabled - } - }); - - if ( this._tabParent ) { - _initTabs.call(this); - } - - for (var type in this.DOM_EVENTS) { - if ( this.DOM_EVENTS.hasOwnProperty(type) ) { - this.addListener.call(this, type, this.DOMEventHandler); - } - } - }; - - /** - * Creates Tab instances from a collection of HTMLElements. - * @method createTabs - * @private - * @param {Array|HTMLCollection} elements The elements to use for Tabs. - * @return void - */ - var _initTabs = function() { - var tab, - attr, - contentEl; - - var el = this.get('element'); - var tabs = _getChildNodes(this._tabParent); - var contentElements = _getChildNodes(this._contentParent); - - for (var i = 0, len = tabs.length; i < len; ++i) { - attr = {}; - - if (contentElements[i]) { - attr.contentEl = contentElements[i]; - } - - tab = new YAHOO.widget.Tab(tabs[i], attr); - this.addTab(tab); - - if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) { - this._configs.activeTab.value = tab; // dont invoke method - } - } - }; - - var _createTabViewElement = function(attr) { - var el = document.createElement('div'); - - if ( this.CLASSNAME ) { - el.className = this.CLASSNAME; - } - - return el; - }; - - var _createTabParent = function(attr) { - var el = document.createElement('ul'); - - if ( this.TAB_PARENT_CLASSNAME ) { - el.className = this.TAB_PARENT_CLASSNAME; - } - - this.get('element').appendChild(el); - - return el; - }; - - var _createContentParent = function(attr) { - var el = document.createElement('div'); - - if ( this.CONTENT_PARENT_CLASSNAME ) { - el.className = this.CONTENT_PARENT_CLASSNAME; - } - - this.get('element').appendChild(el); - - return el; - }; - - var _getChildNodes = function(el) { - var nodes = []; - var childNodes = el.childNodes; - - for (var i = 0, len = childNodes.length; i < len; ++i) { - if (childNodes[i].nodeType == 1) { - nodes[nodes.length] = childNodes[i]; - } - } - - return nodes; - }; - -/** - * Fires before the activeTab is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeActiveTabChange<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * prevValue</code> the currently active tab<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * newValue</code> the tab to be made active</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeActiveTabChange', handler);</code></p> - * @event beforeActiveTabChange - */ - -/** - * Fires after the activeTab is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> activeTabChange<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * prevValue</code> the formerly active tab<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * newValue</code> the new active tab</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('activeTabChange', handler);</code></p> - * @event activeTabChange - */ - -/** - * Fires before the orientation is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeOrientationChange<br> - * <code><String> - * prevValue</code> the current orientation<br> - * <code><String> - * newValue</code> the new orientation to be applied</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeOrientationChange', handler);</code></p> - * @event beforeOrientationChange - */ - -/** - * Fires after the orientation is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> orientationChange<br> - * <code><String> - * prevValue</code> the former orientation<br> - * <code><String> - * newValue</code> the new orientation</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('orientationChange', handler);</code></p> - * @event orientationChange - */ -})(); - diff --git a/reports/site_media/yui/tabview/tabview-min.js b/reports/site_media/yui/tabview/tabview-min.js deleted file mode 100644 index 24e39dac3..000000000 --- a/reports/site_media/yui/tabview/tabview-min.js +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ - -YAHOO.util.Lang={isArray:function(val){if(val.constructor&&val.constructor.toString().indexOf('Array')>-1){return true;}else{return YAHOO.util.Lang.isObject(val)&&val.constructor==Array;}},isBoolean:function(val){return typeof val=='boolean';},isFunction:function(val){return typeof val=='function';},isNull:function(val){return val===null;},isNumber:function(val){return!isNaN(val);},isObject:function(val){return typeof val=='object'||YAHOO.util.Lang.isFunction(val);},isString:function(val){return typeof val=='string';},isUndefined:function(val){return typeof val=='undefined';}};YAHOO.util.Attribute=function(hash,owner){if(owner){this.owner=owner;this.configure(hash,true);}};YAHOO.util.Attribute.prototype={name:undefined,value:null,owner:null,readOnly:false,writeOnce:false,_initialConfig:null,_written:false,method:null,validator:null,getValue:function(){return this.value;},setValue:function(value,silent){var beforeRetVal;var owner=this.owner;var name=this.name;var event={type:name,prevValue:this.getValue(),newValue:value};if(this.readOnly||(this.writeOnce&&this._written)){return false;} -if(this.validator&&!this.validator.call(owner,value)){return false;} -if(!silent){beforeRetVal=owner.fireBeforeChangeEvent(event);if(beforeRetVal===false){return false;}} -if(this.method){this.method.call(owner,value);} -this.value=value;this._written=true;event.type=name;if(!silent){this.owner.fireChangeEvent(event);} -return true;},configure:function(map,init){map=map||{};this._written=false;this._initialConfig=this._initialConfig||{};for(var key in map){if(key&&map.hasOwnProperty(key)){this[key]=map[key];if(init){this._initialConfig[key]=map[key];}}}},resetValue:function(){return this.setValue(this._initialConfig.value);},resetConfig:function(){this.configure(this._initialConfig);},refresh:function(silent){this.setValue(this.value,silent);}};(function(){var Lang=YAHOO.util.Lang;YAHOO.util.AttributeProvider=function(){};YAHOO.util.AttributeProvider.prototype={_configs:null,get:function(key){var configs=this._configs||{};var config=configs[key];if(!config){return undefined;} -return config.value;},set:function(key,value,silent){var configs=this._configs||{};var config=configs[key];if(!config){return false;} -return config.setValue(value,silent);},getAttributeKeys:function(){var configs=this._configs;var keys=[];var config;for(var key in configs){config=configs[key];if(configs.hasOwnProperty(key)&&!Lang.isUndefined(config)){keys[keys.length]=key;}} -return keys;},setAttributes:function(map,silent){for(var key in map){if(map.hasOwnProperty(key)){this.set(key,map[key],silent);}}},resetValue:function(key,silent){var configs=this._configs||{};if(configs[key]){this.set(key,configs[key]._initialConfig.value,silent);return true;} -return false;},refresh:function(key,silent){var configs=this._configs;key=((Lang.isString(key))?[key]:key)||this.getAttributeKeys();for(var i=0,len=key.length;i<len;++i){if(configs[key[i]]&&!Lang.isUndefined(configs[key[i]].value)&&!Lang.isNull(configs[key[i]].value)){configs[key[i]].refresh(silent);}}},register:function(key,map){this._configs=this._configs||{};if(this._configs[key]){return false;} -map.name=key;this._configs[key]=new YAHOO.util.Attribute(map,this);return true;},getAttributeConfig:function(key){var configs=this._configs||{};var config=configs[key]||{};var map={};for(key in config){if(config.hasOwnProperty(key)){map[key]=config[key];}} -return map;},configureAttribute:function(key,map,init){var configs=this._configs||{};if(!configs[key]){return false;} -configs[key].configure(map,init);},resetAttributeConfig:function(key){var configs=this._configs||{};configs[key].resetConfig();},fireBeforeChangeEvent:function(e){var type='before';type+=e.type.charAt(0).toUpperCase()+e.type.substr(1)+'Change';e.type=type;return this.fireEvent(e.type,e);},fireChangeEvent:function(e){e.type+='Change';return this.fireEvent(e.type,e);}};YAHOO.augment(YAHOO.util.AttributeProvider,YAHOO.util.EventProvider);})();(function(){var Dom=YAHOO.util.Dom,Lang=YAHOO.util.Lang,EventPublisher=YAHOO.util.EventPublisher,AttributeProvider=YAHOO.util.AttributeProvider;YAHOO.util.Element=function(el,map){if(arguments.length){this.init(el,map);}};YAHOO.util.Element.prototype={DOM_EVENTS:null,appendChild:function(child){child=child.get?child.get('element'):child;this.get('element').appendChild(child);},getElementsByTagName:function(tag){return this.get('element').getElementsByTagName(tag);},hasChildNodes:function(){return this.get('element').hasChildNodes();},insertBefore:function(element,before){element=element.get?element.get('element'):element;before=(before&&before.get)?before.get('element'):before;this.get('element').insertBefore(element,before);},removeChild:function(child){child=child.get?child.get('element'):child;this.get('element').removeChild(child);return true;},replaceChild:function(newNode,oldNode){newNode=newNode.get?newNode.get('element'):newNode;oldNode=oldNode.get?oldNode.get('element'):oldNode;return this.get('element').replaceChild(newNode,oldNode);},initAttributes:function(map){map=map||{};var element=Dom.get(map.element)||null;this.register('element',{value:element,readOnly:true});},addListener:function(type,fn,obj,scope){var el=this.get('element');var scope=scope||this;el=this.get('id')||el;if(!this._events[type]){if(this.DOM_EVENTS[type]){YAHOO.util.Event.addListener(el,type,function(e){if(e.srcElement&&!e.target){e.target=e.srcElement;} -this.fireEvent(type,e);},obj,scope);} -this.createEvent(type,this);this._events[type]=true;} -this.subscribe.apply(this,arguments);},on:function(){this.addListener.apply(this,arguments);},removeListener:function(type,fn){this.unsubscribe.apply(this,arguments);},addClass:function(className){Dom.addClass(this.get('element'),className);},getElementsByClassName:function(className,tag){return Dom.getElementsByClassName(className,tag,this.get('element'));},hasClass:function(className){return Dom.hasClass(this.get('element'),className);},removeClass:function(className){return Dom.removeClass(this.get('element'),className);},replaceClass:function(oldClassName,newClassName){return Dom.replaceClass(this.get('element'),oldClassName,newClassName);},setStyle:function(property,value){return Dom.setStyle(this.get('element'),property,value);},getStyle:function(property){return Dom.getStyle(this.get('element'),property);},fireQueue:function(){var queue=this._queue;for(var i=0,len=queue.length;i<len;++i){this[queue[i][0]].apply(this,queue[i][1]);}},appendTo:function(parent,before){parent=(parent.get)?parent.get('element'):Dom.get(parent);before=(before&&before.get)?before.get('element'):Dom.get(before);var element=this.get('element');var newAddition=!Dom.inDocument(element);if(!element){return false;} -if(!parent){return false;} -if(element.parent!=parent){if(before){parent.insertBefore(element,before);}else{parent.appendChild(element);}} -if(!newAddition){return false;} -var keys=this.getAttributeKeys();for(var key in keys){if(!Lang.isUndefined(element[key])){this.refresh(key);}}},get:function(key){var configs=this._configs||{};var el=configs.element;if(el&&!configs[key]&&!Lang.isUndefined(el.value[key])){return el.value[key];} -return AttributeProvider.prototype.get.call(this,key);},set:function(key,value,silent){var el=this.get('element');if(!el){this._queue[this._queue.length]=['set',arguments];return false;} -if(!this._configs[key]&&!Lang.isUndefined(el[key])){_registerHTMLAttr.call(this,key);} -return AttributeProvider.prototype.set.apply(this,arguments);},register:function(key){var configs=this._configs||{};var element=this.get('element')||null;if(element&&!Lang.isUndefined(element[key])){return false;} -return AttributeProvider.prototype.register.apply(this,arguments);},configureAttribute:function(property,map,init){var el=this.get('element');if(!el){this._queue[this._queue.length]=['configureAttribute',arguments];return;} -if(!this._configs[property]&&!Lang.isUndefined(el[property])){_registerHTMLAttr.call(this,property,map);} -return AttributeProvider.prototype.configureAttribute.apply(this,arguments);},getAttributeKeys:function(){var el=this.get('element');var keys=AttributeProvider.prototype.getAttributeKeys.call(this);for(var key in el){if(!this._configs[key]){keys[key]=keys[key]||el[key];}} -return keys;},init:function(el,attr){this._queue=this._queue||[];this._events=this._events||{};this._configs=this._configs||{};attr=attr||{};attr.element=attr.element||el||null;this.DOM_EVENTS={'click':true,'keydown':true,'keypress':true,'keyup':true,'mousedown':true,'mousemove':true,'mouseout':true,'mouseover':true,'mouseup':true};var readyHandler=function(){this.initAttributes(attr);this.setAttributes(attr,true);this.fireQueue();this.fireEvent('contentReady',{type:'contentReady',target:attr.element});};if(Lang.isString(el)){_registerHTMLAttr.call(this,'id',{value:el});YAHOO.util.Event.onAvailable(el,function(){attr.element=Dom.get(el);this.fireEvent('available',{type:'available',target:attr.element});},this,true);YAHOO.util.Event.onContentReady(el,function(){readyHandler.call(this);},this,true);}else{readyHandler.call(this);}}};var _registerHTMLAttr=function(key,map){var el=this.get('element');map=map||{};map.name=key;map.method=map.method||function(value){el[key]=value;};map.value=map.value||el[key];this._configs[key]=new YAHOO.util.Attribute(map,this);};YAHOO.augment(YAHOO.util.Element,AttributeProvider);})();(function(){var Dom=YAHOO.util.Dom,Event=YAHOO.util.Event,Lang=YAHOO.util.Lang;var Tab=function(el,attr){attr=attr||{};if(arguments.length==1&&!Lang.isString(el)&&!el.nodeName){attr=el;el=attr.element;} -if(!el&&!attr.element){el=_createTabElement.call(this,attr);} -this.loadHandler={success:function(o){this.set('content',o.responseText);},failure:function(o){}};Tab.superclass.constructor.call(this,el,attr);this.DOM_EVENTS={};};YAHOO.extend(Tab,YAHOO.util.Element);var proto=Tab.prototype;proto.LABEL_TAGNAME='em';proto.ACTIVE_CLASSNAME='selected';proto.DISABLED_CLASSNAME='disabled';proto.LOADING_CLASSNAME='loading';proto.dataConnection=null;proto.loadHandler=null;proto.toString=function(){var el=this.get('element');var id=el.id||el.tagName;return"Tab "+id;};proto.initAttributes=function(attr){attr=attr||{};Tab.superclass.initAttributes.call(this,attr);var el=this.get('element');this.register('activationEvent',{value:attr.activationEvent||'click'});this.register('labelEl',{value:attr.labelEl||_getlabelEl.call(this),method:function(value){var current=this.get('labelEl');if(current){if(current==value){return false;} -this.replaceChild(value,current);}else if(el.firstChild){this.insertBefore(value,el.firstChild);}else{this.appendChild(value);}}});this.register('label',{value:attr.label||_getLabel.call(this),method:function(value){var labelEl=this.get('labelEl');if(!labelEl){this.set('labelEl',_createlabelEl.call(this));} -_setLabel.call(this,value);}});this.register('contentEl',{value:attr.contentEl||document.createElement('div'),method:function(value){var current=this.get('contentEl');if(current){if(current==value){return false;} -this.replaceChild(value,current);}}});this.register('content',{value:attr.content,method:function(value){this.get('contentEl').innerHTML=value;}});var _dataLoaded=false;this.register('dataSrc',{value:attr.dataSrc});this.register('cacheData',{value:attr.cacheData||false,validator:Lang.isBoolean});this.register('loadMethod',{value:attr.loadMethod||'GET',validator:Lang.isString});this.register('dataLoaded',{value:false,validator:Lang.isBoolean,writeOnce:true});this.register('dataTimeout',{value:attr.dataTimeout||null,validator:Lang.isNumber});this.register('active',{value:attr.active||this.hasClass(this.ACTIVE_CLASSNAME),method:function(value){if(value===true){this.addClass(this.ACTIVE_CLASSNAME);this.set('title','active');}else{this.removeClass(this.ACTIVE_CLASSNAME);this.set('title','');}},validator:function(value){return Lang.isBoolean(value)&&!this.get('disabled');}});this.register('disabled',{value:attr.disabled||this.hasClass(this.DISABLED_CLASSNAME),method:function(value){if(value===true){Dom.addClass(this.get('element'),this.DISABLED_CLASSNAME);}else{Dom.removeClass(this.get('element'),this.DISABLED_CLASSNAME);}},validator:Lang.isBoolean});this.register('href',{value:attr.href||'#',method:function(value){this.getElementsByTagName('a')[0].href=value;},validator:Lang.isString});this.register('contentVisible',{value:attr.contentVisible,method:function(value){if(value==true){this.get('contentEl').style.display='block';if(this.get('dataSrc')){if(!this.get('dataLoaded')||!this.get('cacheData')){_dataConnect.call(this);}}}else{this.get('contentEl').style.display='none';}},validator:Lang.isBoolean});};var _createTabElement=function(attr){var el=document.createElement('li');var a=document.createElement('a');a.href=attr.href||'#';el.appendChild(a);var label=attr.label||null;var labelEl=attr.labelEl||null;if(labelEl){if(!label){label=_getLabel.call(this,labelEl);}}else{labelEl=_createlabelEl.call(this);} -a.appendChild(labelEl);return el;};var _getlabelEl=function(){return this.getElementsByTagName(this.LABEL_TAGNAME)[0];};var _createlabelEl=function(){var el=document.createElement(this.LABEL_TAGNAME);return el;};var _setLabel=function(label){var el=this.get('labelEl');el.innerHTML=label;};var _getLabel=function(){var label,el=this.get('labelEl');if(!el){return undefined;} -return el.innerHTML;};var _dataConnect=function(){if(!YAHOO.util.Connect){return false;} -Dom.addClass(this.get('contentEl').parentNode,this.LOADING_CLASSNAME);this.dataConnection=YAHOO.util.Connect.asyncRequest(this.get('loadMethod'),this.get('dataSrc'),{success:function(o){this.loadHandler.success.call(this,o);this.set('dataLoaded',true);this.dataConnection=null;Dom.removeClass(this.get('contentEl').parentNode,this.LOADING_CLASSNAME);},failure:function(o){this.loadHandler.failure.call(this,o);this.dataConnection=null;Dom.removeClass(this.get('contentEl').parentNode,this.LOADING_CLASSNAME);},scope:this,timeout:this.get('dataTimeout')});};YAHOO.widget.Tab=Tab;})();(function(){YAHOO.widget.TabView=function(el,attr){attr=attr||{};if(arguments.length==1&&!Lang.isString(el)&&!el.nodeName){attr=el;el=attr.element||null;} -if(!el&&!attr.element){el=_createTabViewElement.call(this,attr);} -YAHOO.widget.TabView.superclass.constructor.call(this,el,attr);};YAHOO.extend(YAHOO.widget.TabView,YAHOO.util.Element);var proto=YAHOO.widget.TabView.prototype;var Dom=YAHOO.util.Dom;var Lang=YAHOO.util.Lang;var Event=YAHOO.util.Event;var Tab=YAHOO.widget.Tab;proto.CLASSNAME='yui-navset';proto.TAB_PARENT_CLASSNAME='yui-nav';proto.CONTENT_PARENT_CLASSNAME='yui-content';proto._tabParent=null;proto._contentParent=null;proto.addTab=function(tab,index){var tabs=this.get('tabs');if(!tabs){this._queue[this._queue.length]=['addTab',arguments];return false;} -index=(index===undefined)?tabs.length:index;var before=this.getTab(index);var self=this;var el=this.get('element');var tabParent=this._tabParent;var contentParent=this._contentParent;var tabElement=tab.get('element');var contentEl=tab.get('contentEl');if(before){tabParent.insertBefore(tabElement,before.get('element'));}else{tabParent.appendChild(tabElement);} -if(contentEl&&!Dom.isAncestor(contentParent,contentEl)){contentParent.appendChild(contentEl);} -if(!tab.get('active')){tab.set('contentVisible',false,true);}else{this.set('activeTab',tab,true);} -var activate=function(e){YAHOO.util.Event.preventDefault(e);self.set('activeTab',this);};tab.addListener(tab.get('activationEvent'),activate);tab.addListener('activationEventChange',function(e){if(e.prevValue!=e.newValue){tab.removeListener(e.prevValue,activate);tab.addListener(e.newValue,activate);}});tabs.splice(index,0,tab);};proto.DOMEventHandler=function(e){var el=this.get('element');var target=YAHOO.util.Event.getTarget(e);var tabParent=this._tabParent;if(Dom.isAncestor(tabParent,target)){var tabEl;var tab=null;var contentEl;var tabs=this.get('tabs');for(var i=0,len=tabs.length;i<len;i++){tabEl=tabs[i].get('element');contentEl=tabs[i].get('contentEl');if(target==tabEl||Dom.isAncestor(tabEl,target)){tab=tabs[i];break;}} -if(tab){tab.fireEvent(e.type,e);}}};proto.getTab=function(index){return this.get('tabs')[index];};proto.getTabIndex=function(tab){var index=null;var tabs=this.get('tabs');for(var i=0,len=tabs.length;i<len;++i){if(tab==tabs[i]){index=i;break;}} -return index;};proto.removeTab=function(tab){var tabCount=this.get('tabs').length;var index=this.getTabIndex(tab);var nextIndex=index+1;if(tab==this.get('activeTab')){if(tabCount>1){if(index+1==tabCount){this.set('activeIndex',index-1);}else{this.set('activeIndex',index+1);}}} -this._tabParent.removeChild(tab.get('element'));this._contentParent.removeChild(tab.get('contentEl'));this._configs.tabs.value.splice(index,1);};proto.toString=function(){var name=this.get('id')||this.get('tagName');return"TabView "+name;};proto.contentTransition=function(newTab,oldTab){newTab.set('contentVisible',true);oldTab.set('contentVisible',false);};proto.initAttributes=function(attr){YAHOO.widget.TabView.superclass.initAttributes.call(this,attr);if(!attr.orientation){attr.orientation='top';} -var el=this.get('element');this.register('tabs',{value:[],readOnly:true});this._tabParent=this.getElementsByClassName(this.TAB_PARENT_CLASSNAME,'ul')[0]||_createTabParent.call(this);this._contentParent=this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME,'div')[0]||_createContentParent.call(this);this.register('orientation',{value:attr.orientation,method:function(value){var current=this.get('orientation');this.addClass('yui-navset-'+value);if(current!=value){this.removeClass('yui-navset-'+current);} -switch(value){case'bottom':this.appendChild(this._tabParent);break;}}});this.register('activeIndex',{value:attr.activeIndex,method:function(value){this.set('activeTab',this.getTab(value));},validator:function(value){return!this.getTab(value).get('disabled');}});this.register('activeTab',{value:attr.activeTab,method:function(tab){var activeTab=this.get('activeTab');if(tab){tab.set('active',true);} -if(activeTab&&activeTab!=tab){activeTab.set('active',false);} -if(activeTab&&tab!=activeTab){this.contentTransition(tab,activeTab);}else if(tab){tab.set('contentVisible',true);}},validator:function(value){return!value.get('disabled');}});if(this._tabParent){_initTabs.call(this);} -for(var type in this.DOM_EVENTS){if(this.DOM_EVENTS.hasOwnProperty(type)){this.addListener.call(this,type,this.DOMEventHandler);}}};var _initTabs=function(){var tab,attr,contentEl;var el=this.get('element');var tabs=_getChildNodes(this._tabParent);var contentElements=_getChildNodes(this._contentParent);for(var i=0,len=tabs.length;i<len;++i){attr={};if(contentElements[i]){attr.contentEl=contentElements[i];} -tab=new YAHOO.widget.Tab(tabs[i],attr);this.addTab(tab);if(tab.hasClass(tab.ACTIVE_CLASSNAME)){this._configs.activeTab.value=tab;}}};var _createTabViewElement=function(attr){var el=document.createElement('div');if(this.CLASSNAME){el.className=this.CLASSNAME;} -return el;};var _createTabParent=function(attr){var el=document.createElement('ul');if(this.TAB_PARENT_CLASSNAME){el.className=this.TAB_PARENT_CLASSNAME;} -this.get('element').appendChild(el);return el;};var _createContentParent=function(attr){var el=document.createElement('div');if(this.CONTENT_PARENT_CLASSNAME){el.className=this.CONTENT_PARENT_CLASSNAME;} -this.get('element').appendChild(el);return el;};var _getChildNodes=function(el){var nodes=[];var childNodes=el.childNodes;for(var i=0,len=childNodes.length;i<len;++i){if(childNodes[i].nodeType==1){nodes[nodes.length]=childNodes[i];}} -return nodes;};})();
\ No newline at end of file diff --git a/reports/site_media/yui/tabview/tabview.js b/reports/site_media/yui/tabview/tabview.js deleted file mode 100644 index 8f5d4bb02..000000000 --- a/reports/site_media/yui/tabview/tabview.js +++ /dev/null @@ -1,1945 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ -YAHOO.util.Lang = { - isArray: function(val) { // frames lose type, so test constructor string - if (val.constructor && val.constructor.toString().indexOf('Array') > -1) { - return true; - } else { - return YAHOO.util.Lang.isObject(val) && val.constructor == Array; - } - }, - - isBoolean: function(val) { - return typeof val == 'boolean'; - }, - - isFunction: function(val) { - return typeof val == 'function'; - }, - - isNull: function(val) { - return val === null; - }, - - isNumber: function(val) { - return !isNaN(val); - }, - - isObject: function(val) { - return typeof val == 'object' || YAHOO.util.Lang.isFunction(val); - }, - - isString: function(val) { - return typeof val == 'string'; - }, - - isUndefined: function(val) { - return typeof val == 'undefined'; - } -}; - -/** - * Provides Attribute configurations. - * @namespace YAHOO.util - * @class Attribute - * @constructor - * @param hash {Object} The intial Attribute. - * @param {YAHOO.util.AttributeProvider} The owner of the Attribute instance. - */ - -YAHOO.util.Attribute = function(hash, owner) { - if (owner) { - this.owner = owner; - this.configure(hash, true); - } -}; - -YAHOO.util.Attribute.prototype = { - /** - * The name of the attribute. - * @property name - * @type String - */ - name: undefined, - - /** - * The value of the attribute. - * @property value - * @type String - */ - value: null, - - /** - * The owner of the attribute. - * @property owner - * @type YAHOO.util.AttributeProvider - */ - owner: null, - - /** - * Whether or not the attribute is read only. - * @property readOnly - * @type Boolean - */ - readOnly: false, - - /** - * Whether or not the attribute can only be written once. - * @property writeOnce - * @type Boolean - */ - writeOnce: false, - - /** - * The attribute's initial configuration. - * @private - * @property _initialConfig - * @type Object - */ - _initialConfig: null, - - /** - * Whether or not the attribute's value has been set. - * @private - * @property _written - * @type Boolean - */ - _written: false, - - /** - * The method to use when setting the attribute's value. - * The method recieves the new value as the only argument. - * @property method - * @type Function - */ - method: null, - - /** - * The validator to use when setting the attribute's value. - * @property validator - * @type Function - * @return Boolean - */ - validator: null, - - /** - * Retrieves the current value of the attribute. - * @method getValue - * @return {any} The current value of the attribute. - */ - getValue: function() { - return this.value; - }, - - /** - * Sets the value of the attribute and fires beforeChange and change events. - * @method setValue - * @param {Any} value The value to apply to the attribute. - * @param {Boolean} silent If true the change events will not be fired. - * @return {Boolean} Whether or not the value was set. - */ - setValue: function(value, silent) { - var beforeRetVal; - var owner = this.owner; - var name = this.name; - - var event = { - type: name, - prevValue: this.getValue(), - newValue: value - }; - - if (this.readOnly || ( this.writeOnce && this._written) ) { - return false; // write not allowed - } - - if (this.validator && !this.validator.call(owner, value) ) { - return false; // invalid value - } - - if (!silent) { - beforeRetVal = owner.fireBeforeChangeEvent(event); - if (beforeRetVal === false) { - return false; - } - } - - if (this.method) { - this.method.call(owner, value); - } - - this.value = value; - this._written = true; - - event.type = name; - - if (!silent) { - this.owner.fireChangeEvent(event); - } - - return true; - }, - - /** - * Allows for configuring the Attribute's properties. - * @method configure - * @param {Object} map A key-value map of Attribute properties. - * @param {Boolean} init Whether or not this should become the initial config. - */ - configure: function(map, init) { - map = map || {}; - this._written = false; // reset writeOnce - this._initialConfig = this._initialConfig || {}; - - for (var key in map) { - if ( key && map.hasOwnProperty(key) ) { - this[key] = map[key]; - if (init) { - this._initialConfig[key] = map[key]; - } - } - } - }, - - /** - * Resets the value to the initial config value. - * @method resetValue - * @return {Boolean} Whether or not the value was set. - */ - resetValue: function() { - return this.setValue(this._initialConfig.value); - }, - - /** - * Resets the attribute config to the initial config state. - * @method resetConfig - */ - resetConfig: function() { - this.configure(this._initialConfig); - }, - - /** - * Resets the value to the current value. - * Useful when values may have gotten out of sync with actual properties. - * @method refresh - * @return {Boolean} Whether or not the value was set. - */ - refresh: function(silent) { - this.setValue(this.value, silent); - } -}; - -(function() { - var Lang = YAHOO.util.Lang; - - /* - Copyright (c) 2006, Yahoo! Inc. All rights reserved. - Code licensed under the BSD License: - http://developer.yahoo.net/yui/license.txt - */ - - /** - * Provides and manages YAHOO.util.Attribute instances - * @namespace YAHOO.util - * @class AttributeProvider - * @uses YAHOO.util.EventProvider - */ - YAHOO.util.AttributeProvider = function() {}; - - YAHOO.util.AttributeProvider.prototype = { - - /** - * A key-value map of Attribute configurations - * @property _configs - * @protected (may be used by subclasses and augmentors) - * @private - * @type {Object} - */ - _configs: null, - /** - * Returns the current value of the attribute. - * @method get - * @param {String} key The attribute whose value will be returned. - */ - get: function(key){ - var configs = this._configs || {}; - var config = configs[key]; - - if (!config) { - return undefined; - } - - return config.value; - }, - - /** - * Sets the value of a config. - * @method set - * @param {String} key The name of the attribute - * @param {Any} value The value to apply to the attribute - * @param {Boolean} silent Whether or not to suppress change events - * @return {Boolean} Whether or not the value was set. - */ - set: function(key, value, silent){ - var configs = this._configs || {}; - var config = configs[key]; - - if (!config) { - return false; - } - - return config.setValue(value, silent); - }, - - /** - * Returns an array of attribute names. - * @method getAttributeKeys - * @return {Array} An array of attribute names. - */ - getAttributeKeys: function(){ - var configs = this._configs; - var keys = []; - var config; - for (var key in configs) { - config = configs[key]; - if ( configs.hasOwnProperty(key) && - !Lang.isUndefined(config) ) { - keys[keys.length] = key; - } - } - - return keys; - }, - - /** - * Sets multiple attribute values. - * @method setAttributes - * @param {Object} map A key-value map of attributes - * @param {Boolean} silent Whether or not to suppress change events - */ - setAttributes: function(map, silent){ - for (var key in map) { - if ( map.hasOwnProperty(key) ) { - this.set(key, map[key], silent); - } - } - }, - - /** - * Resets the specified attribute's value to its initial value. - * @method resetValue - * @param {String} key The name of the attribute - * @param {Boolean} silent Whether or not to suppress change events - * @return {Boolean} Whether or not the value was set - */ - resetValue: function(key, silent){ - var configs = this._configs || {}; - if (configs[key]) { - this.set(key, configs[key]._initialConfig.value, silent); - return true; - } - return false; - }, - - /** - * Sets the attribute's value to its current value. - * @method refresh - * @param {String | Array} key The attribute(s) to refresh - * @param {Boolean} silent Whether or not to suppress change events - */ - refresh: function(key, silent){ - var configs = this._configs; - - key = ( ( Lang.isString(key) ) ? [key] : key ) || - this.getAttributeKeys(); - - for (var i = 0, len = key.length; i < len; ++i) { - if ( // only set if there is a value and not null - configs[key[i]] && - ! Lang.isUndefined(configs[key[i]].value) && - ! Lang.isNull(configs[key[i]].value) ) { - configs[key[i]].refresh(silent); - } - } - }, - - /** - * Adds an Attribute to the AttributeProvider instance. - * @method register - * @param {String} key The attribute's name - * @param {Object} map A key-value map containing the - * attribute's properties. - */ - register: function(key, map) { - this._configs = this._configs || {}; - - if (this._configs[key]) { // dont override - return false; - } - - map.name = key; - this._configs[key] = new YAHOO.util.Attribute(map, this); - return true; - }, - - /** - * Returns the attribute's properties. - * @method getAttributeConfig - * @param {String} key The attribute's name - * @private - * @return {object} A key-value map containing all of the - * attribute's properties. - */ - getAttributeConfig: function(key) { - var configs = this._configs || {}; - var config = configs[key] || {}; - var map = {}; // returning a copy to prevent overrides - - for (key in config) { - if ( config.hasOwnProperty(key) ) { - map[key] = config[key]; - } - } - - return map; - }, - - /** - * Sets or updates an Attribute instance's properties. - * @method configureAttribute - * @param {String} key The attribute's name. - * @param {Object} map A key-value map of attribute properties - * @param {Boolean} init Whether or not this should become the intial config. - */ - configureAttribute: function(key, map, init) { - var configs = this._configs || {}; - - if (!configs[key]) { - return false; - } - - configs[key].configure(map, init); - }, - - /** - * Resets an attribute to its intial configuration. - * @method resetAttributeConfig - * @param {String} key The attribute's name. - * @private - */ - resetAttributeConfig: function(key){ - var configs = this._configs || {}; - configs[key].resetConfig(); - }, - - /** - * Fires the attribute's beforeChange event. - * @method fireBeforeChangeEvent - * @param {String} key The attribute's name. - * @param {Obj} e The event object to pass to handlers. - */ - fireBeforeChangeEvent: function(e) { - var type = 'before'; - type += e.type.charAt(0).toUpperCase() + e.type.substr(1) + 'Change'; - e.type = type; - return this.fireEvent(e.type, e); - }, - - /** - * Fires the attribute's change event. - * @method fireChangeEvent - * @param {String} key The attribute's name. - * @param {Obj} e The event object to pass to the handlers. - */ - fireChangeEvent: function(e) { - e.type += 'Change'; - return this.fireEvent(e.type, e); - } - }; - - YAHOO.augment(YAHOO.util.AttributeProvider, YAHOO.util.EventProvider); -})(); - -(function() { -// internal shorthand -var Dom = YAHOO.util.Dom, - Lang = YAHOO.util.Lang, - EventPublisher = YAHOO.util.EventPublisher, - AttributeProvider = YAHOO.util.AttributeProvider; - -/** - * Element provides an interface to an HTMLElement's attributes and common - * methods. Other commonly used attributes are added as well. - * @namespace YAHOO.util - * @class Element - * @uses YAHOO.util.AttributeProvider - * @constructor - * @param el {HTMLElement | String} The html element that - * represents the Element. - * @param {Object} map A key-value map of initial config names and values - */ -YAHOO.util.Element = function(el, map) { - if (arguments.length) { - this.init(el, map); - } -}; - -YAHOO.util.Element.prototype = { - /** - * Dom events supported by the Element instance. - * @property DOM_EVENTS - * @type Object - */ - DOM_EVENTS: null, - - /** - * Wrapper for HTMLElement method. - * @method appendChild - * @param {Boolean} deep Whether or not to do a deep clone - */ - appendChild: function(child) { - child = child.get ? child.get('element') : child; - this.get('element').appendChild(child); - }, - - /** - * Wrapper for HTMLElement method. - * @method getElementsByTagName - * @param {String} tag The tagName to collect - */ - getElementsByTagName: function(tag) { - return this.get('element').getElementsByTagName(tag); - }, - - /** - * Wrapper for HTMLElement method. - * @method hasChildNodes - * @return {Boolean} Whether or not the element has childNodes - */ - hasChildNodes: function() { - return this.get('element').hasChildNodes(); - }, - - /** - * Wrapper for HTMLElement method. - * @method insertBefore - * @param {HTMLElement} element The HTMLElement to insert - * @param {HTMLElement} before The HTMLElement to insert - * the element before. - */ - insertBefore: function(element, before) { - element = element.get ? element.get('element') : element; - before = (before && before.get) ? before.get('element') : before; - - this.get('element').insertBefore(element, before); - }, - - /** - * Wrapper for HTMLElement method. - * @method removeChild - * @param {HTMLElement} child The HTMLElement to remove - */ - removeChild: function(child) { - child = child.get ? child.get('element') : child; - this.get('element').removeChild(child); - return true; - }, - - /** - * Wrapper for HTMLElement method. - * @method replaceChild - * @param {HTMLElement} newNode The HTMLElement to insert - * @param {HTMLElement} oldNode The HTMLElement to replace - */ - replaceChild: function(newNode, oldNode) { - newNode = newNode.get ? newNode.get('element') : newNode; - oldNode = oldNode.get ? oldNode.get('element') : oldNode; - return this.get('element').replaceChild(newNode, oldNode); - }, - - - /** - * Registers Element specific attributes. - * @method initAttributes - * @param {Object} map A key-value map of initial attribute configs - */ - initAttributes: function(map) { - map = map || {}; - var element = Dom.get(map.element) || null; - - /** - * The HTMLElement the Element instance refers to. - * @config element - * @type HTMLElement - */ - this.register('element', { - value: element, - readOnly: true - }); - }, - - /** - * Adds a listener for the given event. These may be DOM or - * customEvent listeners. Any event that is fired via fireEvent - * can be listened for. All handlers receive an event object. - * @method addListener - * @param {String} type The name of the event to listen for - * @param {Function} fn The handler to call when the event fires - * @param {Any} obj A variable to pass to the handler - * @param {Object} scope The object to use for the scope of the handler - */ - addListener: function(type, fn, obj, scope) { - var el = this.get('element'); - var scope = scope || this; - - el = this.get('id') || el; - - if (!this._events[type]) { // create on the fly - if ( this.DOM_EVENTS[type] ) { - YAHOO.util.Event.addListener(el, type, function(e) { - if (e.srcElement && !e.target) { // supplement IE with target - e.target = e.srcElement; - } - this.fireEvent(type, e); - }, obj, scope); - } - - this.createEvent(type, this); - this._events[type] = true; - } - - this.subscribe.apply(this, arguments); // notify via customEvent - }, - - - /** - * Alias for addListener - * @method on - * @param {String} type The name of the event to listen for - * @param {Function} fn The function call when the event fires - * @param {Any} obj A variable to pass to the handler - * @param {Object} scope The object to use for the scope of the handler - */ - on: function() { this.addListener.apply(this, arguments); }, - - - /** - * Remove an event listener - * @method removeListener - * @param {String} type The name of the event to listen for - * @param {Function} fn The function call when the event fires - */ - removeListener: function(type, fn) { - this.unsubscribe.apply(this, arguments); - }, - - /** - * Wrapper for Dom method. - * @method addClass - * @param {String} className The className to add - */ - addClass: function(className) { - Dom.addClass(this.get('element'), className); - }, - - /** - * Wrapper for Dom method. - * @method getElementsByClassName - * @param {String} className The className to collect - * @param {String} tag (optional) The tag to use in - * conjunction with class name - * @return {Array} Array of HTMLElements - */ - getElementsByClassName: function(className, tag) { - return Dom.getElementsByClassName(className, tag, - this.get('element') ); - }, - - /** - * Wrapper for Dom method. - * @method hasClass - * @param {String} className The className to add - * @return {Boolean} Whether or not the element has the class name - */ - hasClass: function(className) { - return Dom.hasClass(this.get('element'), className); - }, - - /** - * Wrapper for Dom method. - * @method removeClass - * @param {String} className The className to remove - */ - removeClass: function(className) { - return Dom.removeClass(this.get('element'), className); - }, - - /** - * Wrapper for Dom method. - * @method replaceClass - * @param {String} oldClassName The className to replace - * @param {String} newClassName The className to add - */ - replaceClass: function(oldClassName, newClassName) { - return Dom.replaceClass(this.get('element'), - oldClassName, newClassName); - }, - - /** - * Wrapper for Dom method. - * @method setStyle - * @param {String} property The style property to set - * @param {String} value The value to apply to the style property - */ - setStyle: function(property, value) { - return Dom.setStyle(this.get('element'), property, value); - }, - - /** - * Wrapper for Dom method. - * @method getStyle - * @param {String} property The style property to retrieve - * @return {String} The current value of the property - */ - getStyle: function(property) { - return Dom.getStyle(this.get('element'), property); - }, - - /** - * Apply any queued set calls. - * @method fireQueue - */ - fireQueue: function() { - var queue = this._queue; - for (var i = 0, len = queue.length; i < len; ++i) { - this[queue[i][0]].apply(this, queue[i][1]); - } - }, - - /** - * Appends the HTMLElement into either the supplied parentNode. - * @method appendTo - * @param {HTMLElement | Element} parentNode The node to append to - * @param {HTMLElement | Element} before An optional node to insert before - */ - appendTo: function(parent, before) { - parent = (parent.get) ? parent.get('element') : Dom.get(parent); - - before = (before && before.get) ? - before.get('element') : Dom.get(before); - var element = this.get('element'); - - var newAddition = !Dom.inDocument(element); - - if (!element) { - return false; - } - - if (!parent) { - return false; - } - - if (element.parent != parent) { - if (before) { - parent.insertBefore(element, before); - } else { - parent.appendChild(element); - } - } - - - if (!newAddition) { - return false; // note return; no refresh if in document - } - - // if a new addition, refresh HTMLElement any applied attributes - var keys = this.getAttributeKeys(); - - for (var key in keys) { // only refresh HTMLElement attributes - if ( !Lang.isUndefined(element[key]) ) { - this.refresh(key); - } - } - }, - - get: function(key) { - var configs = this._configs || {}; - var el = configs.element; // avoid loop due to 'element' - if (el && !configs[key] && !Lang.isUndefined(el.value[key]) ) { - return el.value[key]; - } - - return AttributeProvider.prototype.get.call(this, key); - }, - - set: function(key, value, silent) { - var el = this.get('element'); - if (!el) { - this._queue[this._queue.length] = ['set', arguments]; - return false; - } - - // set it on the element if not a property - if ( !this._configs[key] && !Lang.isUndefined(el[key]) ) { - _registerHTMLAttr.call(this, key); - } - - return AttributeProvider.prototype.set.apply(this, arguments); - }, - - register: function(key) { // protect html attributes - var configs = this._configs || {}; - var element = this.get('element') || null; - - if ( element && !Lang.isUndefined(element[key]) ) { - return false; - } - - return AttributeProvider.prototype.register.apply(this, arguments); - }, - - configureAttribute: function(property, map, init) { // protect html attributes - var el = this.get('element'); - if (!el) { - this._queue[this._queue.length] = ['configureAttribute', arguments]; - return; - } - - if (!this._configs[property] && !Lang.isUndefined(el[property]) ) { - _registerHTMLAttr.call(this, property, map); - } - - return AttributeProvider.prototype.configureAttribute.apply(this, arguments); - }, - - getAttributeKeys: function() { - var el = this.get('element'); - var keys = AttributeProvider.prototype.getAttributeKeys.call(this); - - //add any unconfigured element keys - for (var key in el) { - if (!this._configs[key]) { - keys[key] = keys[key] || el[key]; - } - } - - return keys; - }, - - init: function(el, attr) { - this._queue = this._queue || []; - this._events = this._events || {}; - this._configs = this._configs || {}; - attr = attr || {}; - attr.element = attr.element || el || null; - - this.DOM_EVENTS = { - 'click': true, - 'keydown': true, - 'keypress': true, - 'keyup': true, - 'mousedown': true, - 'mousemove': true, - 'mouseout': true, - 'mouseover': true, - 'mouseup': true - }; - - var readyHandler = function() { - this.initAttributes(attr); - - this.setAttributes(attr, true); - this.fireQueue(); - this.fireEvent('contentReady', { - type: 'contentReady', - target: attr.element - }); - }; - - if ( Lang.isString(el) ) { - _registerHTMLAttr.call(this, 'id', { value: el }); - YAHOO.util.Event.onAvailable(el, function() { - attr.element = Dom.get(el); - this.fireEvent('available', { - type: 'available', - target: attr.element - }); - }, this, true); - - YAHOO.util.Event.onContentReady(el, function() { - readyHandler.call(this); - }, this, true); - } else { - readyHandler.call(this); - } - } -}; - -/** - * Sets the value of the property and fires beforeChange and change events. - * @private - * @method _registerHTMLAttr - * @param {YAHOO.util.Element} element The Element instance to - * register the config to. - * @param {String} key The name of the config to register - * @param {Object} map A key-value map of the config's params - */ -var _registerHTMLAttr = function(key, map) { - var el = this.get('element'); - map = map || {}; - map.name = key; - map.method = map.method || function(value) { - el[key] = value; - }; - map.value = map.value || el[key]; - this._configs[key] = new YAHOO.util.Attribute(map, this); -}; - -/** - * Fires when the Element's HTMLElement can be retrieved by Id. - * <p>See: <a href="#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> available<br> - * <code><HTMLElement> - * target</code> the HTMLElement bound to this Element instance<br> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var target = e.target};<br> - * myTabs.addListener('available', handler);</code></p> - * @event available - */ - -/** - * Fires when the Element's HTMLElement subtree is rendered. - * <p>See: <a href="#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> contentReady<br> - * <code><HTMLElement> - * target</code> the HTMLElement bound to this Element instance<br> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var target = e.target};<br> - * myTabs.addListener('contentReady', handler);</code></p> - * @event contentReady - */ - -YAHOO.augment(YAHOO.util.Element, AttributeProvider); -})(); - -(function() { - var Dom = YAHOO.util.Dom, - Event = YAHOO.util.Event, - Lang = YAHOO.util.Lang; - - /** - * A representation of a Tab's label and content. - * @namespace YAHOO.widget - * @class Tab - * @extends YAHOO.util.Element - * @constructor - * @param element {HTMLElement | String} (optional) The html element that - * represents the TabView. An element will be created if none provided. - * @param {Object} properties A key map of initial properties - */ - var Tab = function(el, attr) { - attr = attr || {}; - if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) { - attr = el; - el = attr.element; - } - - if (!el && !attr.element) { - el = _createTabElement.call(this, attr); - } - - this.loadHandler = { - success: function(o) { - this.set('content', o.responseText); - }, - failure: function(o) { - } - }; - - Tab.superclass.constructor.call(this, el, attr); - - this.DOM_EVENTS = {}; // delegating to tabView - }; - - YAHOO.extend(Tab, YAHOO.util.Element); - var proto = Tab.prototype; - - /** - * The default tag name for a Tab's inner element. - * @property LABEL_INNER_TAGNAME - * @type String - * @default "em" - */ - proto.LABEL_TAGNAME = 'em'; - - /** - * The class name applied to active tabs. - * @property ACTIVE_CLASSNAME - * @type String - * @default "on" - */ - proto.ACTIVE_CLASSNAME = 'selected'; - - /** - * The class name applied to disabled tabs. - * @property DISABLED_CLASSNAME - * @type String - * @default "disabled" - */ - proto.DISABLED_CLASSNAME = 'disabled'; - - /** - * The class name applied to dynamic tabs while loading. - * @property LOADING_CLASSNAME - * @type String - * @default "disabled" - */ - proto.LOADING_CLASSNAME = 'loading'; - - /** - * Provides a reference to the connection request object when data is - * loaded dynamically. - * @property dataConnection - * @type Object - */ - proto.dataConnection = null; - - /** - * Object containing success and failure callbacks for loading data. - * @property loadHandler - * @type object - */ - proto.loadHandler = null; - - /** - * Provides a readable name for the tab. - * @method toString - * @return String - */ - proto.toString = function() { - var el = this.get('element'); - var id = el.id || el.tagName; - return "Tab " + id; - }; - - /** - * Registers TabView specific properties. - * @method initAttributes - * @param {Object} attr Hash of initial attributes - */ - proto.initAttributes = function(attr) { - attr = attr || {}; - Tab.superclass.initAttributes.call(this, attr); - - var el = this.get('element'); - - /** - * The event that triggers the tab's activation. - * @config activationEvent - * @type String - */ - this.register('activationEvent', { - value: attr.activationEvent || 'click' - }); - - /** - * The element that contains the tab's label. - * @config labelEl - * @type HTMLElement - */ - this.register('labelEl', { - value: attr.labelEl || _getlabelEl.call(this), - method: function(value) { - var current = this.get('labelEl'); - - if (current) { - if (current == value) { - return false; // already set - } - - this.replaceChild(value, current); - } else if (el.firstChild) { // ensure label is firstChild by default - this.insertBefore(value, el.firstChild); - } else { - this.appendChild(value); - } - } - }); - - /** - * The tab's label text (or innerHTML). - * @config label - * @type String - */ - this.register('label', { - value: attr.label || _getLabel.call(this), - method: function(value) { - var labelEl = this.get('labelEl'); - if (!labelEl) { // create if needed - this.set('labelEl', _createlabelEl.call(this)); - } - - _setLabel.call(this, value); - } - }); - - /** - * The HTMLElement that contains the tab's content. - * @config contentEl - * @type HTMLElement - */ - this.register('contentEl', { // TODO: apply className? - value: attr.contentEl || document.createElement('div'), - method: function(value) { - var current = this.get('contentEl'); - - if (current) { - if (current == value) { - return false; // already set - } - this.replaceChild(value, current); - } - } - }); - - /** - * The tab's content. - * @config content - * @type String - */ - this.register('content', { - value: attr.content, // TODO: what about existing? - method: function(value) { - this.get('contentEl').innerHTML = value; - } - }); - - var _dataLoaded = false; - - /** - * The tab's data source, used for loading content dynamically. - * @config dataSrc - * @type String - */ - this.register('dataSrc', { - value: attr.dataSrc - }); - - /** - * Whether or not content should be reloaded for every view. - * @config cacheData - * @type Boolean - * @default false - */ - this.register('cacheData', { - value: attr.cacheData || false, - validator: Lang.isBoolean - }); - - /** - * The method to use for the data request. - * @config loadMethod - * @type String - * @default "GET" - */ - this.register('loadMethod', { - value: attr.loadMethod || 'GET', - validator: Lang.isString - }); - - /** - * Whether or not any data has been loaded from the server. - * @config dataLoaded - * @type Boolean - */ - this.register('dataLoaded', { - value: false, - validator: Lang.isBoolean, - writeOnce: true - }); - - /** - * Number if milliseconds before aborting and calling failure handler. - * @config dataTimeout - * @type Number - * @default null - */ - this.register('dataTimeout', { - value: attr.dataTimeout || null, - validator: Lang.isNumber - }); - - /** - * Whether or not the tab is currently active. - * If a dataSrc is set for the tab, the content will be loaded from - * the given source. - * @config active - * @type Boolean - */ - this.register('active', { - value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME), - method: function(value) { - if (value === true) { - this.addClass(this.ACTIVE_CLASSNAME); - this.set('title', 'active'); - } else { - this.removeClass(this.ACTIVE_CLASSNAME); - this.set('title', ''); - } - }, - validator: function(value) { - return Lang.isBoolean(value) && !this.get('disabled') ; - } - }); - - /** - * Whether or not the tab is disabled. - * @config disabled - * @type Boolean - */ - this.register('disabled', { - value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME), - method: function(value) { - if (value === true) { - Dom.addClass(this.get('element'), this.DISABLED_CLASSNAME); - } else { - Dom.removeClass(this.get('element'), this.DISABLED_CLASSNAME); - } - }, - validator: Lang.isBoolean - }); - - /** - * The href of the tab's anchor element. - * @config href - * @type String - * @default '#' - */ - this.register('href', { - value: attr.href || '#', - method: function(value) { - this.getElementsByTagName('a')[0].href = value; - }, - validator: Lang.isString - }); - - /** - * The Whether or not the tab's content is visible. - * @config contentVisible - * @type Boolean - * @default false - */ - this.register('contentVisible', { - value: attr.contentVisible, - method: function(value) { - if (value == true) { - this.get('contentEl').style.display = 'block'; - - if ( this.get('dataSrc') ) { - // load dynamic content unless already loaded and caching - if ( !this.get('dataLoaded') || !this.get('cacheData') ) { - _dataConnect.call(this); - } - } - } else { - this.get('contentEl').style.display = 'none'; - } - }, - validator: Lang.isBoolean - }); - }; - - var _createTabElement = function(attr) { - var el = document.createElement('li'); - var a = document.createElement('a'); - - a.href = attr.href || '#'; - - el.appendChild(a); - - var label = attr.label || null; - var labelEl = attr.labelEl || null; - - if (labelEl) { // user supplied labelEl - if (!label) { // user supplied label - label = _getLabel.call(this, labelEl); - } - } else { - labelEl = _createlabelEl.call(this); - } - - a.appendChild(labelEl); - - return el; - }; - - var _getlabelEl = function() { - return this.getElementsByTagName(this.LABEL_TAGNAME)[0]; - }; - - var _createlabelEl = function() { - var el = document.createElement(this.LABEL_TAGNAME); - return el; - }; - - var _setLabel = function(label) { - var el = this.get('labelEl'); - el.innerHTML = label; - }; - - var _getLabel = function() { - var label, - el = this.get('labelEl'); - - if (!el) { - return undefined; - } - - return el.innerHTML; - }; - - var _dataConnect = function() { - if (!YAHOO.util.Connect) { - return false; - } - - Dom.addClass(this.get('contentEl').parentNode, this.LOADING_CLASSNAME); - - this.dataConnection = YAHOO.util.Connect.asyncRequest( - this.get('loadMethod'), - this.get('dataSrc'), - { - success: function(o) { - this.loadHandler.success.call(this, o); - this.set('dataLoaded', true); - this.dataConnection = null; - Dom.removeClass(this.get('contentEl').parentNode, - this.LOADING_CLASSNAME); - }, - failure: function(o) { - this.loadHandler.failure.call(this, o); - this.dataConnection = null; - Dom.removeClass(this.get('contentEl').parentNode, - this.LOADING_CLASSNAME); - }, - scope: this, - timeout: this.get('dataTimeout') - } - ); - }; - - YAHOO.widget.Tab = Tab; - - /** - * Fires before the active state is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeActiveChange<br> - * <code><Boolean> - * prevValue</code> the current value<br> - * <code><Boolean> - * newValue</code> the new value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeActiveChange', handler);</code></p> - * @event beforeActiveChange - */ - - /** - * Fires after the active state is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> activeChange<br> - * <code><Boolean> - * prevValue</code> the previous value<br> - * <code><Boolean> - * newValue</code> the updated value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('activeChange', handler);</code></p> - * @event activeChange - */ - - /** - * Fires before the tab label is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeLabelChange<br> - * <code><String> - * prevValue</code> the current value<br> - * <code><String> - * newValue</code> the new value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeLabelChange', handler);</code></p> - * @event beforeLabelChange - */ - - /** - * Fires after the tab label is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> labelChange<br> - * <code><String> - * prevValue</code> the previous value<br> - * <code><String> - * newValue</code> the updated value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('labelChange', handler);</code></p> - * @event labelChange - */ - - /** - * Fires before the tab content is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeContentChange<br> - * <code><String> - * prevValue</code> the current value<br> - * <code><String> - * newValue</code> the new value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeContentChange', handler);</code></p> - * @event beforeContentChange - */ - - /** - * Fires after the tab content is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> contentChange<br> - * <code><String> - * prevValue</code> the previous value<br> - * <code><Boolean> - * newValue</code> the updated value</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('contentChange', handler);</code></p> - * @event contentChange - */ -})(); - -(function() { - - /** - * The tabview module provides a widget for managing content bound to tabs. - * @module tabview - * @requires yahoo, dom, event - * - */ - /** - * A widget to control tabbed views. - * @namespace YAHOO.widget - * @class TabView - * @extends YAHOO.util.Element - * @constructor - * @param {HTMLElement | String | Object} el(optional) The html - * element that represents the TabView, or the attribute object to use. - * An element will be created if none provided. - * @param {Object} attr (optional) A key map of the tabView's - * initial attributes. Ignored if first arg is attributes object. - */ - YAHOO.widget.TabView = function(el, attr) { - attr = attr || {}; - if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) { - attr = el; // treat first arg as attr object - el = attr.element || null; - } - - if (!el && !attr.element) { // create if we dont have one - el = _createTabViewElement.call(this, attr); - } - YAHOO.widget.TabView.superclass.constructor.call(this, el, attr); - }; - - YAHOO.extend(YAHOO.widget.TabView, YAHOO.util.Element); - - var proto = YAHOO.widget.TabView.prototype; - var Dom = YAHOO.util.Dom; - var Lang = YAHOO.util.Lang; - var Event = YAHOO.util.Event; - var Tab = YAHOO.widget.Tab; - - - /** - * The className to add when building from scratch. - * @property CLASSNAME - * @default "navset" - */ - proto.CLASSNAME = 'yui-navset'; - - /** - * The className of the HTMLElement containing the TabView's tab elements - * to look for when building from existing markup, or to add when building - * from scratch. - * All childNodes of the tab container are treated as Tabs when building - * from existing markup. - * @property TAB_PARENT_CLASSNAME - * @default "nav" - */ - proto.TAB_PARENT_CLASSNAME = 'yui-nav'; - - /** - * The className of the HTMLElement containing the TabView's label elements - * to look for when building from existing markup, or to add when building - * from scratch. - * All childNodes of the content container are treated as content elements when - * building from existing markup. - * @property CONTENT_PARENT_CLASSNAME - * @default "nav-content" - */ - proto.CONTENT_PARENT_CLASSNAME = 'yui-content'; - - proto._tabParent = null; - proto._contentParent = null; - - /** - * Adds a Tab to the TabView instance. - * If no index is specified, the tab is added to the end of the tab list. - * @method addTab - * @param {YAHOO.widget.Tab} tab A Tab instance to add. - * @param {Integer} index The position to add the tab. - * @return void - */ - proto.addTab = function(tab, index) { - var tabs = this.get('tabs'); - if (!tabs) { // not ready yet - this._queue[this._queue.length] = ['addTab', arguments]; - return false; - } - - index = (index === undefined) ? tabs.length : index; - - var before = this.getTab(index); - - var self = this; - var el = this.get('element'); - var tabParent = this._tabParent; - var contentParent = this._contentParent; - - var tabElement = tab.get('element'); - var contentEl = tab.get('contentEl'); - - if ( before ) { - tabParent.insertBefore(tabElement, before.get('element')); - } else { - tabParent.appendChild(tabElement); - } - - if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) { - contentParent.appendChild(contentEl); - } - - if ( !tab.get('active') ) { - tab.set('contentVisible', false, true); /* hide if not active */ - } else { - this.set('activeTab', tab, true); - - } - - var activate = function(e) { - YAHOO.util.Event.preventDefault(e); - self.set('activeTab', this); - }; - - tab.addListener( tab.get('activationEvent'), activate); - - tab.addListener('activationEventChange', function(e) { - if (e.prevValue != e.newValue) { - tab.removeListener(e.prevValue, activate); - tab.addListener(e.newValue, activate); - } - }); - - tabs.splice(index, 0, tab); - }; - - /** - * Routes childNode events. - * @method DOMEventHandler - * @param {event} e The Dom event that is being handled. - * @return void - */ - proto.DOMEventHandler = function(e) { - var el = this.get('element'); - var target = YAHOO.util.Event.getTarget(e); - var tabParent = this._tabParent; - - if (Dom.isAncestor(tabParent, target) ) { - var tabEl; - var tab = null; - var contentEl; - var tabs = this.get('tabs'); - - for (var i = 0, len = tabs.length; i < len; i++) { - tabEl = tabs[i].get('element'); - contentEl = tabs[i].get('contentEl'); - - if ( target == tabEl || Dom.isAncestor(tabEl, target) ) { - tab = tabs[i]; - break; // note break - } - } - - if (tab) { - tab.fireEvent(e.type, e); - } - } - }; - - /** - * Returns the Tab instance at the specified index. - * @method getTab - * @param {Integer} index The position of the Tab. - * @return YAHOO.widget.Tab - */ - proto.getTab = function(index) { - return this.get('tabs')[index]; - }; - - /** - * Returns the index of given tab. - * @method getTabIndex - * @param {YAHOO.widget.Tab} tab The tab whose index will be returned. - * @return int - */ - proto.getTabIndex = function(tab) { - var index = null; - var tabs = this.get('tabs'); - for (var i = 0, len = tabs.length; i < len; ++i) { - if (tab == tabs[i]) { - index = i; - break; - } - } - - return index; - }; - - /** - * Removes the specified Tab from the TabView. - * @method removeTab - * @param {YAHOO.widget.Tab} item The Tab instance to be removed. - * @return void - */ - proto.removeTab = function(tab) { - var tabCount = this.get('tabs').length; - - var index = this.getTabIndex(tab); - var nextIndex = index + 1; - if ( tab == this.get('activeTab') ) { // select next tab - if (tabCount > 1) { - if (index + 1 == tabCount) { - this.set('activeIndex', index - 1); - } else { - this.set('activeIndex', index + 1); - } - } - } - - this._tabParent.removeChild( tab.get('element') ); - this._contentParent.removeChild( tab.get('contentEl') ); - this._configs.tabs.value.splice(index, 1); - - }; - - /** - * Provides a readable name for the TabView instance. - * @method toString - * @return String - */ - proto.toString = function() { - var name = this.get('id') || this.get('tagName'); - return "TabView " + name; - }; - - /** - * The transiton to use when switching between tabs. - * @method contentTransition - */ - proto.contentTransition = function(newTab, oldTab) { - newTab.set('contentVisible', true); - oldTab.set('contentVisible', false); - }; - - /** - * Registers TabView specific properties. - * @method initAttributes - * @param {Object} attr Hash of initial attributes - */ - proto.initAttributes = function(attr) { - YAHOO.widget.TabView.superclass.initAttributes.call(this, attr); - - if (!attr.orientation) { - attr.orientation = 'top'; - } - - var el = this.get('element'); - - /** - * The Tabs belonging to the TabView instance. - * @config tabs - * @type Array - */ - this.register('tabs', { - value: [], - readOnly: true - }); - - /** - * The container of the tabView's label elements. - * @property _tabParent - * @private - * @type HTMLElement - */ - this._tabParent = - this.getElementsByClassName(this.TAB_PARENT_CLASSNAME, - 'ul' )[0] || _createTabParent.call(this); - - /** - * The container of the tabView's content elements. - * @property _contentParent - * @type HTMLElement - * @private - */ - this._contentParent = - this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME, - 'div')[0] || _createContentParent.call(this); - - /** - * How the Tabs should be oriented relative to the TabView. - * @config orientation - * @type String - * @default "top" - */ - this.register('orientation', { - value: attr.orientation, - method: function(value) { - var current = this.get('orientation'); - this.addClass('yui-navset-' + value); - - if (current != value) { - this.removeClass('yui-navset-' + current); - } - - switch(value) { - case 'bottom': - this.appendChild(this._tabParent); - break; - } - } - }); - - /** - * The index of the tab currently active. - * @config activeIndex - * @type Int - */ - this.register('activeIndex', { - value: attr.activeIndex, - method: function(value) { - this.set('activeTab', this.getTab(value)); - }, - validator: function(value) { - return !this.getTab(value).get('disabled'); // cannot activate if disabled - } - }); - - /** - * The tab currently active. - * @config activeTab - * @type YAHOO.widget.Tab - */ - this.register('activeTab', { - value: attr.activeTab, - method: function(tab) { - var activeTab = this.get('activeTab'); - - if (tab) { - tab.set('active', true); - } - - if (activeTab && activeTab != tab) { - activeTab.set('active', false); - } - - if (activeTab && tab != activeTab) { // no transition if only 1 - this.contentTransition(tab, activeTab); - } else if (tab) { - tab.set('contentVisible', true); - } - }, - validator: function(value) { - return !value.get('disabled'); // cannot activate if disabled - } - }); - - if ( this._tabParent ) { - _initTabs.call(this); - } - - for (var type in this.DOM_EVENTS) { - if ( this.DOM_EVENTS.hasOwnProperty(type) ) { - this.addListener.call(this, type, this.DOMEventHandler); - } - } - }; - - /** - * Creates Tab instances from a collection of HTMLElements. - * @method createTabs - * @private - * @param {Array|HTMLCollection} elements The elements to use for Tabs. - * @return void - */ - var _initTabs = function() { - var tab, - attr, - contentEl; - - var el = this.get('element'); - var tabs = _getChildNodes(this._tabParent); - var contentElements = _getChildNodes(this._contentParent); - - for (var i = 0, len = tabs.length; i < len; ++i) { - attr = {}; - - if (contentElements[i]) { - attr.contentEl = contentElements[i]; - } - - tab = new YAHOO.widget.Tab(tabs[i], attr); - this.addTab(tab); - - if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) { - this._configs.activeTab.value = tab; // dont invoke method - } - } - }; - - var _createTabViewElement = function(attr) { - var el = document.createElement('div'); - - if ( this.CLASSNAME ) { - el.className = this.CLASSNAME; - } - - return el; - }; - - var _createTabParent = function(attr) { - var el = document.createElement('ul'); - - if ( this.TAB_PARENT_CLASSNAME ) { - el.className = this.TAB_PARENT_CLASSNAME; - } - - this.get('element').appendChild(el); - - return el; - }; - - var _createContentParent = function(attr) { - var el = document.createElement('div'); - - if ( this.CONTENT_PARENT_CLASSNAME ) { - el.className = this.CONTENT_PARENT_CLASSNAME; - } - - this.get('element').appendChild(el); - - return el; - }; - - var _getChildNodes = function(el) { - var nodes = []; - var childNodes = el.childNodes; - - for (var i = 0, len = childNodes.length; i < len; ++i) { - if (childNodes[i].nodeType == 1) { - nodes[nodes.length] = childNodes[i]; - } - } - - return nodes; - }; - -/** - * Fires before the activeTab is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeActiveTabChange<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * prevValue</code> the currently active tab<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * newValue</code> the tab to be made active</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeActiveTabChange', handler);</code></p> - * @event beforeActiveTabChange - */ - -/** - * Fires after the activeTab is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> activeTabChange<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * prevValue</code> the formerly active tab<br> - * <code><<a href="YAHOO.widget.Tab.html">YAHOO.widget.Tab</a>> - * newValue</code> the new active tab</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('activeTabChange', handler);</code></p> - * @event activeTabChange - */ - -/** - * Fires before the orientation is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p>If handler returns false, the change will be cancelled, and the value will not - * be set.</p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> beforeOrientationChange<br> - * <code><String> - * prevValue</code> the current orientation<br> - * <code><String> - * newValue</code> the new orientation to be applied</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('beforeOrientationChange', handler);</code></p> - * @event beforeOrientationChange - */ - -/** - * Fires after the orientation is changed. - * <p>See: <a href="YAHOO.util.Element.html#addListener">Element.addListener</a></p> - * <p><strong>Event fields:</strong><br> - * <code><String> type</code> orientationChange<br> - * <code><String> - * prevValue</code> the former orientation<br> - * <code><String> - * newValue</code> the new orientation</p> - * <p><strong>Usage:</strong><br> - * <code>var handler = function(e) {var previous = e.prevValue};<br> - * myTabs.addListener('orientationChange', handler);</code></p> - * @event orientationChange - */ -})(); - diff --git a/reports/site_media/yui/yahoo/README b/reports/site_media/yui/yahoo/README deleted file mode 100644 index 5d9a85146..000000000 --- a/reports/site_media/yui/yahoo/README +++ /dev/null @@ -1,45 +0,0 @@ -YAHOO Global - Release Notes - -0.12.2 - - * No change - -0.12.1 - - * No change - -0.12.0 - - * Added YAHOO.augment, which copies all or part of the prototype of one - object to another. - - * YAHOO.namespace now can create multiple namespaces. - - * Added an optional third parameter to YAHOO.extend: overrides. It takes - an object literal of properties/methods to apply to the subclass - prototype, overriding the superclass if present. - -0.11.4 - - * Changed window.YAHOO = window.YAHOO || {} to - if (typeof YAHOO == "undefined") YAHOO = {} because the previous statement - contributed to a memory leak in IE6 when the library was hosted in an - iframe. - -0.11.3 - - * Changed var YAHOO = window.YAHOO || {} to window.YAHOO = window.YAHOO || {}. - This fixes an issue in IE where YAHOO would get overwritten if previously - defined via array notation (window["YAHOO"]). - -0.11.0 - - * Added YAHOO.extend, which provides an easy way to assign the prototype, - constructor, and superclass properties inheritance properties. It also - prevents the constructor of the superclass from being exectuted twice. - -0.10.0 - - * Added YAHOO.log that provides a safe way to plumb logging statements in - code that will work if the logging component isn't available. - diff --git a/reports/site_media/yui/yahoo/yahoo-debug.js b/reports/site_media/yui/yahoo/yahoo-debug.js deleted file mode 100644 index e1f745ca8..000000000 --- a/reports/site_media/yui/yahoo/yahoo-debug.js +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ - -/** - * The YAHOO object is the single global object used by YUI Library. It - * contains utility function for setting up namespaces, inheritance, and - * logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces - * created automatically for and used by the library. - * @module yahoo - * @title YAHOO Global - */ - -if (typeof YAHOO == "undefined") { - /** - * The YAHOO global namespace object - * @class YAHOO - * @static - */ - var YAHOO = {}; -} - -/** - * Returns the namespace specified and creates it if it doesn't exist - * <pre> - * YAHOO.namespace("property.package"); - * YAHOO.namespace("YAHOO.property.package"); - * </pre> - * Either of the above would create YAHOO.property, then - * YAHOO.property.package - * - * Be careful when naming packages. Reserved words may work in some browsers - * and not others. For instance, the following will fail in Safari: - * <pre> - * YAHOO.namespace("really.long.nested.namespace"); - * </pre> - * This fails because "long" is a future reserved word in ECMAScript - * - * @method namespace - * @static - * @param {String*} arguments 1-n namespaces to create - * @return {Object} A reference to the last namespace object created - */ -YAHOO.namespace = function() { - var a=arguments, o=null, i, j, d; - for (i=0; i<a.length; ++i) { - d=a[i].split("."); - o=YAHOO; - - // YAHOO is implied, so it is ignored if it is included - for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; ++j) { - o[d[j]]=o[d[j]] || {}; - o=o[d[j]]; - } - } - - return o; -}; - -/** - * Uses YAHOO.widget.Logger to output a log message, if the widget is available. - * - * @method log - * @static - * @param {String} msg The message to log. - * @param {String} cat The log category for the message. Default - * categories are "info", "warn", "error", time". - * Custom categories can be used as well. (opt) - * @param {String} src The source of the the message (opt) - * @return {Boolean} True if the log operation was successful. - */ -YAHOO.log = function(msg, cat, src) { - var l=YAHOO.widget.Logger; - if(l && l.log) { - return l.log(msg, cat, src); - } else { - return false; - } -}; - -/** - * Utility to set up the prototype, constructor and superclass properties to - * support an inheritance strategy that can chain constructors and methods. - * - * @method extend - * @static - * @param {Function} subc the object to modify - * @param {Function} superc the object to inherit - * @param {Object} overrides additional properties/methods to add to the - * subclass prototype. These will override the - * matching items obtained from the superclass - * if present. - */ -YAHOO.extend = function(subc, superc, overrides) { - var F = function() {}; - F.prototype=superc.prototype; - subc.prototype=new F(); - subc.prototype.constructor=subc; - subc.superclass=superc.prototype; - if (superc.prototype.constructor == Object.prototype.constructor) { - superc.prototype.constructor=superc; - } - - if (overrides) { - for (var i in overrides) { - subc.prototype[i]=overrides[i]; - } - } -}; - -/** - * Applies all prototype properties in the supplier to the receiver if the - * receiver does not have these properties yet. Optionally, one or more - * methods/properties can be specified (as additional parameters). This - * option will overwrite the property if receiver has it already. - * - * @method augment - * @static - * @param {Function} r the object to receive the augmentation - * @param {Function} s the object that supplies the properties to augment - * @param {String*} arguments zero or more properties methods to augment the - * receiver with. If none specified, everything - * in the supplier will be used unless it would - * overwrite an existing property in the receiver - */ -YAHOO.augment = function(r, s) { - var rp=r.prototype, sp=s.prototype, a=arguments, i, p; - if (a[2]) { - for (i=2; i<a.length; ++i) { - rp[a[i]] = sp[a[i]]; - } - } else { - for (p in sp) { - if (!rp[p]) { - rp[p] = sp[p]; - } - } - } -}; - -YAHOO.namespace("util", "widget", "example"); diff --git a/reports/site_media/yui/yahoo/yahoo-min.js b/reports/site_media/yui/yahoo/yahoo-min.js deleted file mode 100644 index fb93090be..000000000 --- a/reports/site_media/yui/yahoo/yahoo-min.js +++ /dev/null @@ -1,12 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ - - -if(typeof YAHOO=="undefined"){var YAHOO={};} -YAHOO.namespace=function(){var a=arguments,o=null,i,j,d;for(i=0;i<a.length;++i){d=a[i].split(".");o=YAHOO;for(j=(d[0]=="YAHOO")?1:0;j<d.length;++j){o[d[j]]=o[d[j]]||{};o=o[d[j]];}} -return o;};YAHOO.log=function(msg,cat,src){var l=YAHOO.widget.Logger;if(l&&l.log){return l.log(msg,cat,src);}else{return false;}};YAHOO.extend=function(subc,superc,overrides){var F=function(){};F.prototype=superc.prototype;subc.prototype=new F();subc.prototype.constructor=subc;subc.superclass=superc.prototype;if(superc.prototype.constructor==Object.prototype.constructor){superc.prototype.constructor=superc;} -if(overrides){for(var i in overrides){subc.prototype[i]=overrides[i];}}};YAHOO.augment=function(r,s){var rp=r.prototype,sp=s.prototype,a=arguments,i,p;if(a[2]){for(i=2;i<a.length;++i){rp[a[i]]=sp[a[i]];}}else{for(p in sp){if(!rp[p]){rp[p]=sp[p];}}}};YAHOO.namespace("util","widget","example");
\ No newline at end of file diff --git a/reports/site_media/yui/yahoo/yahoo.js b/reports/site_media/yui/yahoo/yahoo.js deleted file mode 100644 index 2c3a17dec..000000000 --- a/reports/site_media/yui/yahoo/yahoo.js +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright (c) 2006, Yahoo! Inc. All rights reserved. -Code licensed under the BSD License: -http://developer.yahoo.net/yui/license.txt -version: 0.12.2 -*/ -/** - * The YAHOO object is the single global object used by YUI Library. It - * contains utility function for setting up namespaces, inheritance, and - * logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces - * created automatically for and used by the library. - * @module yahoo - * @title YAHOO Global - */ - -if (typeof YAHOO == "undefined") { - /** - * The YAHOO global namespace object - * @class YAHOO - * @static - */ - var YAHOO = {}; -} - -/** - * Returns the namespace specified and creates it if it doesn't exist - * <pre> - * YAHOO.namespace("property.package"); - * YAHOO.namespace("YAHOO.property.package"); - * </pre> - * Either of the above would create YAHOO.property, then - * YAHOO.property.package - * - * Be careful when naming packages. Reserved words may work in some browsers - * and not others. For instance, the following will fail in Safari: - * <pre> - * YAHOO.namespace("really.long.nested.namespace"); - * </pre> - * This fails because "long" is a future reserved word in ECMAScript - * - * @method namespace - * @static - * @param {String*} arguments 1-n namespaces to create - * @return {Object} A reference to the last namespace object created - */ -YAHOO.namespace = function() { - var a=arguments, o=null, i, j, d; - for (i=0; i<a.length; ++i) { - d=a[i].split("."); - o=YAHOO; - - // YAHOO is implied, so it is ignored if it is included - for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; ++j) { - o[d[j]]=o[d[j]] || {}; - o=o[d[j]]; - } - } - - return o; -}; - -/** - * Uses YAHOO.widget.Logger to output a log message, if the widget is available. - * - * @method log - * @static - * @param {String} msg The message to log. - * @param {String} cat The log category for the message. Default - * categories are "info", "warn", "error", time". - * Custom categories can be used as well. (opt) - * @param {String} src The source of the the message (opt) - * @return {Boolean} True if the log operation was successful. - */ -YAHOO.log = function(msg, cat, src) { - var l=YAHOO.widget.Logger; - if(l && l.log) { - return l.log(msg, cat, src); - } else { - return false; - } -}; - -/** - * Utility to set up the prototype, constructor and superclass properties to - * support an inheritance strategy that can chain constructors and methods. - * - * @method extend - * @static - * @param {Function} subc the object to modify - * @param {Function} superc the object to inherit - * @param {Object} overrides additional properties/methods to add to the - * subclass prototype. These will override the - * matching items obtained from the superclass - * if present. - */ -YAHOO.extend = function(subc, superc, overrides) { - var F = function() {}; - F.prototype=superc.prototype; - subc.prototype=new F(); - subc.prototype.constructor=subc; - subc.superclass=superc.prototype; - if (superc.prototype.constructor == Object.prototype.constructor) { - superc.prototype.constructor=superc; - } - - if (overrides) { - for (var i in overrides) { - subc.prototype[i]=overrides[i]; - } - } -}; - -/** - * Applies all prototype properties in the supplier to the receiver if the - * receiver does not have these properties yet. Optionally, one or more - * methods/properties can be specified (as additional parameters). This - * option will overwrite the property if receiver has it already. - * - * @method augment - * @static - * @param {Function} r the object to receive the augmentation - * @param {Function} s the object that supplies the properties to augment - * @param {String*} arguments zero or more properties methods to augment the - * receiver with. If none specified, everything - * in the supplier will be used unless it would - * overwrite an existing property in the receiver - */ -YAHOO.augment = function(r, s) { - var rp=r.prototype, sp=s.prototype, a=arguments, i, p; - if (a[2]) { - for (i=2; i<a.length; ++i) { - rp[a[i]] = sp[a[i]]; - } - } else { - for (p in sp) { - if (!rp[p]) { - rp[p] = sp[p]; - } - } - } -}; - -YAHOO.namespace("util", "widget", "example"); @@ -28,7 +28,9 @@ setup(cmdclass=cmdclass, "Bcfg2.Server.Snapshots", ], package_dir = {'Bcfg2':'src/lib'}, - package_data = {'Bcfg2.Server.Reports.reports':['fixtures/*.xml']}, + package_data = {'Bcfg2.Server.Reports.reports':['fixtures/*.xml', + 'templates/*.html', 'templates/*/*.html', + 'templates/*/*.inc' ] }, scripts = glob('src/sbin/*'), data_files = [('share/bcfg2/schemas', glob('schemas/*.xsd')), @@ -39,19 +41,13 @@ setup(cmdclass=cmdclass, ('share/man/man1', glob("man/bcfg2.1")), ('share/man/man5', glob("man/*.5")), ('share/man/man8', glob("man/*.8")), - ('share/bcfg2/Reports/templates', - glob('src/lib/Server/Reports/reports/templates/*.html')), - ('share/bcfg2/Reports/templates/displays', - glob('src/lib/Server/Reports/reports/templates/displays/*')), - ('share/bcfg2/Reports/templates/clients', - glob('src/lib/Server/Reports/reports/templates/clients/*')), - ('share/bcfg2/Reports/templates/config_items', - glob('src/lib/Server/Reports/reports/templates/config_items/*')), ('share/bcfg2/Hostbase/templates', glob('src/lib/Server/Hostbase/hostbase/webtemplates/*.*')), ('share/bcfg2/Hostbase/templates/hostbase', glob('src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/*')), ('share/bcfg2/Hostbase/repo', glob('src/lib/Server/Hostbase/templates/*')), + ('share/bcfg2/site_media', + glob('reports/site_media/*')), ] ) diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 95569e3ac..0458a4ce0 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -33,8 +33,8 @@ info_regex = re.compile( \ 'encoding:(\s)*(?P<encoding>\w+)|' + 'group:(\s)*(?P<group>\S+)|' + 'important:(\s)*(?P<important>\S+)|' + - 'mtime:(\s)*(?P<mtime>\w+)|' + - 'owner:(\s)*(?P<owner>\S+)|' + + 'mtime:(\s)*(?P<mtime>\w+)$' + + '^owner:(\s)*(?P<owner>\S+)|' + 'paranoid:(\s)*(?P<paranoid>\S+)|' + 'perms:(\s)*(?P<perms>\w+)|') diff --git a/src/lib/Server/Reports/reports/models.py b/src/lib/Server/Reports/reports/models.py index 5468420f6..1963a9090 100644 --- a/src/lib/Server/Reports/reports/models.py +++ b/src/lib/Server/Reports/reports/models.py @@ -28,26 +28,30 @@ TYPE_CHOICES = ( (TYPE_MODIFIED, 'Modified'), (TYPE_EXTRA, 'Extra'), ) + +def convert_entry_type_to_id(type_name): + """Convert a entry type to its entry id""" + for e_id, e_name in TYPE_CHOICES: + if e_name.lower() == type_name.lower(): + return e_id + return -1 + class ClientManager(models.Manager): """Extended client manager functions.""" - def active(self, timestamp='now'): - '''returns a set of clients that have been created and have not yet been + def active(self, timestamp=None): + """returns a set of clients that have been created and have not yet been expired as of optional timestmamp argument. Timestamp should be a - string formatted in the fashion: 2006-01-01 00:00:00''' + datetime object.""" - if timestamp == 'now': + if timestamp == None: timestamp = datetime.now() + elif not isinstance(timestamp, datetime): + raise ValueError, 'Expected a datetime object' else: - print timestamp try: timestamp = datetime(*strptime(timestamp, "%Y-%m-%d %H:%M:%S")[0:6]) except ValueError: - return self.filter(expiration__lt=timestamp, creation__gt=timestamp); - ''' - - this is a really hacky way to return an empty QuerySet - - this should return Client.objects.none() in Django - development version. - ''' + return self.none() return self.filter(Q(expiration__gt=timestamp) | Q(expiration__isnull=True), creation__lt=timestamp) @@ -81,33 +85,64 @@ class Ping(models.Model): get_latest_by = 'endtime' class InteractiveManager(models.Manager): - """Manages interactions objects. + """Manages interactions objects.""" + + def recent_interactions_dict(self, maxdate=None, active_only=True): + """ + Return the most recent interactions for clients as of a date. + + This method uses aggregated queries to return a ValuesQueryDict object. + Faster then raw sql since this is executed as a single query. + """ - Returns most recent interaction as of specified timestamp in format: - '2006-01-01 00:00:00' or 'now' or None->'now' + return self.values('client').annotate(max_timestamp=Max('timestamp')).values() + + def interaction_per_client(self, maxdate = None, active_only=True): + """ + Returns the most recent interactions for clients as of a date + + Arguments: + maxdate -- datetime object. Most recent date to pull. (dafault None) + active_only -- Include only active clients (default True) + + """ - """ - def interaction_per_client(self, maxdate = None): - """Returns the most recent interactions for clients as of a date. - FIXME - check the dates passed in. + if maxdate and not isinstance(maxdate,datetime): + raise ValueError, 'Expected a datetime object' + return self.filter(id__in = self.get_interaction_per_client_ids(maxdate, active_only)) + + def get_interaction_per_client_ids(self, maxdate = None, active_only=True): + """ + Returns the ids of most recent interactions for clients as of a date. + + Arguments: + maxdate -- datetime object. Most recent date to pull. (dafault None) + active_only -- Include only active clients (default True) """ from django.db import connection cursor = connection.cursor() + cfilter = "expiration is null" sql = 'select reports_interaction.id, x.client_id from (select client_id, MAX(timestamp) ' + \ 'as timer from reports_interaction' - if maxdate != 'now': - sql = sql + " where timestamp < '%s' " % maxdate + if maxdate: + if not isinstance(maxdate,datetime): + raise ValueError, 'Expected a datetime object' + sql = sql + " where timestamp <= '%s' " % maxdate + cfilter = "(expiration is null or expiration > '%s') and creation <= '%s'" % (maxdate,maxdate) sql = sql + ' GROUP BY client_id) x, reports_interaction where ' + \ 'reports_interaction.client_id = x.client_id AND reports_interaction.timestamp = x.timer' + if active_only: + sql = sql + " and x.client_id in (select id from reports_client where %s)" % \ + cfilter try: cursor.execute(sql) + return [item[0] for item in cursor.fetchall()] except: '''FIXME - really need some error hadling''' - return self.none() - return self.filter(id__in = [item[0] for item in cursor.fetchall()]) - + pass + return [] class Interaction(models.Model): """Models each reconfiguration operation interaction between client and server.""" @@ -213,6 +248,7 @@ class Interaction(models.Model): pass class Meta: get_latest_by = 'timestamp' + ordering = ['-timestamp'] unique_together = ("client", "timestamp") class Reason(models.Model): @@ -267,42 +303,6 @@ class Entries_interactions(models.Model): interaction = models.ForeignKey(Interaction) type = models.IntegerField(choices=TYPE_CHOICES) -class PerformanceManager(models.Manager): - """ - Provides ability to effectively query for performance information - It is possible this should move to the view - - """ - #Date format for maxdate: '2006-01-01 00:00:00' - def performance_per_client(self, maxdate = None): - from django.db import connection - cursor = connection.cursor() - if (maxdate == 'now' or maxdate == None): - cursor.execute("SELECT reports_client.name, reports_performance.metric, reports_performance.value "+ - "FROM reports_performance, reports_performance_interaction, reports_client WHERE ( "+ - "reports_client.current_interaction_id = reports_performance_interaction.interaction_id AND "+ - "reports_performance.id = reports_performance_interaction.performance_id)") - else: - cursor.execute("select reports_client.name, reports_performance.metric, "+ - "reports_performance.value from (Select reports_interaction.client_id as client_id, "+ - "MAX(reports_interaction.timestamp) as timestamp from reports_interaction where "+ - "timestamp < %s GROUP BY reports_interaction.client_id) x, reports_client, "+ - "reports_interaction, reports_performance, reports_performance_interaction where "+ - "reports_client.id = x.client_id AND x.timestamp = reports_interaction.timestamp AND "+ - "x.client_id = reports_interaction.client_id AND reports_performance.id = "+ - "reports_performance_interaction.performance_id AND "+ - "reports_performance_interaction.interaction_id = reports_interaction.id", [maxdate]) - - results = {} - for row in cursor.fetchall(): - try: - results[row[0]].__setitem__(row[1], row[2]) - except KeyError: - results[row[0]] = {row[1]:row[2]} - - return results - -#performance metrics, models a performance-metric-item class Performance(models.Model): """Object representing performance data for any interaction.""" interaction = models.ManyToManyField(Interaction, related_name="performance_items") @@ -319,8 +319,6 @@ class Performance(models.Model): cursor.execute('delete from reports_performance where not exists (select ri.id from reports_performance_interaction ri where ri.performance_id = reports_performance.id)') transaction.set_dirty() - objects = PerformanceManager() - class InternalDatabaseVersion(models.Model): """Object that tell us to witch version is the database.""" version = models.IntegerField() diff --git a/src/lib/Server/Reports/reports/models.py.orig b/src/lib/Server/Reports/reports/models.py.orig new file mode 100644 index 000000000..5468420f6 --- /dev/null +++ b/src/lib/Server/Reports/reports/models.py.orig @@ -0,0 +1,330 @@ +"""Django models for Bcfg2 reports.""" +from django.db import models +from django.db import connection, transaction +from django.db.models import Q +from datetime import datetime, timedelta +from time import strptime + +KIND_CHOICES = ( + #These are the kinds of config elements + ('Package', 'Package'), + ('Path', 'directory'), + ('Path', 'file'), + ('Path', 'permissions'), + ('Path', 'symlink'), + ('Service', 'Service'), +) +PING_CHOICES = ( + #These are possible ping states + ('Up (Y)', 'Y'), + ('Down (N)', 'N') +) +TYPE_BAD = 1 +TYPE_MODIFIED = 2 +TYPE_EXTRA = 3 + +TYPE_CHOICES = ( + (TYPE_BAD, 'Bad'), + (TYPE_MODIFIED, 'Modified'), + (TYPE_EXTRA, 'Extra'), +) +class ClientManager(models.Manager): + """Extended client manager functions.""" + def active(self, timestamp='now'): + '''returns a set of clients that have been created and have not yet been + expired as of optional timestmamp argument. Timestamp should be a + string formatted in the fashion: 2006-01-01 00:00:00''' + + if timestamp == 'now': + timestamp = datetime.now() + else: + print timestamp + try: + timestamp = datetime(*strptime(timestamp, "%Y-%m-%d %H:%M:%S")[0:6]) + except ValueError: + return self.filter(expiration__lt=timestamp, creation__gt=timestamp); + ''' + - this is a really hacky way to return an empty QuerySet + - this should return Client.objects.none() in Django + development version. + ''' + + return self.filter(Q(expiration__gt=timestamp) | Q(expiration__isnull=True), + creation__lt=timestamp) + + +class Client(models.Model): + """Object representing every client we have seen stats for.""" + creation = models.DateTimeField(auto_now_add=True) + name = models.CharField(max_length=128,) + current_interaction = models.ForeignKey('Interaction', + null=True, blank=True, + related_name="parent_client") + expiration = models.DateTimeField(blank=True, null=True) + + def __str__(self): + return self.name + + objects = ClientManager() + + class Admin: + pass + +class Ping(models.Model): + """Represents a ping of a client (sparsely).""" + client = models.ForeignKey(Client, related_name="pings") + starttime = models.DateTimeField() + endtime = models.DateTimeField() + status = models.CharField(max_length=4, choices=PING_CHOICES)#up/down + + class Meta: + get_latest_by = 'endtime' + +class InteractiveManager(models.Manager): + """Manages interactions objects. + + Returns most recent interaction as of specified timestamp in format: + '2006-01-01 00:00:00' or 'now' or None->'now' + + """ + def interaction_per_client(self, maxdate = None): + """Returns the most recent interactions for clients as of a date. + FIXME - check the dates passed in. + + """ + from django.db import connection + cursor = connection.cursor() + + sql = 'select reports_interaction.id, x.client_id from (select client_id, MAX(timestamp) ' + \ + 'as timer from reports_interaction' + if maxdate != 'now': + sql = sql + " where timestamp < '%s' " % maxdate + sql = sql + ' GROUP BY client_id) x, reports_interaction where ' + \ + 'reports_interaction.client_id = x.client_id AND reports_interaction.timestamp = x.timer' + try: + cursor.execute(sql) + except: + '''FIXME - really need some error hadling''' + return self.none() + return self.filter(id__in = [item[0] for item in cursor.fetchall()]) + + +class Interaction(models.Model): + """Models each reconfiguration operation interaction between client and server.""" + client = models.ForeignKey(Client, related_name="interactions",) + timestamp = models.DateTimeField()#Timestamp for this record + state = models.CharField(max_length=32)#good/bad/modified/etc + repo_rev_code = models.CharField(max_length=64)#repo revision at time of interaction + client_version = models.CharField(max_length=32)#Client Version + goodcount = models.IntegerField()#of good config-items + totalcount = models.IntegerField()#of total config-items + server = models.CharField(max_length=256) # Name of the server used for the interaction + bad_entries = models.IntegerField(default=-1) + modified_entries = models.IntegerField(default=-1) + extra_entries = models.IntegerField(default=-1) + + def __str__(self): + return "With " + self.client.name + " @ " + self.timestamp.isoformat() + + def percentgood(self): + if not self.totalcount == 0: + return (self.goodcount/float(self.totalcount))*100 + else: + return 0 + + def percentbad(self): + if not self.totalcount == 0: + return ((self.totalcount-self.goodcount)/(float(self.totalcount)))*100 + else: + return 0 + + def isclean(self): + if (self.bad_entry_count() == 0 and self.goodcount == self.totalcount): + return True + else: + return False + + def isstale(self): + if (self == self.client.current_interaction):#Is Mostrecent + if(datetime.now()-self.timestamp > timedelta(hours=25) ): + return True + else: + return False + else: + #Search for subsequent Interaction for this client + #Check if it happened more than 25 hrs ago. + if (self.client.interactions.filter(timestamp__gt=self.timestamp) + .order_by('timestamp')[0].timestamp - + self.timestamp > timedelta(hours=25)): + return True + else: + return False + def save(self): + super(Interaction, self).save() #call the real save... + self.client.current_interaction = self.client.interactions.latest() + self.client.save()#save again post update + + def delete(self): + '''Override the default delete. Allows us to remove Performance items''' + pitems = list(self.performance_items.all()) + super(Interaction, self).delete() + for perf in pitems: + if perf.interaction.count() == 0: + perf.delete() + + def badcount(self): + return self.totalcount - self.goodcount + + def bad(self): + return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_BAD) + + def bad_entry_count(self): + """Number of bad entries. Store the count in the interation field to save db queries.""" + if self.bad_entries < 0: + self.bad_entries = Entries_interactions.objects.filter(interaction=self, type=TYPE_BAD).count() + self.save() + return self.bad_entries + + def modified(self): + return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_MODIFIED) + + def modified_entry_count(self): + """Number of modified entries. Store the count in the interation field to save db queries.""" + if self.modified_entries < 0: + self.modified_entries = Entries_interactions.objects.filter(interaction=self, type=TYPE_MODIFIED).count() + self.save() + return self.modified_entries + + def extra(self): + return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_EXTRA) + + def extra_entry_count(self): + """Number of extra entries. Store the count in the interation field to save db queries.""" + if self.extra_entries < 0: + self.extra_entries = Entries_interactions.objects.filter(interaction=self, type=TYPE_EXTRA).count() + self.save() + return self.extra_entries + + objects = InteractiveManager() + + class Admin: + list_display = ('client', 'timestamp', 'state') + list_filter = ['client', 'timestamp'] + pass + class Meta: + get_latest_by = 'timestamp' + unique_together = ("client", "timestamp") + +class Reason(models.Model): + """reason why modified or bad entry did not verify, or changed.""" + owner = models.TextField(max_length=128, blank=True) + current_owner = models.TextField(max_length=128, blank=True) + group = models.TextField(max_length=128, blank=True) + current_group = models.TextField(max_length=128, blank=True) + perms = models.TextField(max_length=4, blank=True)#txt fixes typing issue + current_perms = models.TextField(max_length=4, blank=True) + status = models.TextField(max_length=3, blank=True)#on/off/(None) + current_status = models.TextField(max_length=1, blank=True)#on/off/(None) + to = models.TextField(max_length=256, blank=True) + current_to = models.TextField(max_length=256, blank=True) + version = models.TextField(max_length=128, blank=True) + current_version = models.TextField(max_length=128, blank=True) + current_exists = models.BooleanField()#False means its missing. Default True + current_diff = models.TextField(max_length=1280, blank=True) + is_binary = models.BooleanField(default=False) + def _str_(self): + return "Reason" + + @staticmethod + @transaction.commit_on_success + def prune_orphans(): + '''Prune oprhaned rows... no good way to use the ORM''' + cursor = connection.cursor() + cursor.execute('delete from reports_reason where not exists (select rei.id from reports_entries_interactions rei where rei.reason_id = reports_reason.id)') + transaction.set_dirty() + + +class Entries(models.Model): + """Contains all the entries feed by the client.""" + name = models.CharField(max_length=128, db_index=True) + kind = models.CharField(max_length=16, choices=KIND_CHOICES, db_index=True) + + def __str__(self): + return self.name + + @staticmethod + @transaction.commit_on_success + def prune_orphans(): + '''Prune oprhaned rows... no good way to use the ORM''' + cursor = connection.cursor() + cursor.execute('delete from reports_entries where not exists (select rei.id from reports_entries_interactions rei where rei.entry_id = reports_entries.id)') + transaction.set_dirty() + +class Entries_interactions(models.Model): + """Define the relation between the reason, the interaction and the entry.""" + entry = models.ForeignKey(Entries) + reason = models.ForeignKey(Reason) + interaction = models.ForeignKey(Interaction) + type = models.IntegerField(choices=TYPE_CHOICES) + +class PerformanceManager(models.Manager): + """ + Provides ability to effectively query for performance information + It is possible this should move to the view + + """ + #Date format for maxdate: '2006-01-01 00:00:00' + def performance_per_client(self, maxdate = None): + from django.db import connection + cursor = connection.cursor() + if (maxdate == 'now' or maxdate == None): + cursor.execute("SELECT reports_client.name, reports_performance.metric, reports_performance.value "+ + "FROM reports_performance, reports_performance_interaction, reports_client WHERE ( "+ + "reports_client.current_interaction_id = reports_performance_interaction.interaction_id AND "+ + "reports_performance.id = reports_performance_interaction.performance_id)") + else: + cursor.execute("select reports_client.name, reports_performance.metric, "+ + "reports_performance.value from (Select reports_interaction.client_id as client_id, "+ + "MAX(reports_interaction.timestamp) as timestamp from reports_interaction where "+ + "timestamp < %s GROUP BY reports_interaction.client_id) x, reports_client, "+ + "reports_interaction, reports_performance, reports_performance_interaction where "+ + "reports_client.id = x.client_id AND x.timestamp = reports_interaction.timestamp AND "+ + "x.client_id = reports_interaction.client_id AND reports_performance.id = "+ + "reports_performance_interaction.performance_id AND "+ + "reports_performance_interaction.interaction_id = reports_interaction.id", [maxdate]) + + results = {} + for row in cursor.fetchall(): + try: + results[row[0]].__setitem__(row[1], row[2]) + except KeyError: + results[row[0]] = {row[1]:row[2]} + + return results + +#performance metrics, models a performance-metric-item +class Performance(models.Model): + """Object representing performance data for any interaction.""" + interaction = models.ManyToManyField(Interaction, related_name="performance_items") + metric = models.CharField(max_length=128) + value = models.DecimalField(max_digits=32, decimal_places=16) + def __str__(self): + return self.metric + + @staticmethod + @transaction.commit_on_success + def prune_orphans(): + '''Prune oprhaned rows... no good way to use the ORM''' + cursor = connection.cursor() + cursor.execute('delete from reports_performance where not exists (select ri.id from reports_performance_interaction ri where ri.performance_id = reports_performance.id)') + transaction.set_dirty() + + objects = PerformanceManager() + +class InternalDatabaseVersion(models.Model): + """Object that tell us to witch version is the database.""" + version = models.IntegerField() + updated = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return "version %d updated the %s" % (self.version, self.updated.isoformat()) diff --git a/src/lib/Server/Reports/reports/models.py.rej b/src/lib/Server/Reports/reports/models.py.rej new file mode 100644 index 000000000..c8e1b2229 --- /dev/null +++ b/src/lib/Server/Reports/reports/models.py.rej @@ -0,0 +1,15 @@ +*************** +*** 1,6 **** + """Django models for Bcfg2 reports.""" + from django.db import models +- from django.db.models import Q + from datetime import datetime, timedelta + from time import strptime + +--- 1,6 ---- + """Django models for Bcfg2 reports.""" + from django.db import models ++ from django.db.models import Q, Max + from datetime import datetime, timedelta + from time import strptime + diff --git a/src/lib/Server/Reports/reports/templates/404.html b/src/lib/Server/Reports/reports/templates/404.html new file mode 100644 index 000000000..168bd9fec --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/404.html @@ -0,0 +1,8 @@ +{% extends 'base.html' %} +{% block title %}Bcfg2 - Page not found{% endblock %} +{% block fullcontent %} +<h2>Page not found</h2> +<p> +The page or object requested could not be found. +</p> +{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/base-timeview.html b/src/lib/Server/Reports/reports/templates/base-timeview.html new file mode 100644 index 000000000..d0617cde7 --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/base-timeview.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} + +{% block timepiece %} +<script type="text/javascript"> +function showCalendar() { + var cal = new CalendarPopup("calendar_div"); + cal.showYearNavigation(); + cal.select(document.forms['cal_form'].cal_date,'cal_link', + 'yyyy/MM/dd' {% if timestamp %}, '{{ timestamp|date:'Y/m/d' }}'{% endif %} ); + return false; +} +function bcfg2_check_date() { + var new_date = document.getElementById('cal_date').value; + if(new_date) { + document.cal_form.submit(); + } +} +document.write(getCalendarStyles()); +</script> +{% if not timestamp %}Rendered at {% now "Y-m-d H:i" %} | {% else %}View as of {{ timestamp|date:"Y-m-d H:i" }} | {% endif %}{% spaceless %} + <a id='cal_link' name='cal_link' href='#' onclick='showCalendar(); return false;' + >[change]</a> + <form method='post' action='{{ path }}' id='cal_form' name='cal_form'><input id='cal_date' name='cal_date' type='hidden' value=''/></form> +{% endspaceless %} +{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Server/Reports/reports/templates/base.html index d42e26960..64c105e34 100644 --- a/src/lib/Server/Reports/reports/templates/base.html +++ b/src/lib/Server/Reports/reports/templates/base.html @@ -1,55 +1,93 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<?xml version="1.0"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> - <title>{% block title %}Bcfg2 Reporting System{% endblock %}</title> - <link rel="stylesheet" type="text/css" href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/boxypastel.css" /> - <link rel="stylesheet" type="text/css" href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/base.css" /> - <script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/main.js"></script> - {% block extra_header_info %}{% endblock %} +<title>{% block title %}Bcfg2 Reporting System{% endblock %}</title> + +<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> +<meta http-equiv="Content-language" content="en" /> +<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /> +<meta name="robots" content="noindex, nofollow" /> +<meta http-equiv="cache-control" content="no-cache" /> + +<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}/bcfg2_base.css" media="all" /> +<script type="text/javascript" src="{{ MEDIA_URL }}/bcfg2.js"></script> +<script type="text/javascript" src="{{ MEDIA_URL }}/date.js"></script> +<script type="text/javascript" src="{{ MEDIA_URL }}/AnchorPosition.js"></script> +<script type="text/javascript" src="{{ MEDIA_URL }}/CalendarPopup.js"></script> +<script type="text/javascript" src="{{ MEDIA_URL }}/PopupWindow.js"></script> +{% block extra_header_info %}{% endblock %} + </head> +<body onload="{% block body_onload %}{% endblock %}"> -<body> <div id="header"> - <div id="branding"> - <h1>Bcfg2 Reporting System</h1> + <a href="http://trac.mcs.anl.gov/projects/bcfg2"><img src='{{ MEDIA_URL }}/bcfg2_logo.png' + height='115' width='300' alt='Bcfg2' style='float:left; height: 115px' /></a> </div> - <div id="user-tools">...Change is Coming...</div> + +<div id="document"> + <div id="content"><div id="contentwrapper"> + {% block fullcontent %} + <div class='page_name'> + <h1>{% block pagebanner %}Page Banner{% endblock %}</h1> + <div id="timepiece">{% block timepiece %}Rendered at {% now "Y-m-d H:i" %}{% endblock %}</div> </div> - <div id="content-main"> - <div id="sidebar"> - {% block sidebar %} - <ul class="sidebar"> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../" class="sidebar">Home</a></li> - <li> - <a href="{% url Bcfg2.Server.Reports.reports.views.client_index %}" class="sidebar">Clients</a> - <ul class="sidebar-level2"> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.client_detailed_list %}" class="sidebar">Detailed List</a></li> - </ul> - </li> - <li> - <a href="{% url Bcfg2.Server.Reports.reports.views.display_index %}" class="sidebar">Displays</a> - <ul class="sidebar-level2"> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.display_sys_view %}" class="sidebar">System</a></li> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.display_summary %}" class="sidebar">Summary</a></li> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.display_timing %}" class="sidebar">Timing</a></li> - </ul> - </li> - <li> - <span class="sidebar">Config Items</span> - <ul class="sidebar-level2"> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.bad_item_index %}" class="sidebar">Bad</a></li> - <li><a href="{% url Bcfg2.Server.Reports.reports.views.modified_item_index %}" class="sidebar">Modified</a></li> - </ul> - </li> + <div class='detail_wrapper'> + {% block content %}{% endblock %} + </div> + {% endblock %} + </div></div><!-- content --> + <div id="sidemenucontainer"><div id="sidemenu"> + {% block sidemenu %} + <ul class='menu-level1'> + <li>Overview</li> + </ul> + <ul class='menu-level2'> + <li><a href="{% url reports_summary %}">Summary</a></li> + <li><a href="{% url reports_history %}">Recent Interactions</a></li> + <li><a href="{% url reports_timing %}">Timing</a></li> + </ul> + <ul class='menu-level1'> + <li>Clients</li> + </ul> + <ul class='menu-level2'> + <li><a href="{% url reports_grid_view %}">Grid View</a></li> + <li><a href="{% url reports_detailed_list %}">Detailed List</a></li> + <li><a href="{% url reports_client_manage %}">Manage</a></li> + </ul> + <ul class='menu-level1'> + <li>Entries Configured</li> + </ul> + <ul class='menu-level2'> + <li><a href="{% url reports_item_list "bad" %}">Bad</a></li> + <li><a href="{% url reports_item_list "modified" %}">Modified</a></li> + <li><a href="{% url reports_item_list "extra" %}">Extra</a></li> + </ul> +{% comment %} + TODO + <ul class='menu-level1'> + <li>Entry Types</li> + </ul> + <ul class='menu-level2'> + <li><a href="#">Action</a></li> + <li><a href="#">Package</a></li> + <li><a href="#">Path</a></li> + <li><a href="#">Service</a></li> + </ul> +{% endcomment %} + <ul class='menu-level1'> + <li><a href="http://trac.mcs.anl.gov/projects/bcfg2">Homepage</a></li> + <li><a href="http://doc.bcfg2.fourkitchens.com/index.html">Documentation</a></li> </ul> {% endblock %} + </div></div><!-- sidemenu --> + <div style='clear:both'></div> +</div><!-- document --> + <div id="footer"> + <span>Bcfg2 Version 1.1.0</span> </div> - <div id="container"> - {% block pagebanner %}{% endblock %} - {% block content %}{% endblock %} - </div> - </div> +<div id="calendar_div" style='position:absolute; visibility:hidden; background-color:white; layer-background-color:white;'></div> </body> </html> diff --git a/src/lib/Server/Reports/reports/templates/clients/client-nodebox.html b/src/lib/Server/Reports/reports/templates/clients/client-nodebox.html deleted file mode 100644 index 8dbd01d9a..000000000 --- a/src/lib/Server/Reports/reports/templates/clients/client-nodebox.html +++ /dev/null @@ -1,63 +0,0 @@ -{% load django_templating_sigh %} -{% if client %} - <a name="{{client.name}}"></a> - <div class="nodebox"> - <span class="notebox">Time Ran: {{interaction.timestamp}}</span> - <!--<span class="configbox">(-Insert Profile Name Here-)</span>--> - - <table class="invisitable"> - <tr><td width="43%"><h2>Node: <span class="nodename"> - <a href="{% url Bcfg2.Server.Reports.reports.views.client_detail hostname=client.name, pk=client.current_interaction.id %}">{{client.name}}</a></span></h2></td> - <td width="23%"> - {% if interaction.repo_rev_code %}Revision: {{interaction.repo_rev_code}}{% endif %} - </td> - <td width="33%"><div class="statusborder"> - <div class="greenbar" style="width: {{interaction.percentgood}}%;"> </div> - <div class="redbar" style="width: {{interaction.percentbad}}%;"> </div> - </div> - </td></tr> - </table> - {% if interaction.isclean %} - <div class="clean"> - <span class="nodelisttitle">Node is clean; Everything has been satisfactorily configured.</span> - </div> - {% endif %} - {% if interaction.isstale %} - <div class="warning"> - <span class="nodelisttitle">This node did not run within the last 24 hours-- it may be out of date.</span> - </div> - {% endif %} - {% if interaction.bad %} - <div class="bad"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('{{client.name}}-bad');" title="Click to expand" class="commentLink">{{interaction.bad.count}}</a> items did not verify and are considered Dirty.<br /></span> - <div class="items" id="{{client.name}}-bad"><ul class="plain"> - {% for bad in interaction.bad|sortwell %} - <li><strong>{{bad.entry.kind}}: </strong><tt><a href="{% url Bcfg2.Server.Reports.reports.views.config_item_bad bad.id%}">{{bad.entry.name}}</a></tt></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if interaction.modified %} - <div class="modified"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('{{client.name}}-modified');" title="Click to expand" class="commentLink">{{interaction.modified.count}}</a> items were modified in the last run.<br /></span> - <div class="items" id="{{client.name}}-modified"><ul class="plain"> - {% for modified in interaction.modified|sortwell %} - <li><strong>{{modified.entry.kind}}: </strong><tt><a href="{% url Bcfg2.Server.Reports.reports.views.config_item_modified modified.id %}">{{modified.entry.name}}</a></tt></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if interaction.extra %} - <div class="extra"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('{{client.name}}-extra');" title="Click to expand" class="commentLink">{{interaction.extra.count}}</a> extra configuration elements on the node.<br /></span> - <div class="items" id="{{client.name}}-extra"><ul class="plain"> - {% for extra in interaction.extra|sortwell %} - <li><strong>{{extra.entry.kind}}: </strong><tt>{{extra.entry.name}}</tt></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - </div> -{% else %} - <p>No record could be found for this client.</p> -{% endif %} diff --git a/src/lib/Server/Reports/reports/templates/clients/detail.html b/src/lib/Server/Reports/reports/templates/clients/detail.html index 77f505804..efd5f9e00 100644 --- a/src/lib/Server/Reports/reports/templates/clients/detail.html +++ b/src/lib/Server/Reports/reports/templates/clients/detail.html @@ -1,17 +1,127 @@ {% extends "base.html" %} +{% load bcfg2_tags %} -{% block title %}Info for: {{client.name}}{% endblock %} +{% block title %}Bcfg2 - Client {{client.name}}{% endblock %} + +{% block extra_header_info %} +<style type="text/css"> +.node_data { + border: 1px solid #98DBCC; + margin: 10px; + padding-left: 18px; +} +.node_data td { + padding: 1px 20px 1px 2px; +} +span.history_links { + font-size: 90%; + margin-left: 50px; +} +span.history_links a { + font-size: 90%; +} +</style> +{% endblock %} + +{% block body_onload %}javascript:clientdetailload(){% endblock %} + +{% block pagebanner %}Client Details{% endblock %} {% block content %} -<h2>Client Status Detail page for {{client.name}}</h2><br/> -<b>Select time: </b> -<select name=quick onChange="MM_jumpMenu('parent',this,0)"> - {% for i in client.interactions.all %} - <option {% ifequal i.id interaction.id %}selected {% endifequal %} value="{% url Bcfg2.Server.Reports.reports.views.client_detail hostname=client.name, pk=i.id %}"> {{i.timestamp}} + <div class='detail_header'> + <h2>{{client.name}}</h2> + <a href='{% url reports_client_manage %}#{{ client.name }}'>[manage]</a> + <span class='history_links'><a href="{% url reports_client_history client.name %}">View History</a> | Jump to + <select id="quick" name="quick" onchange="javascript:pageJump('quick');"> + <option value="" selected="selected">--- Time ---</option> + {% for i in client.interactions.all|slice:":25" %} + <option value="{% url reports_client_detail_pk hostname=client.name, pk=i.id %}">{{i.timestamp}}</option> + {% endfor %} + </select></span> + </div> + + {% if interaction.isstale %} + <div class="warningbox"> + This node did not run within the last 24 hours — it may be out of date. + </div> + {% endif %} + <table class='node_data'> + <tr><td>Timestamp</td><td>{{interaction.timestamp}}</td></tr> + {% if interaction.server %} + <tr><td>Served by</td><td>{{interaction.server}}</td></tr> + {% endif %} + {% if interaction.repo_rev_code %} + <tr><td>Revision</td><td>{{interaction.repo_rev_code}}</td></tr> + {% endif %} + <tr><td>State</td><td class='{{interaction.state}}-lineitem'>{{interaction.state|capfirst}}</td></tr> + <tr><td>Managed entries</td><td>{{interaction.totalcount}}</td></tr> + {% if not interaction.isclean %} + <tr><td>Deviation</td><td>{{interaction.percentbad|floatformat:"3"}}%</td></tr> + {% endif %} + </table> + + {% if interaction.bad_entry_count %} + <div class='entry_list'> + <div class='entry_list_head dirty-lineitem'> + <div class='entry_expand_tab' onclick='javascript:toggleMe("bad_table");'>[+]</div> + <h3>Bad Entries — {{ interaction.bad_entry_count }}</h3> + </div> + <table id='bad_table' class='entry_list'> + {% for e in interaction.bad|sortwell %} + <tr class='{% cycle listview,listview_alt %}'> + <td class='entry_list_type'>{{e.entry.kind}}:</td> + <td><a href="{% url reports_item "bad",e.id %}"> + {{e.entry.name}}</a></td> + </tr> + {% endfor %} + </table> + </div> + {% endif %} + + {% if interaction.modified_entry_count %} + <div class='entry_list'> + <div class='entry_list_head modified-lineitem'> + <div class='entry_expand_tab' onclick='javascript:toggleMe("modified_table");'>[+]</div> + <h3>Modified Entries — {{ interaction.modified_entry_count }}</h3> + </div> + <table id='modified_table' class='entry_list'> + {% for e in interaction.modified|sortwell %} + <tr class='{% cycle listview,listview_alt %}'> + <td class='entry_list_type'>{{e.entry.kind}}:</td> + <td><a href="{% url reports_item "modified",e.id %}"> + {{e.entry.name}}</a></td> + </tr> + {% endfor %} + </table> + </div> + {% endif %} + + {% if interaction.extra_entry_count %} + <div class='entry_list'> + <div class='entry_list_head extra-lineitem'> + <div class='entry_expand_tab' onclick='javascript:toggleMe("extra_table");'>[+]</div> + <h3>Extra Entries — {{ interaction.extra_entry_count }}</h3> + </div> + <table id='extra_table' class='entry_list'> + {% for e in interaction.extra|sortwell %} + <tr class='{% cycle listview,listview_alt %}'> + <td class='entry_list_type'>{{e.entry.kind}}:</td> + <td><a href="{% url reports_item "extra",e.id %}">{{e.entry.name}}</a></td> + </tr> {% endfor %} -</select> - -<a href="{% url Bcfg2.Server.Reports.reports.views.client_manage hostname=client.name %}">Manage</a> {{client.name}} options.<br/> + </table> + </div> + {% endif %} -{% include "clients/client-nodebox.html" %} + {% if entry_list %} + <div class="entry_list recent_history_wrapper"> + <div class="entry_list_head" style="border-bottom: 2px solid #98DBCC;"> + <h4 style="display: inline"><a href="{% url reports_client_history client.name %}">Recent Interactions</a></h4> + </div> + <div class='recent_history_box'> + {% include "widgets/interaction_list.inc" %} + <div style='padding-left: 5px'><a href="{% url reports_client_history client.name %}">more...</a></div> + </div> + </div> + {% endif %} {% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html b/src/lib/Server/Reports/reports/templates/clients/detailed-list.html index 5a1352cff..0c1fae8d5 100644 --- a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html +++ b/src/lib/Server/Reports/reports/templates/clients/detailed-list.html @@ -1,57 +1,15 @@ -{% extends "base.html" %} +{% extends "base-timeview.html" %} +{% load bcfg2_tags %} -{% block title %}Detailed Client Listing{% endblock %} - -{% block extra_header_info %} -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script> -<script type="text/javascript">var cal = new CalendarPopup();</script> -<style type="text/css"> -#client_list_header { - font-weight: bold; - border-bottom:1px solid; - /*color: #333366;*/ -} -/*#client_list_box { - min-width:875px; -}*/ -.listview { - padding-top:3px; - padding-bottom:3px; -} -.listview_alt { - background:#f1ffc9; - padding-top:3px; - padding-bottom:3px; -} -</style> -{% endblock%} - -{% block pagebanner %} - <div class="header"> - <h1>Detailed Client List</h1> - </div> - <br/> -{% endblock %} +{% block title %}Bcfg2 - Detailed Client Listing{% endblock %} +{% block pagebanner %}Clients - Detailed View{% endblock %} {% block content %} -<div> -<form name="timestamp-select" action='{{ path }}' method='get'> -<span class="mini-date"> -<b>Enter date or use calendar popup: </b> -<input type="text" name="date1" value="{{timestamp_date}}" size="10" />@ -<input type="text" name="time" value="{{timestamp_time}}" size="8" /> -<a href="#" onclick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;" - name="anchor1" id="anchor1">Calendar</a> -<input type="button" value="Go" onclick="document.forms['timestamp-select'].submit();"/> - | <input type="button" name="now" value="Now" onclick="location.href='{{ path }}';"/> -</span><br/><br/> -</form> -</div> - -<div id='client_list_box'> +<div class='client_list_box'> {% if entry_list %} + {% filter_navigator %} <table cellpadding="3"> - <tr id='client_list_header' class='listview'> + <tr id='table_list_header' class='listview'> <td class='left_column'>Node</td> <td class='right_column' style='width:75px'>State</td> <td class='right_column_narrow'>Good</td> @@ -61,30 +19,19 @@ <td class='right_column'>Last Run</td> <td class='right_column_wide'>Server</td> </tr> - {% for client,entry,stale in entry_list %} + {% for entry in entry_list %} <tr class='{% cycle listview,listview_alt %}'> - <td class='left_column'><a href='{% url Bcfg2.Server.Reports.reports.views.client_detail hostname=client, pk=entry.id %}'>{{ client }}</a></td> - <td class='right_column' style='width:75px'><a href= - {% if server %} - '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list server=server,state=entry.state %}{{ qsa }}' - {% else %} - '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list state=entry.state %}{{ qsa }}' - {% endif %} - {% ifequal entry.state 'dirty' %}style='background:#FF6A6A'{% endifequal %}>{{ entry.state }}</a></td> + <td class='left_column'><a href='{% url Bcfg2.Server.Reports.reports.views.client_detail hostname=entry.client.name, pk=entry.id %}'>{{ entry.client.name }}</a></td> + <td class='right_column' style='width:75px'><a href='{% add_url_filter state=entry.state %}' + {% ifequal entry.state 'dirty' %}class='dirty-lineitem'{% endifequal %}>{{ entry.state }}</a></td> <td class='right_column_narrow'>{{ entry.goodcount }}</td> <td class='right_column_narrow'>{{ entry.bad_entry_count }}</td> <td class='right_column_narrow'>{{ entry.modified_entry_count }}</td> <td class='right_column_narrow'>{{ entry.extra_entry_count }}</td> - <td class='right_column'><span {% if stale %}style='background:#FF6A6A'{% endif %}>{{ entry.timestamp|date:"Y-m-d H:i" }}</span></td> + <td class='right_column'><span {% if entry.timestamp|isstale:entry_max %}class='dirty-lineitem'{% endif %}>{{ entry.timestamp|date:"Y-m-d\&\n\b\s\p\;H:i"|safe }}</span></td> <td class='right_column_wide'> {% if entry.server %} - <a href= - {% if state %} - '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list server=entry.server,state=state %}{{ qsa }}' - {% else %} - '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list server=entry.server %}{{ qsa }}' - {% endif %} - >{{ entry.server }}</a> + <a href='{% add_url_filter server=entry.server %}'>{{ entry.server }}</a> {% else %} {% endif %} diff --git a/src/lib/Server/Reports/reports/templates/clients/history.html b/src/lib/Server/Reports/reports/templates/clients/history.html new file mode 100644 index 000000000..01d4ec2f4 --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/clients/history.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load bcfg2_tags %} + +{% block title %}Bcfg2 - Interaction History{% endblock %} +{% block pagebanner %}Interaction history{% if client %} for {{ client.name }}{% endif %}{% endblock %} + +{% block extra_header_info %} +{% endblock %} + +{% block content %} +<div class='client_list_box'> +{% if entry_list %} + {% filter_navigator %} + {% include "widgets/interaction_list.inc" %} +{% else %} + <p>No client records are available.</p> +{% endif %} +</div> +{% page_navigator %} +{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/clients/index.html b/src/lib/Server/Reports/reports/templates/clients/index.html index cfb8a6c83..e0c0d2d7a 100644 --- a/src/lib/Server/Reports/reports/templates/clients/index.html +++ b/src/lib/Server/Reports/reports/templates/clients/index.html @@ -1,56 +1,33 @@ -{% extends "base.html" %} +{% extends "base-timeview.html" %} {% block extra_header_info %} -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/sorttable.js"></script> -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script> -<script language="JavaScript" type="text/javascript">var cal = new CalendarPopup();</script> {% endblock%} -{% block title %}Client Index Listing{% endblock %} +{% block title %}Bcfg2 - Client Grid View{% endblock %} -{% block pagebanner %} - <div class="header"> - <h1>Clients List</h1> - </div> - <br/> -{% endblock %} +{% block pagebanner %}Clients - Grid View{% endblock %} {% block content %} -<div> -<span class="mini-date"> -<b>Enter date or use calendar popup: </b> -</span> -<form name="timestamp-select" action="{{path}}" method="get"> -<span class="mini-date"> -<input type="text" name="date1" value="{{timestamp_date}}" size=10 />@ -<input type="text" name="time" value="{{timestamp_time}}" size=8 /> -<a href="#" onClick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;" - name="anchor1" ID="anchor1">Calendar</A> -<input type="button" name="go" value="Go" onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.client_index %}'+document.forms['timestamp-select'].date1.value+'@'+document.forms['timestamp-select'].time.value;" /> - | <input type="button" name="now" value="Now" onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.client_index %}';"/> -</span></form> -<br/><br/><br/></div> {% if inter_list %} -<table><tr><td valign="top"> - <ul style="list-style-type:none;"> - {% for client,inter in inter_list %} - <li><div class="{{inter.state}}-lineitem"> - <a href="{% spaceless %}{% ifequal timestamp 'now' %} - {% url Bcfg2.Server.Reports.reports.views.client_detail client %} + <table class='grid-view' align='center'> + {% for inter in inter_list %} + {% if forloop.first %}<tr>{% endif %} + <td class="{{inter.state}}-lineitem"> + <a href="{% spaceless %}{% if not timestamp %} + {% url reports_client_detail inter.client.name %} + {% else %} + {% url reports_client_detail_pk inter.client.name,inter.id %} + {% endif %} + {% endspaceless %}">{{ inter.client.name }}</a> + </td> + {% if forloop.last %} + </tr> {% else %} - {% url Bcfg2.Server.Reports.reports.views.client_detail client,inter.id %} - {% endifequal %} - {% endspaceless %}">{{ client }}</a> - </div></li> - {% ifequal half_list forloop.counter0 %} - </ul> -</td><td valign="top"> - <ul style="list-style-type:none;"> - {% endifequal %} + {% if forloop.counter|divisibleby:"4" %}</tr><tr>{% endif %} + {% endif %} {% endfor %} - </ul> -</tr></table> + </table> {% else %} <p>No client records are available.</p> {% endif %} diff --git a/src/lib/Server/Reports/reports/templates/clients/manage.html b/src/lib/Server/Reports/reports/templates/clients/manage.html index 61f0fe017..5725ae577 100644 --- a/src/lib/Server/Reports/reports/templates/clients/manage.html +++ b/src/lib/Server/Reports/reports/templates/clients/manage.html @@ -1,29 +1,45 @@ {% extends "base.html" %} + {% block extra_header_info %} -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script> -<script language="JavaScript" type="text/javascript">var cal = new CalendarPopup();</script> {% endblock%} -{% block title %}{{client.name}}{% endblock %} -{% block content %} -<h2>Client Options Management page for {{client.name}}</h2><br/> -<p>Client status detail page: <a href="{% url Bcfg2.Server.Reports.reports.views.client_detail client.name %}">{{client.name}}</a>.</p> -<p>Hosts may be prevented from showing up in the reporting system if they have been retired, are no longer managed by bcfg2 :(, etc. </p> -<b>Select deactivation date: </b> -<div> -<span class="mini-date"> -<b>Enter date or use calendar popup: </b> -</span> -<form name="timestamp-select" action="{% url Bcfg2.Server.Reports.reports.views.client_manage client.name %}" method="post"> -<span class="mini-date"> -<input type="text" name="date1" value="{{timestamp_date}}" size="10" />@ -<input type="text" name="time" value="{{timestamp_time}}" size="8" /> -<a href="#" onClick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;" - name="anchor1" ID="anchor1">Calendar</a> -<input type="submit" value="Submit"> -</span></form> -<br/><br/><br/></div> -<br/><br/> -<p>{{message}}</p> +{% block title %}Bcfg2 - Manage Clients{% endblock %} +{% block pagebanner %}Clients - Manage{% endblock %} + +{% block content %} +<div class='client_list_box'> + {% if message %} + <div class="warningbox">{{ message }}</div> + {% endif %} +{% if clients %} + <table cellpadding="3"> + <tr id='table_list_header' class='listview'> + <td class='left_column'>Node</td> + <td class='right_column'>Expiration</td> + <td class='right_column_narrow'>Manage</td> + </tr> + {% for client in clients %} + <tr class='{% cycle listview,listview_alt %}'> + <td><span id="{{ client.name }}"> </span> + <span id="ttag-{{ client.name }}"> </span> + <span id="s-ttag-{{ client.name }}"> </span> + <a href="{% url reports_client_detail client.name %}">{{ client.name }}</a></td> + <td>{% firstof client.expiration 'Active' %}</td> + <td> + <form method="post" action="{% url reports_client_manage %}"> + <div> {# here for no reason other then to validate #} + <input type="hidden" name="client_name" value="{{ client.name }}" /> + <input type="hidden" name="client_action" value="{% if client.expiration %}unexpire{% else %}expire{% endif %}" /> + <input type="submit" value="{% if client.expiration %}Activate{% else %}Expire Now{% endif %}" /> + </div> + </form> + </td> + </tr> + {% endfor %} + </table> + </div> +{% else %} + <p>No client records are available.</p> +{% endif %} {% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/config_items/index.html b/src/lib/Server/Reports/reports/templates/config_items/index.html deleted file mode 100644 index 04083344c..000000000 --- a/src/lib/Server/Reports/reports/templates/config_items/index.html +++ /dev/null @@ -1,100 +0,0 @@ -{% extends "base.html" %} - -{% load syntax_coloring %} - -{% block extra_header_info %} -<link rel="stylesheet" type="text/css" href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/syntax-coloring.css" /> -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script> -<script language="JavaScript" type="text/javascript">var cal = new CalendarPopup();</script> -{% endblock%} -{% block title %}Configuration Element Details{% endblock %} - -{% block pagebanner %} - <div class="header"> - <h1>Configuration Element Details</h1> - </div> - <br/> -{% endblock %} - -{% block content %} - -{% ifequal mod_or_bad "bad" %} -<div class="bad"> -<h2>Bad {{item.entry.kind}}: {{item.entry.name}}</h2> -</div> -{% else %} -<div class="modified"> -<h2>Modified {{item.entry.kind}}: {{item.entry.name}}</h2> -</div> -{% endifequal %} -<center> -<table border=1 padding=0 > -<tr><th>Reason</th><th>Current Status</th><th>Specified in bcfg2</th></tr> -{% if item.reason.current_owner %} -<tr><td align="right"><b>Owner: </b></td><td>{{item.reason.current_owner}}</td><td>{{item.reason.owner}}</td></tr> -{% endif %}{% if item.reason.current_group %} -<tr><td align="right"><b>Group: </b></td><td>{{item.reason.current_group}}</td><td>{{item.reason.group}}</td></tr> -{% endif %}{% if item.reason.current_perms %} -<tr><td align="right"><b>Permissions: </b></td><td>{{item.reason.current_perms}}</td><td>{{item.reason.perms}}</td></tr> -{% endif %}{% if item.reason.current_status %} -<tr><td align="right"><b>Status: </b></td><td>{{item.reason.current_status}}</td><td>{{item.reason.status}}</td></tr> -{% endif %}{% if item.reason.current_to %} -<tr><td align="right"><b>Link Destination: </b></td><td>{{item.reason.current_to}}</td><td>{{item.reason.to}}</td></tr> -{% endif %}{% if item.reason.current_version %} -<tr><td align="right"><b>Version: </b></td><td>{{item.reason.current_version}}</td><td>{{item.reason.version}}</td></tr> -{% endif %}{% if not item.reason.current_exists %} -<tr><td align="right"><b>Existence: </b></td><td colspan=2>This item does not currently exist on the host but is specified to exist in the configuration.</td></tr> -{% endif %}{% if item.reason.current_diff %} -<tr><td align="right"><b>NDiff: </b></td><td colspan=2><pre>{{item.reason.current_diff|syntaxhilight:"diff"}}</pre></td></tr> -{% endif %} -</table></center> -<hr/> -<div> -<span class="mini-date"> -<b>Enter date or use calendar popup: </b> -</span> -<form name="timestamp-select" action="{{path}}" method="get"> -<span class="mini-date"> -<input type="text" name="date1" value="{{timestamp_date}}" size="10" />@ -<input type="text" name="time" value="{{timestamp_time}}" size="8" /> -<a href="#" onClick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;" - name="anchor1" ID="anchor1">Calendar</A> -{% ifequal mod_or_bad "modified" %} - <input type="button" - name="go" - value="Go" - onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.config_item_modified eyedee=item.id%}'+document.forms['timestamp-select'].date1.value+'@'+document.forms['timestamp-select'].time.value;" /> - | <input type="button" - name="now" - value="Now" - onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.config_item_modified eyedee=item.id %}';"/> -{% else %} - <input type="button" - name="go" - value="Go" - onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.config_item_bad eyedee=item.id %}'+document.forms['timestamp-select'].date1.value+'@'+document.forms['timestamp-select'].time.value;"/> - | <input type="button" - name="now" - value="Now" - onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.config_item_bad eyedee=item.id %}';"/> -{% endifequal %} -</span></form> -<br/><br/><br/></div> -{% if associated_client_list %} - <p>The following clients had this problem as of {{timestamp_date}}@{{timestamp_time}}:</p> - {% for client in associated_client_list %} - <a href="{% url Bcfg2.Server.Reports.reports.views.client_detail client.name %}">{{client.name}}</a><br/> - {% endfor %} - <br /> - <br /> -{% else %} - <p>No Clients had this problem at {{timestamp}}</p> -{% endif %} - - - - - - - -{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/config_items/item.html b/src/lib/Server/Reports/reports/templates/config_items/item.html new file mode 100644 index 000000000..41474922b --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/config_items/item.html @@ -0,0 +1,109 @@ +{% extends "base.html" %} +{% load syntax_coloring %} + + +{% block title %}Bcfg2 - Element Details{% endblock %} + + +{% block extra_header_info %} +<style type="text/css"> +#table_list_header { + font-size: 100%; +} +table.entry_list { + width: auto; +} +div.information_wrapper { + margin: 15px; +} +div.diff_wrapper { + overflow: auto; +} +div.entry_list h3 { + font-size: 90%; + padding: 5px; +} +</style> +{% endblock%} + +{% block pagebanner %}Element Details{% endblock %} + +{% block content %} + <div class='detail_header'> + <h3>{{mod_or_bad|capfirst}} {{item.entry.kind}}: {{item.entry.name}}</h3> + </div> + + <div class="information_wrapper"> + + {% if isextra %} + <p>This item exists on the host but is not defined in the configuration.</p> + {% endif %} + + {% if not item.reason.current_exists %} + <div class="warning">This item does not currently exist on the host but is specified to exist in the configuration.</div> + {% endif %} + + {% if item.reason.current_owner or item.reason.current_group or item.reason.current_perms or item.reason.current_status or item.reason.current_status or item.reason.current_to or item.reason.current_version %} + <table class='entry_list'> + <tr id='table_list_header'> + <td style='text-align: right;'>Problem Type</td><td>Expected</td><td style='border-bottom: 1px solid #98DBCC;'>Found</td></tr> + {% if item.reason.current_owner %} + <tr><td style='text-align: right'><b>Owner</b></td><td>{{item.reason.owner}}</td> + <td>{{item.reason.current_owner}}</td></tr> + {% endif %} + {% if item.reason.current_group %} + <tr><td style='text-align: right'><b>Group</b></td><td>{{item.reason.group}}</td> + <td>{{item.reason.current_group}}</td></tr> + {% endif %} + {% if item.reason.current_perms %} + <tr><td style='text-align: right'><b>Permissions</b></td><td>{{item.reason.perms}}</td> + <td>{{item.reason.current_perms}}</td></tr> + {% endif %} + {% if item.reason.current_status %} + <tr><td style='text-align: right'><b>Status</b></td><td>{{item.reason.status}}</td> + <td>{{item.reason.current_status}}</td></tr> + {% endif %} + {% if item.reason.current_to %} + <tr><td style='text-align: right'><b>Symlink Target</b></td><td>{{item.reason.to}}</td> + <td>{{item.reason.current_to}}</td></tr> + {% endif %} + {% if item.reason.current_version %} + <tr><td style='text-align: right'><b>Package Version</b></td><td>{{item.reason.version|cut:"("|cut:")"}}</td> + <td>{{item.reason.current_version|cut:"("|cut:")"}}</td></tr> + {% endif %} + </table> + {% endif %} + + {% if item.reason.current_diff %} + <div class='entry_list'> + <div class='entry_list_head'> + <h3>Incorrect file contents</h3> + </div> + <div class='diff_wrapper'> + {{ item.reason.current_diff|syntaxhilight }} + </div> + </div> + {% endif %} + + + <div class='entry_list'> + <div class='entry_list_head'> + <h3>Occurances on {{ timestamp|date:"Y-m-d" }}</h3> + </div> + {% if associated_list %} + <table class="entry_list" cellpadding="3"> + {% for inter in associated_list %} + <tr><td><a href="{% url reports_client_detail inter.client.name %}" + >{{inter.client.name}}</a></td> + <td><a href="{% url reports_client_detail_pk hostname=inter.client.name,pk=inter.id %}" + >{{inter.timestamp}}</a></td> + </tr> + {% endfor %} + </table> + {% else %} + <p>Missing client list</p> + {% endif %} + </div> + + </div><!-- information_wrapper --> +{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/config_items/listing.html b/src/lib/Server/Reports/reports/templates/config_items/listing.html index 64a60e506..572249470 100644 --- a/src/lib/Server/Reports/reports/templates/config_items/listing.html +++ b/src/lib/Server/Reports/reports/templates/config_items/listing.html @@ -1,50 +1,32 @@ -{% extends "base.html" %} -{% load django_templating_sigh %} +{% extends "base-timeview.html" %} +{% load bcfg2_tags %} -{% block extra_header_info %} -<link rel="stylesheet" type="text/css" href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/yui/tabview/assets/tabview.css" /> -<link rel="stylesheet" type="text/css" href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/yui/round_tabs.css" /> - -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/yui/yahoo/yahoo.js"></script> -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/yui/event/event.js"></script> -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/yui/dom/dom.js"></script> -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/yui/tabview/tabview.js"></script> -<script type="text/javascript"> -YAHOO.example.init = function( ){ - var tabView = new YAHOO.widget.TabView( { id: 'demo' } ); - {% for item_list in item_list_pseudodict %} - tabView.addTab( new YAHOO.widget.Tab({ - label: '{{item_list.0}}', - content: '<p><ul style="list-style-type:none;">{% for item in item_list.1|sortwell %}<li><strong>{{item.entry.kind}}: <'+'/strong><tt>{% ifequal mod_or_bad "modified" %}<a href="{%url Bcfg2.Server.Reports.reports.views.config_item_modified eyedee=item.id%}">{{item.entry.name}}<'+'/a>{% else %}<a href="{%url Bcfg2.Server.Reports.reports.views.config_item_bad eyedee=item.id%}">{{item.entry.name}}<'+'/a>{% endifequal %}<'+'/tt><'+'/li>{% endfor %}<'+'/ul><'+'/p>', - active: 'True' - })); - {% endfor %} +{% block title %}Bcfg2 - Element Listing{% endblock %} - YAHOO.util.Event.onContentReady('tabview', function() { - tabView.appendTo(this); /* append to #doc */ - }); - -}; -YAHOO.example.init(); +{% block extra_header_info %} +{% endblock%} -</script> -<style type="text/css"> -#demo .yui-content { padding:1em; } /* pad content container */ -</style> -{% endblock %} +{% block pagebanner %}{{mod_or_bad|capfirst}} Element Listing{% endblock %} -{% block title %}{{mod_or_bad|capfirst}} Item Listing{% endblock %} +{% block content %} +{% if item_list_dict %} + {% for kind, entries in item_list_dict.items %} -{% block pagebanner %} - <div class="header"> - <h1>{{mod_or_bad|capfirst}} Configuration Elements</h1> + <div class='entry_list'> + <div class='entry_list_head element_list_head'> + <div class='entry_expand_tab' onclick='javascript:toggleMe("table_{{ kind }}");'>[+]</div> + <h3>{{ kind }} — {{ entries|length }}</h3> </div> - <br/> -{% endblock %} -{% block content %} -{% if item_list_pseudodict %} -<div id="tabview"></div> + <table id='table_{{ kind }}' class='entry_list'> + {% for e in entries %} + <tr class='{% cycle listview,listview_alt %}'> + <td><a href="{% url reports_item type=mod_or_bad,pk=e.id %}">{{e.entry.name}}</a></td> + </tr> + {% endfor %} + </table> + </div> + {% endfor %} {% else %} <p>There are currently no inconsistent configuration entries.</p> {% endif %} diff --git a/src/lib/Server/Reports/reports/templates/displays/index.html b/src/lib/Server/Reports/reports/templates/displays/index.html deleted file mode 100644 index c078539b6..000000000 --- a/src/lib/Server/Reports/reports/templates/displays/index.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Display Index Listing{% endblock %} -{% block pagebanner %} - <div class="header"> - <h1>BCFG Display Index</h1> - {% comment %} <span class="notebox">Report Run @ {% now "F j, Y P"%}</span>{% endcomment %} - </div> - <br/> -{% endblock %} - -{% block content %} -<ul> -<li><a href="{% url Bcfg2.Server.Reports.reports.views.display_sys_view %}">System View</a></li> -<li><a href="{% url Bcfg2.Server.Reports.reports.views.display_summary %}">Summary Only</a></li> -<li><a href="{% url Bcfg2.Server.Reports.reports.views.display_timing %}">Timing</a></li> -</ul> -{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/displays/summary-block-direct-links.html b/src/lib/Server/Reports/reports/templates/displays/summary-block-direct-links.html deleted file mode 100644 index 60f97eadc..000000000 --- a/src/lib/Server/Reports/reports/templates/displays/summary-block-direct-links.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "displays/summary-block.html" %} -{% block linkprefix1 %}{% url Bcfg2.Server.Reports.reports.views.client_index %}{% endblock %} -{% block linkprefix2 %}{% url Bcfg2.Server.Reports.reports.views.client_index %}{% endblock %} -{% block linkprefix3 %}{% url Bcfg2.Server.Reports.reports.views.client_index %}{% endblock %} -{% block linkprefix4 %}{% url Bcfg2.Server.Reports.reports.views.client_index %}{% endblock %} -{% block linkprefix5 %}{% url Bcfg2.Server.Reports.reports.views.client_index %}{% endblock %} -{% block linkprefix6 %}{% url Bcfg2.Server.Reports.reports.views.client_index %}{% endblock %}
\ No newline at end of file diff --git a/src/lib/Server/Reports/reports/templates/displays/summary-block.html b/src/lib/Server/Reports/reports/templates/displays/summary-block.html deleted file mode 100644 index 060ff0fa1..000000000 --- a/src/lib/Server/Reports/reports/templates/displays/summary-block.html +++ /dev/null @@ -1,90 +0,0 @@ -{% load django_templating_sigh %} - - <div class="nodebox"> - <h2>Summary:</h2> - <p class="indented">{{client_list|length }} Nodes were included in your report.</p> - {% if clean_client_list %} - <div class="clean"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('goodsummary');" title="Click to Expand" class="commentLink">{{clean_client_list|length}}</a> nodes are clean.<br /></span> - <div class="items" id="goodsummary"><ul class="plain"> - {% for client in clean_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="{% block linkprefix1 %}#{% endblock %}{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if bad_client_list %} - <div class="bad"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('badsummary');" title="Click to Expand" class="commentLink">{{bad_client_list|length}}</a> nodes are bad.<br /></span> - <div class="items" id="badsummary"><ul class="plain"> - {% for client in bad_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="{% block linkprefix2 %}#{% endblock %}{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if modified_client_list %} - <div class="modified"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('modifiedsummary');" title="Click to Expand" class="commentLink">{{modified_client_list|length}}</a> nodes were modified in the previous run.<br /></span> - <div class="items" id="modifiedsummary"><ul class="plain"> - {% for client in modified_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="{% block linkprefix3 %}#{% endblock %}{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if extra_client_list %} - <div class="extra"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('extrasummary');" title="Click to Expand" class="commentLink">{{extra_client_list|length}}</a> nodes have extra configuration. (includes both good and bad nodes)<br /></span> - <div class="items" id="extrasummary"><ul class="plain"> - {% for client in extra_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="{% block linkprefix4 %}#{% endblock %}{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if stale_up_client_list %} - <div class="warning"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('vstalesummary');" title="Click to Expand" class="commentLink">{{stale_up_client_list|length}}</a> nodes did not run within the last 24 hours but were pingable.<br /></span> - <div class="items" id="vstalesummary"><ul class="plain"> - {% for client in stale_up_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="{% block linkprefix5 %}#{% endblock %}{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if stale_all_client_list %} - <div class="all-warning"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('stalesummary');" title="Click to Expand" class="commentLink">{{stale_all_client_list|length}}</a> nodes did not run within the last 24 hours. (includes nodes up and down)<br /></span> - <div class="items" id="stalesummary"><ul class="plain"> - {% for client in stale_all_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="{% block linkprefix6 %}#{% endblock %}{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - {% if down_client_list %} - <div class="down"> - <span class="nodelisttitle"><a href="javascript:toggleLayer('unpingablesummary');" title="Click to Expand" class="commentLink">{{down_client_list|length}}</a> nodes were down.<br /></span> - <div class="items" id="unpingablesummary"><ul class="plain"> - {% for client in down_client_list|sortname %} - {% set_interaction "foo" %} - <li><b>Node: </b> - <tt><a href="#{{client.name}}">{{client.name}}</a></tt><span class="mini-date">{{interaction.timestamp}}</span></li> - {% endfor %} - </ul></div> - </div> - {% endif %} - </div> diff --git a/src/lib/Server/Reports/reports/templates/displays/summary.html b/src/lib/Server/Reports/reports/templates/displays/summary.html index 29cbb22d7..0124f635d 100644 --- a/src/lib/Server/Reports/reports/templates/displays/summary.html +++ b/src/lib/Server/Reports/reports/templates/displays/summary.html @@ -1,31 +1,42 @@ -{% extends "base.html" %} +{% extends "base-timeview.html" %} +{% load bcfg2_tags %} + +{% block title %}Bcfg2 - Client Summary{% endblock %} +{% block pagebanner %}Clients - Summary{% endblock %} + +{% block body_onload %}javascript:hide_table_array(hide_tables){% endblock %} + {% block extra_header_info %} -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script> -<script language="JavaScript" type="text/javascript">var cal = new CalendarPopup();</script> +<script type="text/javascript"> +var hide_tables = new Array({{ summary_data|length }}); +{% for summary in summary_data %} +hide_tables[{{ forloop.counter0 }}] = "table_{{ summary.name }}"; +{% endfor %} +</script> {% endblock%} -{% block title %}Display Index Listing{% endblock %} -{% block pagebanner %} - <div class="header"> - <h1>BCFG Clients Summary</h1> - <span class="notebox">Report Run @ {% now "F j, Y P"%}</span> - </div> - <br/> -{% endblock %} {% block content %} -<div> -<span class="mini-date"> -<b>Enter date or use calendar popup: </b> -</span> -<form name="timestamp-select" action="{{path}" method="get"> -<span class="mini-date"> -<input type="text" name="date1" value="{{timestamp_date}}" size="10" />@ -<input type="text" name="time" value="{{timestamp_time}}" size="8" /> -<a href="#" onClick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;" - name="anchor1" ID="anchor1">Calendar</A> -<input type="button" name="go" value="Go" onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.display_summary %}'+document.forms['timestamp-select'].date1.value+'@'+document.forms['timestamp-select'].time.value;" /> - | <input type="button" name="now" value="Now" onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.display_summary %}';"/> -</span></form> -<br/><br/><br/></div> - {% include "displays/summary-block-direct-links.html" %} + <div class='detail_header'> + <h2>{{ node_count }} nodes reporting in</h2> + </div> +{% if summary_data %} + {% for summary in summary_data %} + <div class='entry_list'> + <div class='entry_list_head element_list_head'> + <div class='entry_expand_tab' onclick='javascript:toggleMe("table_{{ summary.name }}");'>[+]</div> + <h3>{{ summary.nodes|length }} {{ summary.label }}</h3> + </div> + + <table id='table_{{ summary.name }}' class='entry_list'> + {% for node in summary.nodes|sort_interactions_by_name %} + <tr class='{% cycle listview,listview_alt %}'> + <td><a href="{% url reports_client_detail_pk hostname=node.client.name,pk=node.id %}">{{ node.client.name }}</a></td> + </tr> + {% endfor %} + </table> + </div> + {% endfor %} +{% else %} + <p>No data to report on</p> +{% endif %} {% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/displays/sys_view.html b/src/lib/Server/Reports/reports/templates/displays/sys_view.html deleted file mode 100644 index 1298059bf..000000000 --- a/src/lib/Server/Reports/reports/templates/displays/sys_view.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "base.html" %} -{% load django_templating_sigh %} - -{% block title %}System-View Display{% endblock %} -{% block pagebanner %} - <div class="header"> - <h1>Grand System View</h1> - <span class="notebox">Report Run @ {% now "F j, Y P"%}</span> - </div> - <br/> -{% endblock %} -{% block content %} -<center><h2>This view is deprecated and will be removed soon.</h2><br/>Please use the "Summary" view and drill down instead.</center> - - {% include "displays/summary-block.html" %} - {% for client in client_list %} - {% set_interaction "foo" %} - {% include "clients/client-nodebox.html" %} - {% endfor %} -{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/displays/timing.html b/src/lib/Server/Reports/reports/templates/displays/timing.html index 32ddab464..47accb2cb 100644 --- a/src/lib/Server/Reports/reports/templates/displays/timing.html +++ b/src/lib/Server/Reports/reports/templates/displays/timing.html @@ -1,54 +1,38 @@ -{% extends "base.html" %} +{% extends "base-timeview.html" %} +{% load bcfg2_tags %} + +{% block title %}Bcfg2 - Performance Metrics{% endblock %} +{% block pagebanner %}Performance Metrics{% endblock %} + {% block extra_header_info %} -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/sorttable.js"></script> -<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script> -<script language="JavaScript" type="text/javascript">var cal = new CalendarPopup();</script> {% endblock%} -{% block title %}Display Index Listing{% endblock %} {% block content %} - <div class="header"> - <h1>BCFG Performance Timings</h1> - <span class="notebox">Report Run @ {% now "F j, Y P"%}</span> - </div> - <br/> -<div> -<span class="mini-date"> -<b>Enter date or use calendar popup: </b> -</span> -<form name="timestamp-select" action="{{path}}" method="get"> -<span class="mini-date"> -<input type="text" name="date1" value="{{timestamp_date}}" size="10" />@ -<input type="text" name="time" value="{{timestamp_time}}" size="8" /> -<a href="#" onClick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;" - name="anchor1" ID="anchor1">Calendar</A> -<input type="button" name="go" value="Go" onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.display_timing %}'+document.forms['timestamp-select'].date1.value+'@'+document.forms['timestamp-select'].time.value;" /> - | <input type="button" name="now" value="Now" onClick="location.href='{% url Bcfg2.Server.Reports.reports.views.display_timing %}';"/> -</span></form> -<br/><br/><br/></div> - <center> - <table id="t1" class="sortable"> - <tr> - <th class="sortable">Hostname</th> - <th class="sortable">Parse</th> - <th class="sortable">Probe</th> - <th class="sortable">Inventory</th> - <th class="sortable">Install</th> - <th class="sortable">Config</th> - <th class="sortable">Total</th> +<div class='client_list_box'> + {% if metrics %} + <table cellpadding="3"> + <tr id='table_list_header' class='listview'> + <td>Name</td> + <td>Parse</td> + <td>Probe</td> + <td>Inventory</td> + <td>Install</td> + <td>Config</td> + <td>Total</td> </tr> - {% for dict_unit in stats_list %} - <tr> - <td class="sortable"><a href="{% url Bcfg2.Server.Reports.reports.views.client_detail dict_unit.name%}/">{{dict_unit.name}}</a></td> - <td class="sortable">{{dict_unit.parse}}</td> - <td class="sortable">{{dict_unit.probe}}</td> - <td class="sortable">{{dict_unit.inventory}}</td> - <td class="sortable">{{dict_unit.install}}</td> - <td class="sortable">{{dict_unit.config}}</td> - <td class="sortable">{{dict_unit.total}}</td> + {% for metric in metrics|dictsort:"name" %} + <tr class='{% cycle listview,listview_alt %}'> + <td><a style='font-size: 100%' + href="{% url reports_client_detail hostname=metric.name %}">{{ metric.name }}</a></td> + {% for mitem in metric|build_metric_list %} + <td>{{ mitem }}</td> + {% endfor %} </tr> {% endfor %} </table> - </center> + {% else %} + <p>No metric data available</p> + {% endif %} +</div> {% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/index.html b/src/lib/Server/Reports/reports/templates/index.html deleted file mode 100644 index 002a3f770..000000000 --- a/src/lib/Server/Reports/reports/templates/index.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "base.html" %} - -{% block pagebanner %} - <div class="header"> - <h1>BCFG Reports</h1> - {% comment %} <span class="notebox">Report Run @ {% now "F j, Y P"%}</span>{% endcomment %} - </div> - <br/> -{% endblock %} -{% block content %} -<h1>Welcome to the Bcfg2 Reporting System</h1> -<p> -Please use the links at the left to navigate. -</p> -{% endblock %} diff --git a/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html b/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html new file mode 100644 index 000000000..6b57baf6a --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html @@ -0,0 +1,13 @@ +{% spaceless %} +{% if filters %} +{% for filter, filter_url in filters %} + {% if forloop.first %} + <div class="filter_bar">Active filters (click to remove): + {% endif %} + <a href='{{ filter_url }}'>{{ filter|capfirst }}</a>{% if not forloop.last %}, {% endif %} + {% if forloop.last %} + </div> + {% endif %} +{% endfor %} +{% endif %} +{% endspaceless %} diff --git a/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc b/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc new file mode 100644 index 000000000..8f2dec1dc --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc @@ -0,0 +1,38 @@ +{% load bcfg2_tags %} +<div class='interaction_history_widget'> + <table cellpadding="3"> + <tr id='table_list_header' class='listview'> + <td class='left_column'>Timestamp</td> + {% if not client %} + <td class='right_column_wide'>Client</td> + {% endif %} + <td class='right_column' style='width:75px'>State</td> + <td class='right_column_narrow'>Good</td> + <td class='right_column_narrow'>Bad</td> + <td class='right_column_narrow'>Modified</td> + <td class='right_column_narrow'>Extra</td> + <td class='right_column_wide'>Server</td> + </tr> + {% for entry in entry_list %} + <tr class='{% cycle listview,listview_alt %}'> + <td class='left_column'><a href='{% url reports_client_detail_pk hostname=entry.client.name, pk=entry.id %}'>{{ entry.timestamp|date:"Y-m-d\&\n\b\s\p\;H:i"|safe }}</a></td> + {% if not client %} + <td class='right_column_wide'><a href='{% add_url_filter hostname=entry.client.name %}'>{{ entry.client.name }}</a></td> + {% endif %} + <td class='right_column' style='width:75px'><a href='{% add_url_filter state=entry.state %}' + {% ifequal entry.state 'dirty' %}class='dirty-lineitem'{% endifequal %}>{{ entry.state }}</a></td> + <td class='right_column_narrow'>{{ entry.goodcount }}</td> + <td class='right_column_narrow'>{{ entry.bad_entry_count }}</td> + <td class='right_column_narrow'>{{ entry.modified_entry_count }}</td> + <td class='right_column_narrow'>{{ entry.extra_entry_count }}</td> + <td class='right_column_wide'> + {% if entry.server %} + <a href='{% add_url_filter server=entry.server %}'>{{ entry.server }}</a> + {% else %} + + {% endif %} + </td> + </tr> + {% endfor %} + </table> +</div> diff --git a/src/lib/Server/Reports/reports/templates/widgets/page_bar.html b/src/lib/Server/Reports/reports/templates/widgets/page_bar.html new file mode 100644 index 000000000..aa0def83e --- /dev/null +++ b/src/lib/Server/Reports/reports/templates/widgets/page_bar.html @@ -0,0 +1,23 @@ +{% spaceless %} +{% for page, page_url in pager %} + {% if forloop.first %} + <div class="page_bar"> + {% if prev_page %}<a href="{{ prev_page }}">< Prev</a><span> </span>{% endif %} + {% if first_page %}<a href="{{ first_page }}">1</a><span> ... </span>{% endif %} + {% endif %} + {% ifequal page current_page %} + <span class='nav_bar_current'>{{ page }}</span> + {% else %} + <a href="{{ page_url }}">{{ page }}</a> + {% endifequal %} + {% if forloop.last %} + {% if last_page %}<span> ... </span><a href="{{ last_page }}">{{ total_pages }}</a><span> </span>{% endif %} + {% if next_page %}<a href="{{ next_page }}">Next ></a><span> </span>{% endif %} + |{% for limit, limit_url in page_limits %} <a href="{{ limit_url }}">{{ limit }}</a>{% endfor %} + </div> + {% else %} + <span> </span> + {% endif %} +{% endfor %} +{% endspaceless %} +<!-- {{ path }} --> diff --git a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py b/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py new file mode 100644 index 000000000..2c27aab04 --- /dev/null +++ b/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py @@ -0,0 +1,239 @@ +from django import template +from django.core.urlresolvers import resolve, reverse, Resolver404, NoReverseMatch +from django.utils.encoding import smart_unicode, smart_str +from datetime import datetime, timedelta +from Bcfg2.Server.Reports.utils import filter_list + +register = template.Library() + +__PAGE_NAV_LIMITS__ = (10, 25, 50, 100) + +@register.inclusion_tag('widgets/page_bar.html', takes_context=True) +def page_navigator(context): + """ + Creates paginated links. + + Expects the context to be a RequestContext and views.prepare_paginated_list() + to have populated page information. + """ + fragment = dict() + try: + path = context['request'].path + total_pages = int(context['total_pages']) + records_per_page = int(context['records_per_page']) + except KeyError, e: + return fragment + except ValueError, e: + return fragment + + if total_pages < 2: + return {} + + try: + view, args, kwargs = resolve(path) + current_page = int(kwargs.get('page_number',1)) + fragment['current_page'] = current_page + fragment['page_number'] = current_page + fragment['total_pages'] = total_pages + fragment['records_per_page'] = records_per_page + if current_page > 1: + kwargs['page_number'] = current_page - 1 + fragment['prev_page'] = reverse(view, args=args, kwargs=kwargs) + if current_page < total_pages: + kwargs['page_number'] = current_page + 1 + fragment['next_page'] = reverse(view, args=args, kwargs=kwargs) + + view_range = 5 + if total_pages > view_range: + pager_start = current_page - 2 + pager_end = current_page + 2 + if pager_start < 1: + pager_end += (1 - pager_start) + pager_start = 1 + if pager_end > total_pages: + pager_start -= (pager_end - total_pages) + pager_end = total_pages + else: + pager_start = 1 + pager_end = total_pages + + if pager_start > 1: + kwargs['page_number'] = 1 + fragment['first_page'] = reverse(view, args=args, kwargs=kwargs) + if pager_end < total_pages: + kwargs['page_number'] = total_pages + fragment['last_page'] = reverse(view, args=args, kwargs=kwargs) + + pager = [] + for page in range(pager_start, int(pager_end) + 1): + kwargs['page_number'] = page + pager.append( (page, reverse(view, args=args, kwargs=kwargs)) ) + + kwargs['page_number'] = 1 + page_limits = [] + for limit in __PAGE_NAV_LIMITS__: + kwargs['page_limit'] = limit + page_limits.append( (limit, reverse(view, args=args, kwargs=kwargs)) ) + # resolver doesn't like this + del kwargs['page_number'] + del kwargs['page_limit'] + page_limits.append( ('all', reverse(view, args=args, kwargs=kwargs) + "|all") ) + + fragment['pager'] = pager + fragment['page_limits'] = page_limits + + except Resolver404: + path = "404" + except NoReverseMatch, nr: + path = "NoReverseMatch: %s" % nr + except ValueError: + path = "ValueError" + #FIXME - Handle these + + fragment['path'] = path + return fragment + +@register.inclusion_tag('widgets/filter_bar.html', takes_context=True) +def filter_navigator(context): + try: + path = context['request'].path + view, args, kwargs = resolve(path) + + # Strip any page limits and numbers + if 'page_number' in kwargs: + del kwargs['page_number'] + if 'page_limit' in kwargs: + del kwargs['page_limit'] + + filters = [] + for filter in filter_list: + if filter in kwargs: + myargs = kwargs.copy() + del myargs[filter] + filters.append( (filter, reverse(view, args=args, kwargs=myargs) ) ) + filters.sort(lambda x,y: cmp(x[0], y[0])) + return { 'filters': filters } + except (Resolver404, NoReverseMatch, ValueError, KeyError): + pass + return dict() + +def _subtract_or_na(mdict, x, y): + """ + Shortcut for build_metric_list + """ + try: + return round(mdict[x] - mdict[y], 4) + except: + return "n/a" + +@register.filter +def build_metric_list(mdict): + """ + Create a list of metric table entries + + Moving this here it simplify the view. Should really handle the case where these + are missing... + """ + td_list = [] + # parse + td_list.append( _subtract_or_na(mdict, 'config_parse', 'config_download')) + #probe + td_list.append( _subtract_or_na(mdict, 'probe_upload', 'start')) + #inventory + td_list.append( _subtract_or_na(mdict, 'inventory', 'initialization')) + #install + td_list.append( _subtract_or_na(mdict, 'install', 'inventory')) + #cfg download & parse + td_list.append( _subtract_or_na(mdict, 'config_parse', 'probe_upload')) + #total + td_list.append( _subtract_or_na(mdict, 'finished', 'start')) + return td_list + +@register.filter +def isstale(timestamp, entry_max=None): + """ + Check for a stale timestamp + + Compares two timestamps and returns True if the + difference is greater then 24 hours. + """ + if not entry_max: + entry_max = datetime.now() + return entry_max - timestamp > timedelta(hours=24) + +@register.filter +def sort_interactions_by_name(value): + """ + Sort an interaction list by client name + """ + inters = list(value) + inters.sort(lambda a,b: cmp(a.client.name, b.client.name)) + return inters + +class AddUrlFilter(template.Node): + def __init__(self, filter_name, filter_value): + self.filter_name = filter_name + self.filter_value = filter_value + self.fallback_view = 'Bcfg2.Server.Reports.reports.views.render_history_view' + + def render(self, context): + link = '#' + try: + path = context['request'].path + view, args, kwargs = resolve(path) + filter_value = self.filter_value.resolve(context, True) + if filter_value: + filter_name = smart_str(self.filter_name) + filter_value = smart_unicode(filter_value) + kwargs[filter_name] = filter_value + # These two don't make sense + if filter_name == 'server' and 'hostname' in kwargs: + del kwargs['hostname'] + elif filter_name == 'hostname' and 'server' in kwargs: + del kwargs['server'] + try: + link = reverse(view, args=args, kwargs=kwargs) + except NoReverseMatch, rm: + link = reverse(self.fallback_view, args=None, + kwargs={ filter_name: filter_value }) + except NoReverseMatch, rm: + raise rm + except (Resolver404, ValueError), e: + pass + return link + +@register.tag +def add_url_filter(parser, token): + """ + Return a url with the filter added to the current view. + + Takes a new filter and resolves the current view with the new filter + applied. Resolves to Bcfg2.Server.Reports.reports.views.client_history + by default. + + {% add_url_filter server=interaction.server %} + """ + try: + tag_name, filter_pair = token.split_contents() + filter_name, filter_value = filter_pair.split('=', 1) + filter_name = filter_name.strip() + filter_value = parser.compile_filter(filter_value) + except ValueError: + raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0] + if not filter_name or not filter_value: + raise template.TemplateSyntaxError, "argument should be a filter=value pair" + + return AddUrlFilter(filter_name, filter_value) + +@register.filter +def sortwell(value): + """ + Sorts a list(or evaluates queryset to list) of bad, extra, or modified items in the best + way for presentation + """ + + configItems = list(value) + configItems.sort(lambda x,y: cmp(x.entry.name, y.entry.name)) + configItems.sort(lambda x,y: cmp(x.entry.kind, y.entry.kind)) + return configItems + diff --git a/src/lib/Server/Reports/reports/templatetags/django_templating_sigh.py b/src/lib/Server/Reports/reports/templatetags/django_templating_sigh.py deleted file mode 100644 index c0d05d2c1..000000000 --- a/src/lib/Server/Reports/reports/templatetags/django_templating_sigh.py +++ /dev/null @@ -1,41 +0,0 @@ -from django import template -#from Bcfg2.Server.Reports.reports.models import Client, Interaction, Bad, Modified, Extra - -register = template.Library() - -def set_interaction(parser, token): - try: - # Splitting by None == splitting by spaces. - tag_name, format_string = token.contents.split(None, 1) - except ValueError: - raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0] - if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): - raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name - return SetInteraction(format_string[1:-1]) - -def sortwell(value): - "sorts a list(or evaluates queryset to list) of bad, extra, or modified items in the best" - "way for presentation" - configItems = list(value) - configItems.sort(lambda x,y: cmp(x.entry.name, y.entry.name)) - configItems.sort(lambda x,y: cmp(x.entry.kind, y.entry.kind)) - return configItems -def sortname(value): - "sorts a list( or evaluates queryset) by name" - configItems = list(value) - configItems.sort(lambda x,y: cmp(x.name, y.name)) - return configItems - -class SetInteraction(template.Node): - def __init__(self, times): - self.times = times#do soemthing to select different interaction with host? - def render(self, context): - try: - context['interaction'] = context['client_interaction_dict'][context['client'].id] - except:#I don't fully know what the implications of this are. - pass - return '' - -register.tag('set_interaction', set_interaction) -register.filter('sortwell', sortwell) -register.filter('sortname', sortname) diff --git a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py b/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py index 083b83a73..43dafb262 100644 --- a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py +++ b/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py @@ -1,4 +1,7 @@ from django import template +from django.utils.encoding import smart_unicode, smart_str +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe register = template.Library() @@ -11,15 +14,28 @@ try: except: colorize = False -def syntaxhilight(value, arg="diff"): - '''Returns a syntax-hilighted version of Code; requires code/language arguments''' +@register.filter +def syntaxhilight(value, arg="diff", autoescape=None): + """ + Returns a syntax-hilighted version of Code; requires code/language arguments + """ + + if autoescape: + value = conditional_escape(value) + arg = conditional_escape(arg) + if colorize: try: + output = u'<style type="text/css">' \ + + smart_unicode(HtmlFormatter().get_style_defs('.highlight')) \ + + u'</style>' + lexer = get_lexer_by_name(arg) - return highlight(value, lexer, HtmlFormatter()) + output += highlight(value, lexer, HtmlFormatter()) + return mark_safe(output) except: return value else: - return value + return mark_safe(u'<div class="note-box">Tip: Install pygments for highlighting</div><pre>%s</pre>' % value) +syntaxhilight.needs_autoescape = True -register.filter('syntaxhilight', syntaxhilight) diff --git a/src/lib/Server/Reports/reports/urls.py b/src/lib/Server/Reports/reports/urls.py new file mode 100644 index 000000000..9970d26a1 --- /dev/null +++ b/src/lib/Server/Reports/reports/urls.py @@ -0,0 +1,55 @@ +from django.conf.urls.defaults import * +from django.core.urlresolvers import reverse, NoReverseMatch +from django.http import HttpResponsePermanentRedirect +from Bcfg2.Server.Reports.utils import filteredUrls, paginatedUrls, timeviewUrls + +def newRoot(request): + try: + grid_view = reverse('reports_grid_view') + except NoReverseMatch: + grid_view = '/grid' + return HttpResponsePermanentRedirect(grid_view) + +urlpatterns = patterns('Bcfg2.Server.Reports.reports', + (r'^$', newRoot), + + url(r'^manage/?$', 'views.client_manage', name='reports_client_manage'), + url(r'^client/(?P<hostname>\S+)/(?P<pk>\d+)/?$', 'views.client_detail', name='reports_client_detail_pk'), + url(r'^client/(?P<hostname>\S+)/?$', 'views.client_detail', name='reports_client_detail'), + url(r'^elements/(?P<type>\w+)/(?P<pk>\d+)/?$', 'views.config_item', name='reports_item'), +) + +urlpatterns += patterns('Bcfg2.Server.Reports.reports', + *timeviewUrls( + (r'^grid/?$', 'views.client_index', None, 'reports_grid_view'), + (r'^summary/?$', 'views.display_summary', None, 'reports_summary'), + (r'^timing/?$', 'views.display_timing', None, 'reports_timing'), + (r'^elements/(?P<type>\w+)/?$', 'views.config_item_list', None, 'reports_item_list'), +)) + +urlpatterns += patterns('Bcfg2.Server.Reports.reports', + *filteredUrls(*timeviewUrls( + (r'^detailed/?$', + 'views.client_detailed_list', None, 'reports_detailed_list') +))) + +urlpatterns += patterns('Bcfg2.Server.Reports.reports', + *paginatedUrls( *filteredUrls( + (r'^history/?$', + 'views.render_history_view', None, 'reports_history'), + (r'^history/(?P<hostname>[\w\-\.]+)/?$', + 'views.render_history_view', None, 'reports_client_history'), +))) + + # Uncomment this for admin: + #(r'^admin/', include('django.contrib.admin.urls')), + + +## Uncomment this section if using authentication +#urlpatterns += patterns('', +# (r'^login/$', 'django.contrib.auth.views.login', +# {'template_name': 'auth/login.html'}), +# (r'^logout/$', 'django.contrib.auth.views.logout', +# {'template_name': 'auth/logout.html'}) +# ) + diff --git a/src/lib/Server/Reports/reports/views.py b/src/lib/Server/Reports/reports/views.py index d159dcd43..64617ce70 100644 --- a/src/lib/Server/Reports/reports/views.py +++ b/src/lib/Server/Reports/reports/views.py @@ -1,354 +1,379 @@ -# Create your views here. -#from django.shortcuts import get_object_or_404, render_to_response -from django.template import Context, loader -from django.http import HttpResponseRedirect, HttpResponse +""" +Report views + +Functions to handle all of the reporting views. +""" +from django.template import Context, RequestContext, loader +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError, Http404 from django.shortcuts import render_to_response, get_object_or_404 -from Bcfg2.Server.Reports.reports.models import Client, Interaction, Entries, Entries_interactions, Performance, Reason -from Bcfg2.Server.Reports.reports.models import TYPE_BAD, TYPE_MODIFIED, TYPE_EXTRA -from datetime import datetime, timedelta -from time import strptime +from django.core.urlresolvers import resolve, reverse, Resolver404, NoReverseMatch from django.db import connection from django.db.backends import util -from django.contrib.auth.decorators import login_required -def index(request): - return render_to_response('index.html') +from Bcfg2.Server.Reports.reports.models import * +from datetime import datetime, timedelta +from time import strptime +import sys -def config_item_modified(request, eyedee =None, timestamp = 'now', type=TYPE_MODIFIED): - #if eyedee = None, dump with a 404 - timestamp = timestamp.replace("@"," ") - if type == TYPE_MODIFIED: - mod_or_bad = "modified" - else: - mod_or_bad = "bad" - - item = get_object_or_404(Entries_interactions, id=eyedee) - #if everything is blank except current_exists, do something special - cursor = connection.cursor() - if timestamp == 'now': - cursor.execute("select client_id from reports_interaction, reports_entries_interactions, reports_client "+ - "WHERE reports_client.current_interaction_id = reports_entries_interactions.interaction_id "+ - "AND reports_entries_interactions.interaction_id = reports_interaction.id "+ - "AND reports_entries_interactions.entry_id = %s " + - "AND reports_entries_interactions.reason_id = %s", [item.entry.id, item.reason.id]) - associated_client_list = Client.objects.active(timestamp).filter(id__in=[x[0] for x in cursor.fetchall()]) - else: - interact_queryset = Interaction.objects.interaction_per_client(timestamp) - interactionlist = [] - [interactionlist.append(x.id) for x in interact_queryset] - if not interactionlist == []: - cursor.execute("select client_id from reports_interaction, reports_entries_interactions, reports_client "+ - "WHERE reports_entries_interactions.interaction_id IN %s "+ - "AND reports_entries_interactions.interaction_id = reports_interaction.id "+ - "AND reports_entries_interactions.entry_id = %s " + - "AND reports_entries_interactions.reason_id = %s ", [interactionlist, item.entry_id, item.reason.id]) - associated_client_list = Client.objects.active(timestamp).filter(id__in=[x[0] for x in cursor.fetchall()]) - else: - associated_client_list = [] +class PaginationError(Exception): + """This error is raised when pagination cannot be completed.""" + pass - if timestamp == 'now': - timestamp = datetime.now().isoformat('@') +def server_error(request): + """ + 500 error handler. - return render_to_response('config_items/index.html', {'item':item, - 'mod_or_bad':mod_or_bad, - 'associated_client_list':associated_client_list, - 'timestamp' : timestamp, - 'timestamp_date' : timestamp[:10], - 'timestamp_time' : timestamp[11:19]}) + For now always return the debug response. Mailing isn't appropriate here. + """ + from django.views import debug + return debug.technical_500_response(request, *sys.exc_info()) -def config_item_bad(request, eyedee = None, timestamp = 'now'): - return config_item_modified(request, eyedee, timestamp, TYPE_BAD) +def timeview(fn): + """ + Setup a timeview view -def bad_item_index(request, timestamp = 'now', type=TYPE_BAD): - timestamp = timestamp.replace("@"," ") - if type == TYPE_BAD: - mod_or_bad = "bad" - else: - mod_or_bad = "modified" + Handles backend posts from the calendar and converts date pieces + into a 'timestamp' parameter + + """ + def _handle_timeview(request, **kwargs): + """Send any posts back.""" + if request.method == 'POST': + cal_date = request.POST['cal_date'] + try: + fmt = "%Y/%m/%d" + if cal_date.find(' ') > -1: + fmt += " %H:%M" + timestamp = datetime(*strptime(cal_date, fmt)[0:6]) + view, args, kw = resolve(request.path) + kw['year'] = "%0.4d" % timestamp.year + kw['month'] = "%02.d" % timestamp.month + kw['day'] = "%02.d" % timestamp.day + if cal_date.find(' ') > -1: + kw['hour'] = timestamp.hour + kw['minute'] = timestamp.minute + return HttpResponseRedirect(reverse(view, args=args, kwargs=kw)) + except KeyError: + pass + except: + pass + # FIXME - Handle this + + """Extract timestamp from args.""" + timestamp = None + try: + timestamp = datetime(int(kwargs.pop('year')), int(kwargs.pop('month')), + int(kwargs.pop('day')), int(kwargs.pop('hour', 0)), + int(kwargs.pop('minute', 0)), 0) + kwargs['timestamp'] = timestamp + except KeyError: + pass + except: + raise + return fn(request, **kwargs) + + return _handle_timeview + +def config_item(request, pk, type="bad"): + """ + Display a single entry. + + Dispalys information about a single entry. + + """ + item = get_object_or_404(Entries_interactions, id=pk) + timestamp=item.interaction.timestamp + time_start=item.interaction.timestamp.replace(\ + hour=0, minute=0, second=0, microsecond=0) + time_end=time_start + timedelta(days=1) + + todays_data = Interaction.objects.filter(\ + timestamp__gte=time_start,\ + timestamp__lt=time_end) + shared_entries = Entries_interactions.objects.filter(entry=item.entry,\ + reason=item.reason, type=item.type, + interaction__in=[x['id']\ + for x in todays_data.values('id')]) + + associated_list = Interaction.objects.filter(id__in=[x['interaction']\ + for x in shared_entries.values('interaction')])\ + .order_by('client__name','timestamp').select_related().all() + + return render_to_response('config_items/item.html', + {'item':item, + 'isextra': item.type == TYPE_EXTRA, + 'mod_or_bad': type, + 'associated_list':associated_list, + 'timestamp' : timestamp}, + context_instance=RequestContext(request)) + +@timeview +def config_item_list(request, type, timestamp=None): + """Render a listing of affected elements""" + mod_or_bad = type.lower() + type = convert_entry_type_to_id(type) + if type < 0: + raise Http404 - current_clients = [c.current_interaction - for c in Client.objects.active(timestamp)] + current_clients = Interaction.objects.get_interaction_per_client_ids(timestamp) item_list_dict = {} - for x in Entries_interactions.objects.select_related().filter(interaction__in=current_clients, type=type).distinct(): + seen = dict() + for x in Entries_interactions.objects.filter(interaction__in=current_clients, type=type).select_related(): + if (x.entry, x.reason) in seen: + continue + seen[(x.entry, x.reason)] = 1 if item_list_dict.get(x.entry.kind, None): item_list_dict[x.entry.kind].append(x) else: item_list_dict[x.entry.kind] = [x] - item_list_pseudodict = item_list_dict.items() - if timestamp == 'now': - timestamp = datetime.now().isoformat('@') + for kind in item_list_dict: + item_list_dict[kind].sort(lambda a,b: cmp(a.entry.name, b.entry.name)) - return render_to_response('config_items/listing.html', {'item_list_pseudodict':item_list_pseudodict, + return render_to_response('config_items/listing.html', {'item_list_dict':item_list_dict, 'mod_or_bad':mod_or_bad, - 'timestamp' : timestamp, - 'timestamp_date' : timestamp[:10], - 'timestamp_time' : timestamp[11:19]}) -def modified_item_index(request, timestamp = 'now'): - return bad_item_index(request, timestamp, TYPE_MODIFIED) - -def client_index(request, timestamp = 'now'): - timestamp = timestamp.replace("@"," ") - - c_dict = dict() - [c_dict.__setitem__(cl.id,cl.name) for cl in Client.objects.active(timestamp).order_by('name')] - - list = [] - for inter in Interaction.objects.interaction_per_client(timestamp): - if inter.client_id in c_dict: - list.append([c_dict[inter.client_id], inter]) - list.sort(lambda a,b: cmp(a[0], b[0])) - half_list = len(list) / 2 - - if timestamp == 'now': - timestamp = datetime.now().isoformat('@') + 'timestamp' : timestamp}, + context_instance=RequestContext(request)) + +@timeview +def client_index(request, timestamp=None): + """ + Render a grid view of active clients. + + Keyword parameters: + timestamp -- datetime objectto render from + + """ + list = Interaction.objects.interaction_per_client(timestamp).select_related()\ + .order_by("client__name").all() + return render_to_response('clients/index.html', - {'inter_list': list, - 'half_list': half_list, - 'timestamp' : timestamp, - 'timestamp_date' : timestamp[:10], - 'timestamp_time' : timestamp[11:19]}) + { 'inter_list': list, 'timestamp' : timestamp}, + context_instance=RequestContext(request)) -def client_detailed_list(request, **kwargs): +@timeview +def client_detailed_list(request, timestamp=None, **kwargs): """ Provides a more detailed list view of the clients. Allows for extra - filters to be passed in. Somewhat clunky now that dates are allowed. + filters to be passed in. """ - context = dict(path=request.path) - timestamp = 'now' - entry_max = datetime.now() - if request.GET: - context['qsa']='?%s' % request.GET.urlencode() - if request.GET.has_key('date1') and request.GET.has_key('time'): - timestamp = "%s %s" % (request.GET['date1'],request.GET['time']) - entry_max = datetime(*strptime(timestamp, "%Y-%m-%d %H:%M:%S")[0:6]) - client_list = Client.objects.active(timestamp).order_by('name') - if timestamp == 'now': - timestamp = datetime.now().isoformat('@') - context['timestamp_date'] = timestamp[:10] - context['timestamp_time'] = timestamp[11:19] - - interactions = Interaction.objects.interaction_per_client(timestamp) - if 'state' in kwargs and kwargs['state']: - context['state'] = kwargs['state'] - interactions=interactions.filter(state__exact=kwargs['state']) - if 'server' in kwargs and kwargs['server']: - interactions=interactions.filter(server__exact=kwargs['server']) - context['server'] = kwargs['server'] - # build the entry list from available clients - c_dict = dict() - [c_dict.__setitem__(cl.id,cl.name) for cl in client_list] - - entry_list = [] - for inter in interactions: - if inter.client_id in c_dict: - entry_list.append([c_dict[inter.client_id], inter, \ - entry_max - inter.timestamp > timedelta(hours=24)]) - entry_list.sort(lambda a,b: cmp(a[0], b[0])) - ''' - if(datetime.now()-self.timestamp > timedelta(hours=25) ): - return True - else: - return False - ''' - - context['entry_list'] = entry_list - return render_to_response('clients/detailed-list.html', context) + kwargs['interaction_base'] = Interaction.objects.interaction_per_client(timestamp).select_related() + kwargs['orderby'] = "client__name" + kwargs['page_limit'] = 0 + return render_history_view(request, 'clients/detailed-list.html', **kwargs) def client_detail(request, hostname = None, pk = None): - #SETUP error pages for when you specify a client or interaction that doesn't exist + context = dict() client = get_object_or_404(Client, name=hostname) if(pk == None): - interaction = client.current_interaction + context['interaction'] = client.current_interaction + return render_history_view(request, 'clients/detail.html', page_limit=5, + client=client, context=context) else: - interaction = client.interactions.get(pk=pk)#can this be a get object or 404? - return render_to_response('clients/detail.html', {'client': client, 'interaction': interaction}) + context['interaction'] = client.interactions.get(pk=pk) + return render_history_view(request, 'clients/detail.html', page_limit=5, + client=client, maxdate=context['interaction'].timestamp, context=context) -def client_manage(request, hostname = None): - #SETUP error pages for when you specify a client or interaction that doesn't exist - client = get_object_or_404(Client, name=hostname) - currenttime = datetime.now().isoformat('@') - if client.expiration != None: - message = ("This client currently has an expiration date of %s. " - "Reports after %s will not include data for this host " - "You may change this if you wish by selecting a new " - "time, earlier or later." - % (client.expiration, client.expiration)) - else: - message = ("This client is currently active and displayed. You " - "may choose a date after which this client will no " - "longer appear in reports.") +def client_manage(request): + """Manage client expiration""" + message = '' if request.method == 'POST': - date = request.POST['date1'] - time = request.POST['time'] try: - timestamp = datetime(*(strptime(date+"@"+time, "%Y-%m-%d@%H:%M:%S")[0:6])) - except ValueError: - timestamp = None - if timestamp == None: - message = "Invalid removal date, please try again using the format: yyyy-mm-dd hh:mm:ss." - else: - client.expiration = timestamp + client_name = request.POST.get('client_name', None) + client_action = request.POST.get('client_action', None) + client = Client.objects.get(name=client_name) + if client_action == 'expire': + client.expiration = datetime.now(); + client.save() + message = "Expiration for %s set to %s." % \ + (client_name, client.expiration.strftime("%Y-%m-%d %H:%M:%S")) + elif client_action == 'unexpire': + client.expiration = None; client.save() - message = "Expiration for client set to %s." % client.expiration - return render_to_response('clients/manage.html', {'client': client, 'message': message, - 'timestamp_date' : currenttime[:10], - 'timestamp_time' : currenttime[11:19]}) - -def display_sys_view(request, timestamp = 'now'): - client_lists = prepare_client_lists(request, timestamp) - return render_to_response('displays/sys_view.html', client_lists) - -def display_summary(request, timestamp = 'now'): - - client_lists = prepare_client_lists(request, timestamp) - #this returns timestamp and the timestamp parts too - return render_to_response('displays/summary.html', client_lists) - -def display_timing(request, timestamp = 'now'): - #We're going to send a list of dictionaries. Each dictionary will be a row in the table - #+------+-------+----------------+-----------+---------+----------------+-------+ - #| name | parse | probe download | inventory | install | cfg dl & parse | total | - #+------+-------+----------------+-----------+---------+----------------+-------+ - client_list = Client.objects.active(timestamp.replace("@"," ")).order_by('name') - stats_list = [] - - if not timestamp == 'now': - results = Performance.objects.performance_per_client(timestamp.replace("@"," ")) + message = "%s is now active." % client_name else: - results = Performance.objects.performance_per_client() - timestamp = datetime.now().isoformat('@') - - for client in client_list:#Go explicitly to an interaction ID! (new item in dictionary) + message = "Missing action" + except Client.DoesNotExist: + if not client_name: + client_name = "<none>" + message = "Couldn't find client \"%s\"" % client_name + + return render_to_response('clients/manage.html', + {'clients': Client.objects.order_by('name').all(), 'message': message}, + context_instance=RequestContext(request)) + +@timeview +def display_summary(request, timestamp=None): + """ + Display a summary of the bcfg2 world + """ + query = Interaction.objects.interaction_per_client(timestamp).select_related() + node_count = query.count() + recent_data = query.all() + if not timestamp: + timestamp = datetime.now() + + collected_data = dict(clean=[],bad=[],modified=[],extra=[],stale=[],pings=[]) + for node in recent_data: + if timestamp - node.timestamp > timedelta(hours=24): + collected_data['stale'].append(node) + # If stale check for uptime try: - d = results[client.name] - except KeyError: - d = {} + if node.client.pings.latest().status == 'N': + collected_data['pings'].append(node) + except Ping.DoesNotExist: + collected_data['pings'].append(node) + continue + if node.bad_entry_count() > 0: + collected_data['bad'].append(node) + else: + collected_data['clean'].append(node) + if node.modified_entry_count() > 0: + collected_data['modified'].append(node) + if node.extra_entry_count() > 0: + collected_data['extra'].append(node) + + # label, header_text, node_list + summary_data = [] + get_dict = lambda name, label: { 'name': name, + 'nodes': collected_data[name], + 'label': label } + if len(collected_data['clean']) > 0: + summary_data.append( get_dict('clean', 'nodes are clean.') ) + if len(collected_data['bad']) > 0: + summary_data.append( get_dict('bad', 'nodes are bad.') ) + if len(collected_data['modified']) > 0: + summary_data.append( get_dict('modified', 'nodes were modified.') ) + if len(collected_data['extra']) > 0: + summary_data.append( get_dict('extra', + 'nodes have extra configurations.') ) + if len(collected_data['stale']) > 0: + summary_data.append( get_dict('stale', + 'nodes did not run within the last 24 hours.') ) + if len(collected_data['pings']) > 0: + summary_data.append( get_dict('pings', + 'are down.') ) + + return render_to_response('displays/summary.html', + {'summary_data': summary_data, 'node_count': node_count, + 'timestamp': timestamp}, + context_instance=RequestContext(request)) + +@timeview +def display_timing(request, timestamp=None): + mdict = dict() + inters = Interaction.objects.interaction_per_client(timestamp).select_related().all() + [mdict.__setitem__(inter, {'name': inter.client.name}) \ + for inter in inters] + for metric in Performance.objects.filter(interaction__in=mdict.keys()).all(): + for i in metric.interaction.all(): + mdict[i][metric.metric] = metric.value + return render_to_response('displays/timing.html', + {'metrics': mdict.values(), 'timestamp': timestamp}, + context_instance=RequestContext(request)) + + +def render_history_view(request, template='clients/history.html', **kwargs): + """ + Provides a detailed history of a clients interactions. + + Renders a detailed history of a clients interactions. Allows for various + filters and settings. Automatically sets pagination data into the context. + + Keyword arguments: + interaction_base -- Interaction QuerySet to build on + (default Interaction.objects) + context -- Additional context data to render with + page_number -- Page to display (default 1) + page_limit -- Number of results per page, if 0 show all (default 25) + client -- Client object to render + hostname -- Client hostname to lookup and render. Returns a 404 if + not found + server -- Filter interactions by server + state -- Filter interactions by state + entry_max -- Most recent interaction to display + orderby -- Sort results using this field - dict_unit = {} - try: - dict_unit["name"] = client.name #node name - except: - dict_unit["name"] = "n/a" - try: - dict_unit["parse"] = round(d["config_parse"] - d["config_download"], 4) #parse - except: - dict_unit["parse"] = "n/a" - try: - dict_unit["probe"] = round(d["probe_upload"] - d["start"], 4) #probe - except: - dict_unit["probe"] = "n/a" - try: - dict_unit["inventory"] = round(d["inventory"] - d["initialization"], 4) #inventory - except: - dict_unit["inventory"] = "n/a" - try: - dict_unit["install"] = round(d["install"] - d["inventory"], 4) #install - except: - dict_unit["install"] = "n/a" - try: - dict_unit["config"] = round(d["config_parse"] - d["probe_upload"], 4)#config download & parse - except: - dict_unit["config"] = "n/a" + """ + + context = kwargs.get('context', dict()) + max_results = int(kwargs.get('page_limit', 25)) + page = int(kwargs.get('page_number', 1)) + + client=kwargs.get('client', None) + if not client and 'hostname' in kwargs: + client = get_object_or_404(Client, name=kwargs['hostname']) + if client: + context['client'] = client + + entry_max = kwargs.get('maxdate', None) + context['entry_max'] = entry_max + + # Either filter by client or limit by clients + iquery = kwargs.get('interaction_base', Interaction.objects) + if client: + iquery = iquery.filter(client__exact=client).select_related() + + if 'orderby' in kwargs and kwargs['orderby']: + iquery = iquery.order_by(kwargs['orderby']) + + if 'state' in kwargs and kwargs['state']: + iquery = iquery.filter(state__exact=kwargs['state']) + if 'server' in kwargs and kwargs['server']: + iquery = iquery.filter(server__exact=kwargs['server']) + + if entry_max: + iquery = iquery.filter(timestamp__lte=entry_max) + + if max_results < 0: + max_results = 1 + entry_list = [] + if max_results > 0: try: - dict_unit["total"] = round(d["finished"] - d["start"], 4) #total - except: - dict_unit["total"] = "n/a" - - stats_list.append(dict_unit) - - return render_to_response('displays/timing.html', {'client_list': client_list, - 'stats_list': stats_list, - 'timestamp' : timestamp, - 'timestamp_date' : timestamp[:10], - 'timestamp_time' : timestamp[11:19]}) - -def display_index(request): - return render_to_response('displays/index.html') - -def prepare_client_lists(request, timestamp = 'now'): - #I suggest we implement "expiration" here. - - timestamp = timestamp.replace("@"," ") - #client_list = Client.objects.all().order_by('name')#change this to order by interaction's state - client_interaction_dict = {} - clean_client_list = [] - bad_client_list = [] - extra_client_list = [] - modified_client_list = [] - stale_up_client_list = [] - #stale_all_client_list = [] - down_client_list = [] - - cursor = connection.cursor() - - interact_queryset = Interaction.objects.interaction_per_client(timestamp) - # or you can specify a time like this: '2007-01-01 00:00:00' - [client_interaction_dict.__setitem__(x.client_id, x) for x in interact_queryset] - client_list = Client.objects.active(timestamp).filter(id__in=client_interaction_dict.keys()).order_by('name') - - [clean_client_list.append(x) for x in Client.objects.active(timestamp).filter(id__in=[y.client_id for y in interact_queryset.filter(state='clean')])] - [bad_client_list.append(x) for x in Client.objects.active(timestamp).filter(id__in=[y.client_id for y in interact_queryset.filter(state='dirty')])] - - client_ping_dict = {} - [client_ping_dict.__setitem__(x,'Y') for x in client_interaction_dict.keys()]#unless we know otherwise... + rec_start, rec_end = prepare_paginated_list(request, context, iquery, page, max_results) + except PaginationError, page_error: + if isinstance(page_error[0], HttpResponse): + return page_error[0] + return HttpResponseServerError(page_error) + context['entry_list'] = iquery.all()[rec_start:rec_end] + else: + context['entry_list'] = iquery.all() + + return render_to_response(template, context, + context_instance=RequestContext(request)) + +def prepare_paginated_list(request, context, paged_list, page=1, max_results=25): + """ + Prepare context and slice an object for pagination. + """ + if max_results < 1: + raise PaginationError, "Max results less then 1" + if paged_list == None: + raise PaginationError, "Invalid object" + + try: + nitems = paged_list.count() + except TypeError: + nitems = len(paged_list) + rec_start = (page - 1) * int(max_results) try: - cursor.execute("select reports_ping.status, x.client_id from (select client_id, MAX(endtime) "+ - "as timer from reports_ping GROUP BY client_id) x, reports_ping where "+ - "reports_ping.client_id = x.client_id AND reports_ping.endtime = x.timer") - [client_ping_dict.__setitem__(x[1], x[0]) for x in cursor.fetchall()] + total_pages = (nitems / int(max_results)) + 1 except: - pass #This is to fix problems when you have only zero records returned - - client_down_ids = [y for y in client_ping_dict.keys() if client_ping_dict[y]=='N'] - if not client_down_ids == []: - [down_client_list.append(x) for x in Client.objects.active(timestamp).filter(id__in=client_down_ids)] - - if (timestamp == 'now' or timestamp == None): - cursor.execute("select client_id, MAX(timestamp) as timestamp from reports_interaction GROUP BY client_id") - results = cursor.fetchall() - for x in results: - if type(x[1]) == type("") or type(x[1]) == type(u""): - ts = util.typecast_timestamp(x[1]) - else: - ts = x[1] - stale_all_client_list = Client.objects.active(timestamp).filter(id__in=[x[0] for x in results if datetime.now() - ts > timedelta(days=1)]) - else: - cursor.execute("select client_id, timestamp, MAX(timestamp) as timestamp from reports_interaction "+ - "WHERE timestamp < %s GROUP BY client_id", [timestamp]) - t = strptime(timestamp,"%Y-%m-%d %H:%M:%S") - datetimestamp = datetime(t[0], t[1], t[2], t[3], t[4], t[5]) - results = cursor.fetchall() - for x in results: - if type(x[1]) == type(""): - x[1] = util.typecast_timestamp(x[1]) - stale_all_client_list = Client.objects.active(timestamp).filter(id__in=[x[0] for x in results if datetimestamp - x[1] > timedelta(days=1)]) - - [stale_up_client_list.append(x) for x in stale_all_client_list if not client_ping_dict[x.id]=='N'] + total_pages = 1 + if page > total_pages: + # If we passed beyond the end send back + try: + view, args, kwargs = resolve(request.path) + kwargs['page_number'] = total_pages + raise PaginationError, HttpResponseRedirect( reverse(view, kwargs=kwargs) ) + except (Resolver404, NoReverseMatch, ValueError): + raise "Accessing beyond last page. Unable to resolve redirect." + + context['total_pages'] = total_pages + context['records_per_page'] = max_results + return (rec_start, rec_start + int(max_results)) - - cursor.execute("SELECT reports_client.id FROM reports_client, reports_interaction, reports_entries_interactions WHERE reports_client.id = reports_interaction.client_id AND reports_client.current_interaction_id = reports_entries_interactions.interaction_id and reports_entries_interactions.type=%s GROUP BY reports_client.id", [TYPE_MODIFIED]) - modified_client_list = Client.objects.active(timestamp).filter(id__in=[x[0] for x in cursor.fetchall()]) - - cursor.execute("SELECT reports_client.id FROM reports_client, reports_interaction, reports_entries_interactions WHERE reports_client.id = reports_interaction.client_id AND reports_client.current_interaction_id = reports_entries_interactions.interaction_id and reports_entries_interactions.type=%s GROUP BY reports_client.id", [TYPE_EXTRA]) - extra_client_list = Client.objects.active(timestamp).filter(id__in=[x[0] for x in cursor.fetchall()]) - - if timestamp == 'now': - timestamp = datetime.now().isoformat('@') - - return {'client_list': client_list, - 'client_interaction_dict':client_interaction_dict, - 'clean_client_list': clean_client_list, - 'bad_client_list': bad_client_list, - 'extra_client_list': extra_client_list, - 'modified_client_list': modified_client_list, - 'stale_up_client_list': stale_up_client_list, - 'stale_all_client_list': stale_all_client_list, - 'down_client_list': down_client_list, - 'timestamp' : timestamp, - 'timestamp_date' : timestamp[:10], - 'timestamp_time' : timestamp[11:19]} diff --git a/src/lib/Server/Reports/settings.py b/src/lib/Server/Reports/settings.py index 59d29114d..81220c0e3 100644 --- a/src/lib/Server/Reports/settings.py +++ b/src/lib/Server/Reports/settings.py @@ -1,3 +1,5 @@ +import django + # Django settings for bcfg2 reports project. from ConfigParser import ConfigParser, NoSectionError, NoOptionError c = ConfigParser() @@ -62,7 +64,9 @@ MEDIA_ROOT = '' # URL that handles the media served from MEDIA_ROOT. # Example: "http://media.lawrence.com" -MEDIA_URL = '' +MEDIA_URL = '/site_media' +if c.has_option('statistics', 'web_prefix'): + MEDIA_URL = c.get('statistics', 'web_prefix').rstrip('/') + MEDIA_URL # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. @@ -109,9 +113,26 @@ TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates". # Always use forward slashes, even on Windows. '/usr/share/python-support/python-django/django/contrib/admin/templates/', - '/usr/share/bcfg2/Reports/templates' + 'Bcfg2.Server.Reports.reports' ) +if django.VERSION[0] == 1 and django.VERSION[1] < 2: + TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.core.context_processors.auth', + 'django.core.context_processors.debug', + 'django.core.context_processors.i18n', + 'django.core.context_processors.media', + 'django.core.context_processors.request' + ) +else: + TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.contrib.auth.context_processors.auth', + 'django.core.context_processors.debug', + 'django.core.context_processors.i18n', + 'django.core.context_processors.media', + 'django.core.context_processors.request' + ) + INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', diff --git a/src/lib/Server/Reports/urls.py b/src/lib/Server/Reports/urls.py index e1326b5ea..5d298c974 100644 --- a/src/lib/Server/Reports/urls.py +++ b/src/lib/Server/Reports/urls.py @@ -1,4 +1,7 @@ from django.conf.urls.defaults import * +from django.http import HttpResponsePermanentRedirect + +handler500 = 'Bcfg2.Server.Reports.reports.views.server_error' from ConfigParser import ConfigParser, NoSectionError, NoOptionError c = ConfigParser() @@ -9,56 +12,15 @@ c.read(['/etc/bcfg2.conf', '/etc/bcfg2-web.conf']) # web_prefix_root is a workaround for the index if c.has_option('statistics', 'web_prefix'): web_prefix = c.get('statistics', 'web_prefix').lstrip('/') - web_prefix_root = web_prefix else: web_prefix = '' - web_prefix_root = '/' urlpatterns = patterns('', - # Example: - # (r'^%sBcfg2.Server.Reports/' % web_prefix, include('Bcfg2.Server.Reports.apps.foo.urls.foo')), - (r'^%s*$' % web_prefix_root,'Bcfg2.Server.Reports.reports.views.index'), - - (r'^%sclients-detailed/state/(?P<state>\w+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'), - (r'^%sclients-detailed/server/(?P<server>[\w\-\.]+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'), - (r'^%sclients-detailed/server/(?P<server>[\w\-\.]+)/(?P<state>[A-Za-z]+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'), - (r'^%sclients-detailed/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'), - (r'^%sclients/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_index'), - (r'^%sclients/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_index'), - (r'^%sclients/(?P<hostname>\S+)/(?P<pk>\d+)/$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_detail'), - (r'^%sclients/(?P<hostname>\S+)/manage/$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_manage'), - (r'^%sclients/(?P<hostname>\S+)/$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_detail'), - (r'^%sclients/(?P<hostname>\S+)$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_detail'), - #hack because hostnames have periods and we still want to append slash - (r'^%sclients/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_index'), - (r'^%sdisplays/sys-view/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_sys_view'), - (r'^%sdisplays/sys-view/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_sys_view'), - (r'^%sdisplays/summary/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_summary'), - (r'^%sdisplays/summary/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_summary'), - (r'^%sdisplays/timing/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_timing'), - (r'^%sdisplays/timing/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_timing'), - (r'^%sdisplays/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.display_index'), - - (r'^%selements/modified/(?P<eyedee>\d+)/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.config_item_modified'), - (r'^%selements/modified/(?P<eyedee>\d+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.config_item_modified'), - (r'^%selements/modified/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01]\ - [0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.modified_item_index'), - (r'^%selements/modified/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.modified_item_index'), - (r'^%selements/bad/(?P<eyedee>\d+)/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.config_item_bad'), - (r'^%selements/bad/(?P<eyedee>\d+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.config_item_bad'), - (r'^%selements/bad/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01]\ - [0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.bad_item_index'), - (r'^%selements/bad/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.bad_item_index'), + (r'^%s' % web_prefix, include('Bcfg2.Server.Reports.reports.urls')) ) - # Uncomment this for admin: - #(r'^%sadmin/' % web_prefix, include('django.contrib.admin.urls')), - - -## Uncomment this section if using authentication -#urlpatterns += patterns('', -# (r'^%slogin/$' % web_prefix, 'django.contrib.auth.views.login', -# {'template_name': 'auth/login.html'}), -# (r'^%slogout/$' % web_prefix, 'django.contrib.auth.views.logout', -# {'template_name': 'auth/logout.html'}) -# ) +urlpatterns += patterns("django.views", + url(r"media/(?P<path>.*)$", "static.serve", { + "document_root": '/Users/tlaszlo/svn/bcfg2/reports/site_media/', + }) +) diff --git a/src/lib/Server/Reports/utils.py b/src/lib/Server/Reports/utils.py index 2ef21e446..b74f09e74 100755 --- a/src/lib/Server/Reports/utils.py +++ b/src/lib/Server/Reports/utils.py @@ -1,7 +1,13 @@ -'''Helper functions for reports''' +"""Helper functions for reports""" +from Bcfg2.Server.Reports.reports.models import TYPE_CHOICES +from django.conf.urls.defaults import * +import re + +"""List of filters provided by filteredUrls""" +filter_list = ('server', 'state') class BatchFetch(object): - '''Fetch Django objects in smaller batches to save memory''' + """Fetch Django objects in smaller batches to save memory""" def __init__(self, obj, step=10000): self.count = 0 @@ -15,8 +21,8 @@ class BatchFetch(object): return self def next(self): - '''Return the next object from our array and fetch from the - database when needed''' + """Return the next object from our array and fetch from the + database when needed""" if self.block_count + self.count - self.step == self.max: raise StopIteration if self.block_count == 0 or self.count == self.step: @@ -28,3 +34,83 @@ class BatchFetch(object): self.count += 1 return self.data[self.count - 1] +def generateUrls(fn): + """ + Parse url tuples and send to functions. + + Decorator for url generators. Handles url tuple parsing + before the actual function is called. + """ + def url_gen(*urls): + results = [] + for url_tuple in urls: + if isinstance(url_tuple, (list, tuple)): + results += fn(*url_tuple) + else: + raise ValueError("Unable to handle compiled urls") + return results + return url_gen + +@generateUrls +def paginatedUrls(pattern, view, kwargs=None, name=None): + """ + Takes a group of url tuples and adds paginated urls. + + Extends a url tuple to include paginated urls. Currently doesn't handle url() compiled + patterns. + + """ + results = [(pattern, view, kwargs, name)] + tail = '' + mtail = re.search('(/+\+?\\*?\??\$?)$', pattern) + if mtail: + tail = mtail.group(1) + pattern = pattern[:len(pattern) - len(tail)] + results += [(pattern + "/(?P<page_number>\d+)" + tail, view, kwargs)] + results += [(pattern + "/(?P<page_number>\d+)\|(?P<page_limit>\d+)" + tail, view, kwargs)] + if not kwargs: + kwargs = dict() + kwargs['page_limit'] = 0 + results += [(pattern + "/?\|(?P<page_limit>all)" + tail, view, kwargs)] + return results + +@generateUrls +def filteredUrls(pattern, view, kwargs=None, name=None): + """ + Takes a url and adds filtered urls. + + Extends a url tuple to include filtered view urls. Currently doesn't + handle url() compiled patterns. + """ + results = [(pattern, view, kwargs, name)] + tail = '' + mtail = re.search('(/+\+?\\*?\??\$?)$', pattern) + if mtail: + tail = mtail.group(1) + pattern = pattern[:len(pattern) - len(tail)] + for filter in ('/state/(?P<state>\w+)', + '/server/(?P<server>[\w\-\.]+)', + '/server/(?P<server>[\w\-\.]+)/(?P<state>[A-Za-z]+)'): + results += [(pattern + filter + tail, view, kwargs)] + return results + +@generateUrls +def timeviewUrls(pattern, view, kwargs=None, name=None): + """ + Takes a url and adds timeview urls + + Extends a url tuple to include filtered view urls. Currently doesn't + handle url() compiled patterns. + """ + results = [(pattern, view, kwargs, name)] + tail = '' + mtail = re.search('(/+\+?\\*?\??\$?)$', pattern) + if mtail: + tail = mtail.group(1) + pattern = pattern[:len(pattern) - len(tail)] + for filter in ('/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})/' + \ + '(?P<hour>\d\d)-(?P<minute>\d\d)', + '/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'): + results += [(pattern + filter + tail, view, kwargs)] + return results + |