
// Begin /library/javascripts/jquery/jquery.FCKEditor/jquery.FCKEditor.SBA.js
//
// This file includes MetaData and FCKEditor, then sets a $(document).ready() to instantiate the FCKEditor into all 
// textareas with class="rte". If one of these textareas has an rteoptions attribute, it will be used in preference 
// to the SBA default options. That means that eval() must return an object literal. 
//
// Revision History:	10/14/2010, SRS:	Major rewrite as to how we interact with other scripts. FCKeditor_OnComplete 
//											is a hook for an event handler, not an internal routine we shouldn't touch.. 
//											This rewrite uses it for the first time. 
//						06/10/2010, SRS:	Added support for top.gSlafSuppressRTE for Section 508 compliance. 
//						02/27/2009, SRS:	Switched from an array of rich text editors, which accumulated references 
//											to pages that were no longer loaded, to a function SlafGetRichTextEditors, 
//											which returns information only about the current page. Installed accessor 
//											functions in each textarea that gets the FCKEditor, for use by other SBA 
//											JavaScripts. Accessor functions have logical names, so that they can be 
//											installed in other form elements, not necessarily FCKEditor-related. 
//						01/24/2009, SRS:	Original implementation (at SBA). Changed the default editor to have a 
//											new SBA-standard toolbar "SBADefault". Also, built an array of currently 
//											instantiated rich text editors in "top". 

// ***************************************************************************************

// Begin manually included /library/javascripts/jquery/jquery.FCKEditor/jquery.MetaData.js
// (so that SBA developers only have to include jquery.FCKEditor.SBA.js). 

/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.meta.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.meta.setType("class")
 * @after $("#one").data().item_id == 1; $("#one")[0].item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.meta.setType("attr", "data")
 * @after $("#one").data().item_id == 1; $("#one")[0].item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.meta.setType("elem", "script")
 * @after $("#one").data().item_id == 1; $("#one")[0].item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see data()
 */

(function($) {
 // settings
 $.meta = {
   type: "class",
   name: "data",
   setType: function(type,name){
     this.type = type;
     this.name = name;
   },
   cre: /({.*})/,
   single: 'data'
 };
 
 // reference to original setArray()
 var setArray = $.fn.setArray;
 
 // define new setArray()
 $.fn.setArray = function(arr){
     return setArray.apply( this, arguments ).each(function(){
       if ( this.nodeType == 9 || $.isXMLDoc(this) || this.metaDone ) return;
       
       var data = "{}";
       
       if ( $.meta.type == "class" ) {
         var m = $.meta.cre.exec( this.className );
         if ( m )
           data = m[1];
       } else if ( $.meta.type == "elem" ) {
        if( !this.getElementsByTagName ) return;
         var e = this.getElementsByTagName($.meta.name);
         if ( e.length )
           data = $.trim(e[0].innerHTML);
       } else if ( this.getAttribute != undefined ) {
         var attr = this.getAttribute( $.meta.name );
         if ( attr )
           data = attr;
       }
       
       if ( !/^{/.test( data ) )
         data = "{" + data + "}";
 
       eval("data = " + data);
 
       if ( $.meta.single )
         this[ $.meta.single ] = data;
       else
         $.extend( this, data );
       
       this.metaDone = true;
     });
 };
 
 /**
  * Returns the metadata object for the first member of the jQuery object.
  *
  * @name data
  * @descr Returns element's metadata object
  * @type jQuery
  * @cat Plugins/Metadata
  */
 $.fn.data = function(){
   return this[0][$.meta.single || "data"];
 };
})(jQuery);

// End manually included /library/javascripts/jquery/jquery.FCKEditor/jquery.MetaData.js
// (so that SBA developers only have to include jquery.FCKEditor.SBA.js). 

// ***************************************************************************************

// Begin manually included /library/javascripts/jquery/jquery.FCKEditor/jquery.FCKEditor.js
// (so that SBA developers only have to include jquery.FCKEditor.SBA.js). 

/*
 ### jQuery FCKEditor Plugin v1.22 - 2008-07-31 ###
 * http://www.fyneworks.com/ - diego@fyneworks.com
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 ###
 Project: http://jquery.com/plugins/project/FCKEditor/
 Website: http://www.fyneworks.com/jquery/FCKEditor/
*/
/*
 USAGE: $('textarea').fck({ path:'/path/to/fck/editor/' }); // initialize FCK editor
 ADVANCED USAGE: $.fck.update(); // update value in textareas of each FCK editor instance
*/

/*# AVOID COLLISIONS #*/
;if(window.jQuery) (function($){
/*# AVOID COLLISIONS #*/

$.extend($, {
 fck:{
  waitFor: 10,// in seconds, how long should we wait for the script to load?
  config: { Config: {} }, // default configuration
  path: '/CFIDE/scripts/ajax/FCKeditor/', // default path to FCKEditor directory		// SBA
  editors: [], // array of editor instances
  loaded: false, // flag indicating whether FCK script is loaded
  intercepted: null, // variable to store intercepted method(s)
  
  // utility method to read contents of FCK editor
  content: function(i, v){
   try{
    var x = FCKeditorAPI.GetInstance(i);
    if(v) x.SetHTML(v);
    return x.GetXHTML(true);
   }catch(e){ return ''; };
  }, // fck.content function
  
  // inspired by Sebastián Barrozo <sbarrozo@b-soft.com.ar>
  setHTML: function(i, v){
   if(typeof i=='object'){
    v = i.html;
    i = i.InstanceName || i.instance;
   };
   return $.fck.content(i, v);
  },
  
  // utility method to update textarea contents before ajax submission
  update: function(){
   // Update contents of all instances
   var e = $.fck.editors;
   for(var i=0;i<e.length;i++){
    var ta = e[i].textarea;
    var ht = $.fck.content(e[i].InstanceName);
    ta.val(ht).filter('textarea').text(ht);
    if(ht!=ta.val())
     alert('Critical error in FCK plugin:'+'\n'+'Unable to update form data');
   }
  }, // fck.update
  
  // utility method to non-existing instances from memory
  clean: function(){
			var a = $.fck.editors, b = {}, c = [];
			$.each(a, function(){ if($('#'+this.InstanceName).length>0) b[this.InstanceName] = this; });
			$.each(b, function(){ c[c.length] = this; });
			$.fck.editors = c;
  }, // fck.clean
  
  // utility method to create instances of FCK editor (if any)
  create: function(option){
			// Create a new options object
   var o = $.extend({}/* new object */, $.fck.config || {}, option || {});
   // Normalize plugin options
   $.extend(o, {
    selector: (o.selector || 'textarea.fck, textarea.fckeditor'),
    BasePath: (o.path || o.BasePath || $.fck.path)
   });
   // Find fck.editor-instance 'wannabes'
   var e = $(o.e);
   if(!e.length>0) e = $(o.selector);
   if(!e.length>0) return;
			// Accept settings from metadata plugin
			o = $.extend({}, o,
				($.meta ? e.data()/*NEW metadata plugin*/ :
				($.metadata ? e.metadata()/*OLD metadata plugin*/ : 
				null/*metadata plugin not available*/)) || {}
			);
   // Load script and create instances
   if(!$.fck.loading && !$.fck.loaded){
    $.fck.loading = true;
    $.getScript(
     o.BasePath+'fckeditor.js',
     function(){ $.fck.loaded = true; }
    );
   };
   // Start editor
   var start = function(){//e){
    if($.fck.loaded){
     //if(window.console) console.log(['fck.create','start',e,o]);
     $.fck.editor(e,o);
    }
    else{
     //if(window.console) console.log(['fck.create','waiting for script...',e,o]);
     if($.fck.waited<=0){
      alert('jQuery.fckeditor plugin error: The FCKEditor script did not load.');
     }
     else{
      $.fck.waitFor--;
      window.setTimeout(start,1000);
     };
    }
   };
   start(e);
   // Return matched elements...
   return e;
  },
  
  // utility method to integrate this plugin with others...
  intercept: function(){
   if($.fck.intercepted) return;
   // This method intercepts other known methods which
   // require up-to-date code from FCKEditor
   $.fck.intercepted = {
    ajaxSubmit: $.fn.ajaxSubmit || function(){}
   };
   $.fn.ajaxSubmit = function(){
    $.fck.update(); // update html
    return $.fck.intercepted.ajaxSubmit.apply( this, arguments );
   };
  },
  
  // utility method to create an instance of FCK editor
  editor: function(e /* elements */, o /* options */){
   //if(window.console) console.log(['fck.editor','OPTIONS',o]);
   o = $.extend({}, $.fck.config || {}, o || {});
   // Default configuration
   $.extend(o,{
    Width: (o.width || o.Width || '100%'),
    Height: (o.height || o.Height|| '500px'),
    BasePath: (o.path || o.BasePath || $.fck.path),
    ToolbarSet: (o.toolbar || o.ToolbarSet || 'Default'),
    Config: (o.config || o.Config || {})
   });
   // Make sure we have a jQuery object
   e = $(e);
   //if(window.console) console.log(['fck.editor','E',e,o]);
   if(e.size()>0){
    // Local array to store instances
    var a = $.fck.editors;// || [];
    // Go through objects and initialize fck.editor
    e.each(
     function(i,t){
						if((t.tagName||'').toLowerCase()!='textarea')
							return alert(['An invalid parameter has been passed to the $.fckeditor.editor function','tagName:'+t.tagName,'name:'+t.name,'id:'+t.id].join('\n'));
      
      var T = $(t);// t = element, T = jQuery
      if(!t.name) t.name = 'fck'+($.fck.editors.length+1);
      if(!t.id) t.id = t.name;
      if(t.id/* has id */ && !t.fck/* not already installed */){
       var n = a.length;
							// create FCKeditor instance
       a[n] = new FCKeditor(t.name);
							// Apply inline configuration
       $.extend(a[n], o, o.Config || {});
							// Start FCKeditor
       a[n].ReplaceTextarea();
							// Store reference to original element
       a[n].textarea = T;
							// Store reference to FCKeditor in element
       t.fck = a[n];
      };
     }
    );
    // Store instances in global array
    $.fck.editors = a;
				// Remove old non-existing editors from memory
				$.fck.clean();
   };
   // return jQuery array of elements
   return e;
  }, // fck.editor function
  
  // start-up method
  start: function(o/* options */){
   // Attach itself to known plugins...
   $.fck.intercept();
   // Create FCK editors
   return $.fck.create(o);
  } // fck.start
  
 } // fck object
 //##############################
 
});
// extend $
//##############################


$.extend($.fn, {
 fck: function(o){
  //(function(opts){ $.fck.start(opts); })($.extend(o || {}, {e: this}));
  $.fck.start($.extend(o || {}, {e: this}));
 }
});
// extend $.fn
//##############################

/*# AVOID COLLISIONS #*/
})(jQuery);
/*# AVOID COLLISIONS #*/

// End manually included /library/javascripts/jquery/jquery.FCKEditor/jquery.FCKEditor.js
// (so that SBA developers only have to include jquery.FCKEditor.SBA.js). 

// ***************************************************************************************

// Everything that follows is SBA code (as you can tell from the end-of-line comments). 				// SBA

// The existence of the following array means ONLY that this JS file was included. Its purpose is to 	// SBA
// hold only INSTANTIATED rich text editors (currently only FCK editors). For CANDIDATES for conversion // SBA
// into rich text editors, use SlafGetRichTextEditors instead. 											// SBA

top.gSlafRichTextEditors			= new Array();														// SBA

function SlafGetRichTextEditors		()	// Logical name, allows other editors in the future. 			// SBA
	{																									// SBA
	// For instantiated rich text editors, use top.gSlafRichTextEditors (array) instead. 				// SBA
	//																									// SBA
	// In jQuery < 1.4, $() was equivalent to $(document). In jQuery 1.4+, $() returns the empty set. 	// SBA
	// So tack on ".not(document)" to consistently return the empty set, regardless of jQuery version. 	// SBA
	// In 1.4+, the filter loops over 0 elements (unnecessary, but at least it's very quick). 			// SBA
	//																									// SBA
	// That said, top.gSlafSuppressRTE is set by the user using /library/callbacks/dsp_preferences.cfm. // SBA
	// If suppressed, return the empty set, else return all textareas with class="rte" (SBA flag):		// SBA
	return top.gSlafSuppressRTE ? $().not(document) : $("textarea.rte");								// SBA
	}																									// SBA

// The following is for character counts, usually for fields that have a maxlength restriction. In the 	// SBA
// case of a countdown character count, there MUST be a maxlenth restriction, but we don't enforce it. 	// SBA

function SlafRTEKeyUpHandler		(pThis)																// SBA
	{																									// SBA
	var	sValue						= pThis.SbaGetValue();												// SBA
	var	sValueLen					= sValue.length;													// SBA
	// Because it's not a standard textarea attribute,we have to get maxlength with getAttribute: 		// SBA
	var	sMaxLength					= pThis.getAttribute("maxlength");									// SBA
	if	(sMaxLength && (pThis.SbaCountDown))															// SBA
		{																								// SBA
		var	sCD						= pThis.SbaCountDown;	// Save on referential array lookups.		// SBA
		if		(sValueLen			<= (sMaxLength - 20))	{											// SBA
															sCD.style.backgroundColor	= "#fff";		// SBA
															sCD.style.fontWeight		= "normal";		// SBA
															}											// SBA
		else if	(sValueLen			<= sMaxLength)			{// bright yellow: 							// SBA
															sCD.style.backgroundColor	= "#ff0";		// SBA
															sCD.style.fontWeight		= "bold";		// SBA
															}											// SBA
		else												{// pastel red: 							// SBA
															sCD.style.backgroundColor	= "#f99";		// SBA
															sCD.style.fontWeight		= "bold";		// SBA
															}											// SBA
		pThis.SbaCountDown.innerHTML= sMaxLength														// SBA
									- sValueLen;														// SBA
		}																								// SBA
	if	(pThis.SbaCountUp)																				// SBA
		pThis.SbaCountUp.innerHTML	= sValueLen;														// SBA
	if	(pThis.SbaShowHTML)																				// SBA
		pThis.SbaShowHTML.innerHTML	= sValue															// SBA
									.replace(/&/g, "&amp;")												// SBA
									.replace(/\</g, "&lt;")												// SBA
									.replace(/\n/g, "<br/>");											// SBA
	return true;																						// SBA
	}																									// SBA

// The following event handler will fire every time an FCK editor is instantiated. To prevent a "race 	// SBA
// condition", we're defining it BEFORE the $(document).ready routine to trigger the instantiations. 	// SBA
//																										// SBA
// FCKeditor_OnComplete is part of the FCKEditor API. It requires that exact spelling. It accepts only 	// SBA
// one parameter, pFCK, a reference to the FCK object. In this callback, we will use pFCK.LinkedField 	// SBA
// (the underlying textarea) to define our own accessor routines at the form element level, for use in 	// SBA
// form element loops. These will be used by other SBA form routines: ClearForm, FormSynopsis, 			// SBA
// ResetForm and SetFormEltValue. 																		// SBA

function FCKeditor_OnComplete		(pFCK)																// SBA
	{																									// SBA
	var	sTextarea					= pFCK.LinkedField;													// SBA
	sTextarea.SbaEditor				= FCKeditorAPI.GetInstance(pFCK.Name);								// SBA
	sTextarea.SbaGetValue			= function()	{return	this.SbaEditor.GetHTML();};					// SBA
	sTextarea.SbaSetValue			= function(v)	{		this.SbaEditor.SetHTML(v);};				// SBA
	// New. Countdown, countup and showhtml capabilities: 												// SBA
	var	sTextareaCountDown			= sTextarea.getAttribute("data-rtecountdown");						// SBA
	if ((sTextareaCountDown			!= null)															// SBA
	&&	(sTextareaCountDown.length	> 0))																// SBA
		{																								// SBA
		sTextareaCountDown			= document.getElementById(sTextareaCountDown);						// SBA
		if	(sTextareaCountDown		!= null)															// SBA
			sTextarea.SbaCountDown	= sTextareaCountDown;												// SBA
		}																								// SBA
	var	sTextareaCountUp			= sTextarea.getAttribute("data-rtecountup");						// SBA
	if ((sTextareaCountUp			!= null)															// SBA
	&&	(sTextareaCountUp.length	> 0))																// SBA
		{																								// SBA
		sTextareaCountUp			= document.getElementById(sTextareaCountUp);						// SBA
		if	(sTextareaCountUp		!= null)															// SBA
			sTextarea.SbaCountUp	= sTextareaCountUp;													// SBA
		}																								// SBA
	var	sTextareaShowHTML			= sTextarea.getAttribute("data-rteshowhtml");						// SBA
	if ((sTextareaShowHTML			!= null)															// SBA
	&&	(sTextareaShowHTML.length	> 0))																// SBA
		{																								// SBA
		sTextareaShowHTML			= document.getElementById(sTextareaShowHTML);						// SBA
		if	(sTextareaShowHTML		!= null)															// SBA
			sTextarea.SbaShowHTML	= sTextareaShowHTML;												// SBA
		}																								// SBA
	if ((!!sTextareaCountUp)		// !! turns what follows into a true boolean. 						// SBA
	||	(!!sTextareaCountUp)		// !! turns what follows into a true boolean. 						// SBA
	||	(!!sTextareaShowHTML))		// !! turns what follows into a true boolean. 						// SBA
		{																								// SBA
		$(pFCK.EditingArea.Document).keyup(function(){SlafRTEKeyUpHandler(sTextarea);});				// SBA
		$(pFCK.EditingArea.Document).click(function(){SlafRTEKeyUpHandler(sTextarea);});				// SBA
		SlafRTEKeyUpHandler(sTextarea);	// Don't wait on the first keyup/click to show something. 		// SBA
		}																								// SBA
	//																									// SBA
	// Build top.gSlafRichTextEditors array. ("And ye shall know them by their fck attribute"): 		// SBA
	//																									// SBA
	if	(!top.gSlafRichTextEditors)																		// SBA
		top.gSlafRichTextEditors		= new Array();													// SBA
	var	sLen							= top.gSlafRichTextEditors.length;								// SBA
	top.gSlafRichTextEditors[sLen]		= pFCK.LinkedField;												// SBA
	//																									// SBA
	//	My latest-and-greatest failed attempt to write this.SbaSetEnabled() is preserved as follows 	// SBA
	//	in commented-out form. The problem with it is that you can't execute it at $(document).ready()	// SBA
	//	time, or even at $(window).load() time. FCKEditor takes so long to load, FCKeditorAPI will not 	// SBA
	//	have been instantiated yet, and the DOM traversal code fails in Firefox when it tries to 		// SBA
	//	reference sOuterFrame.contentDocument. Presumably that happens because not even that has been 	// SBA
	//	instantiated yet (not even the outer frame's document). This causes other scripts to crash in 	// SBA
	//	Firefox. So my feeling is, it's not worth it at this time. For now, we can't disable FCKEditor 	// SBA
	//	instances. The best we can do is mark them disabled with visual cues. (See HiGrpUtils.js.) SRS	// SBA
	//																									// SBA
	//	this.SbaSetEnabled				= function(pEnabled)											// SBA
	//		{																							// SBA
	//		var	sErrored				= false;														// SBA
	//		try	{																						// SBA
	//			if	(!this.SbaEditor)																	// SBA
	//				this.SbaEditor		= FCKeditorAPI.GetInstance(this.name);							// SBA
	//			this.SbaEditor.EditorDocument.body.contentEditable = pEnabled;							// SBA
	//			}																						// SBA
	//		catch (e)					{sErrored	= true;}											// SBA
	//		if	(sErrored)																				// SBA
	//			{// DOM Navigation done only as a last resort. Could change with new FCKEditor versions.// SBA
	//			var	sOuterFrame			= document.getElementById(this.name);							// SBA
	//			var	sOuterBody			= null;	// Just defining it in one place, at this point. 		// SBA
	//			if	($.browser.msie)																	// SBA
	//				sOuterBody			= sOuterFrame.contentWindow.document.body;						// SBA
	//			else																					// SBA
	//				sOuterBody			= sOuterFrame.contentDocument.body;								// SBA
	//			var	sInnerFrame			= sOuterBody.getElementById("xEditingArea").firstChild;			// SBA
	//			var	sInnerBody			= null;	// Just defining it in one place, at this point. 		// SBA
	//			if	($.browser.msie)																	// SBA
	//				sInnerBody			= sInnerFrame.contentWindow.document.body;						// SBA
	//			else																					// SBA
	//				sInnerBody			= sInnerFrame.contentDocument.body;								// SBA
	//			sInnerBody.contentEditable = pEnabled;													// SBA
	//			}																						// SBA
	//		return sValue;																				// SBA
	//		}																							// SBA
	}																									// SBA

// Instantiate the rich text editors:																	// SBA

$(document).ready(function()																			// SBA
	{																									// SBA
	top.gSlafRichTextEditors.length		= 0;// In case it exists as a leftover in a frames document.	// SBA
	SlafGetRichTextEditors().each(function()															// SBA
		{																								// SBA
		var	s$This						= $(this);	// Save on rebuilding jQuery objects. 				// SBA
		var	sRTEToolbar					= s$This.attr("rtetoolbar");									// SBA
		if	(sRTEToolbar)																				// SBA
			s$This.fck({toolbar:sRTEToolbar,	height: s$This.height(),	width:s$This.width()});		// SBA
		else																							// SBA
			s$This.fck({toolbar:'SBADefault',	height: s$This.height(),	width:s$This.width()});		// SBA
		});
	});																									// SBA

// End /library/javascripts/jquery/jquery.FCKEditor/jquery.FCKEditor.SBA.js


