
(function() {

function addSafely( collection, element, database )
{
	// 1. IE doesn't support customData on text nodes;
	// 2. Text nodes never get chance to appear twice;
	if ( !element.is || !element.getCustomData( 'block_processed' ) )
	{
		element.is && CKEDITOR.dom.element.setMarker( database, element, 'block_processed', true );
		collection.push( element );
	}
}

function getNonEmptyChildren( element )
{
	var retval = [];
	var children = element.getChildren();
	for ( var i = 0 ; i < children.count() ; i++ )
	{
		var child = children.getItem( i );
		if ( ! ( child.type === CKEDITOR.NODE_TEXT
			&& ( /^[ \t\n\r]+$/ ).test( child.getText() ) ) )
			retval.push( child );
	}
	return retval;
}

juvo.define('juvo.ui.clickAreaDiv', {
	init: function( args ) {
	
	var dtd = CKEDITOR.dtd.div,
	styles = {},
	containers = {},
	editor = args.editor,
	className = args.className;

	var divLimitDefinition = ( function() {

		// Customzie from specialize blockLimit elements
		var definition = CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$blockLimit );

		// Exclude 'div' itself.
		delete definition.div;

		// Exclude 'td' and 'th' when 'wrapping table'
		if ( editor.config.div_wrapTable )
		{
			delete definition.td;
			delete definition.th;
		}
		return definition;
	} )();
	
	getDiv = function( editor )
	{
		var path = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() ),
			blockLimit = path.blockLimit,
			div = blockLimit && blockLimit.getAscendant( 'div', true );
		return div;
	};

	getDivLimitElement = function ( element )
	{
		var pathElements = new CKEDITOR.dom.elementPath( element ).elements;
		var divLimit;
		
		//dld = divLimitDefinition( editor );
		
		for ( var i = 0; i < pathElements.length ; i++ )
		{			
			if ( pathElements[ i ].getName() in divLimitDefinition )
			{
				divLimit = pathElements[ i ];
				break;
			}
		}
		return divLimit;
	};
	

	groupByDivLimit = function( nodes )
	{
		var groups = [],
			lastDivLimit = null,
			path, block;
		for ( var i = 0 ; i < nodes.length ; i++ )
		{
			block = nodes[i];
			var limit = getDivLimitElement( block );
			if ( !limit.equals( lastDivLimit ) )
			{
				lastDivLimit = limit ;
				groups.push( [] ) ;
			}
			groups[ groups.length - 1 ].push( block ) ;
		}
		return groups;
	};
	
	this.insideDiv = function( editor )
	{
		var selection = editor.getSelection().getStartElement(),
			path = new CKEDITOR.dom.elementPath( selection ),
			blockLimit = path.blockLimit,
			div = blockLimit.is( 'div' ) && blockLimit;

		if ( div && (
				div.hasClass( 'juvo-ui-click-target' ) ||
				div.hasClass( 'juvo-ui-click-area' ) ) ) 
		{
			return true;
		}
		
		return false;
	},
	
	this.createDiv = function( editor )
	{
		if( this.insideDiv( editor ) ) {
			return this.removeDiv( editor );
		}
		
		// new adding containers OR detected pre-existed containers.
		var containers = [];
		// node markers store.
		var database = {};
		// All block level elements which contained by the ranges.
		var containedBlocks = [], block;

		// Get all ranges from the selection.
		var selection = editor.document.getSelection(),
			ranges = selection.getRanges();
		var bookmarks = selection.createBookmarks();
		var i, iterator;

		// Calcualte a default block tag if we need to create blocks.
		var blockTag = editor.config.enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p';

		// collect all included elements from dom-iterator
		for ( i = 0 ; i < ranges.length ; i++ )
		{
			iterator = ranges[ i ].createIterator();
			while ( ( block = iterator.getNextParagraph() ) )
			{
				// include contents of blockLimit elements.
				if ( block.getName() in divLimitDefinition )
				{
					var j, childNodes = block.getChildren();
					for ( j = 0 ; j < childNodes.count() ; j++ )
						addSafely( containedBlocks, childNodes.getItem( j ) , database );
				}
				else
				{
					// Bypass dtd disallowed elements.
					while ( !dtd[ block.getName() ] && block.getName() != 'body' )
						block = block.getParent();
					addSafely( containedBlocks, block, database );
				}
			}
		}

		CKEDITOR.dom.element.clearAllMarkers( database );

		var blockGroups = groupByDivLimit( containedBlocks );
		var ancestor, blockEl, divElement;

		for ( i = 0 ; i < blockGroups.length ; i++ )
		{
			var currentNode = blockGroups[ i ][ 0 ];

			// Calculate the common parent node of all contained elements.
			ancestor = currentNode.getParent();
			for ( j = 1 ; j < blockGroups[ i ].length; j++ )
				ancestor = ancestor.getCommonAncestor( blockGroups[ i ][ j ] );

			divElement = new CKEDITOR.dom.element( 'div', editor.document );
			//divElement.setStyle( 'background-color', '#fdd' );
			divElement.setAttribute( 'class', className );

			// Normalize the blocks in each group to a common parent.
			for ( j = 0; j < blockGroups[ i ].length ; j++ )
			{
				currentNode = blockGroups[ i ][ j ];

				while ( !currentNode.getParent().equals( ancestor ) )
					currentNode = currentNode.getParent();

				// This could introduce some duplicated elements in array.
				blockGroups[ i ][ j ] = currentNode;
			}

			// Wrapped blocks counting
			var fixedBlock = null;
			for ( j = 0 ; j < blockGroups[ i ].length ; j++ )
			{
				currentNode = blockGroups[ i ][ j ];

				// Avoid DUP elements introduced by grouping.
				if ( !( currentNode.getCustomData && currentNode.getCustomData( 'block_processed' ) ) )
				{
					currentNode.is && CKEDITOR.dom.element.setMarker( database, currentNode, 'block_processed', true );

					// Establish new container, wrapping all elements in this group.
					if ( !j )
						divElement.insertBefore( currentNode );

					divElement.append( currentNode );
				}
			}

			CKEDITOR.dom.element.clearAllMarkers( database );
			containers.push( divElement );
		}

		selection.selectBookmarks( bookmarks );
		return containers;
	},
	
	this.removeDiv = function( editor ) {
		var selection = editor.getSelection(),
			ranges = selection && selection.getRanges(),
			range,
			bookmarks = selection.createBookmarks(),
			walker,
			toRemove = [];

		function findDiv( node )
		{
			var path = new CKEDITOR.dom.elementPath( node ),
				blockLimit = path.blockLimit,
				div = blockLimit.is( 'div' ) && blockLimit;

			if ( div && !div.getAttribute( '_cke_div_added' ) && (
					div.hasClass( 'juvo-ui-click-target' ) ||
					div.hasClass( 'juvo-ui-click-area' ) ) ) 
			{
				toRemove.push( div );
				div.setAttribute( '_cke_div_added' );
			}
		}

		for ( var i = 0 ; i < ranges.length ; i++ )
		{
			range = ranges[ i ];
			if ( range.collapsed )
				findDiv( selection.getStartElement() );
			else
			{
				walker = new CKEDITOR.dom.walker( range );
				walker.evaluator = findDiv;
				walker.lastForward();
			}
		}

		for ( i = 0 ; i < toRemove.length ; i++ )
			toRemove[ i ].remove( true );

		selection.selectBookmarks( bookmarks );
	}
}
});

//window['juvo']['ui']['richEditor']['clickAreaDiv'] = clickAreaDiv;

})();















$(function() {

function getInternetExplorerVersion()
{
  var rv = -1; // Return value assumes failure.
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
	var ua = navigator.userAgent;
	var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
	if (re.exec(ua) != null)
	  rv = parseFloat( RegExp.$1 );
  }
  return rv;
}		

if( typeof(CKEDITOR) == 'undefined' ) {
	$('.juvo-ui-click-target').click( function(e) {
		var isIE = ( getInternetExplorerVersion() != -1 );
		
		e.stopImmediatePropagation();
		
		$elements = $('.juvo-ui-click-target, .juvo-ui-click-area').toArray();
		
		idx = $elements.indexOf( this );
		
		idx += 1;
		$next = this;
		
		while( idx < $elements.length ) {
			$next = $($elements[ idx ]);
			
			if( $next.hasClass( 'juvo-ui-click-area' ) ) {
				
				/*
				$next.slideToggle(300, function() {
					if( $next.css('display') == 'none' ) {
						return;
					}
				*/
				
				if( isIE ) {
					$next.css('opacity', '1');
					if( $next.css('display') == 'block' ) {
						$next[0].style.display = 'none';
						$next.css('display', 'none');						
					} else {
						$next[0].style.display = 'block';
						$next.css('display', 'block');
					}
					
				} else {
					$next.animate({
						height: 'toggle',
						opacity: 'toggle'					
					}, 200, function() {
							if( $next.css('display') == 'none' ) {
								return;
							}
							
							$next.animate({
									'background-color': '#777',
									opacity: 0.50
								}, 50
							);
							$next.animate({
									'background-color': '',
									opacity: 1
								}, 300
							);
						}
					);
				}
				
				break;
			}
			
			idx += 1;
		}
		
	}).wrapInner("<a title='Click here to see more' />");
	
	return;
}

CKEDITOR.plugins.add('jsarea',
{	
	requires: [ 'editingblock', 'domiterator', 'styles' ],	
	
	init: function( editor )
	{
		editor.addCommand( 'insertClickArea', 
			{
				exec: function( editor )
				{
					_command = juvo('juvo-ui-click-area').instantiate( juvo.ui.clickAreaDiv, {
						editor: editor,
						className: 'juvo-ui-click-area' 
					} );
					_command.createDiv( editor );
				}
			}
		);
		
		editor.addCommand( 'removeClickArea', 
			{
				exec: function( editor )
				{
					_command = juvo('juvo-ui-click-area').instantiate( juvo.ui.clickAreaDiv, {
						editor: editor,
						className: 'juvo-ui-click-area' 
					} );
					_command.removeDiv( editor );
				}
			}
		);
		editor.ui.addButton( 'jsarea',
			{
				label: 'Click Area',
				command: 'insertClickArea',
				icon:'/css/juvo/ui/rich-editor/jsexpand_area.png'
			}
		);
		if ( editor.addMenuItems )
		{
			editor.addMenuItems(
				{
					removeClickArea :
					{
						label : 'Remove Click Area',
						command : 'removeClickArea',
						group : 'jsarea',
						order : 1
					}
				} );

			if ( editor.contextMenu )
			{
				editor.contextMenu.addListener( function( element, selection )
					{
						if ( !element )//|| element.isReadOnly() )
							return null;

						var elementPath = new CKEDITOR.dom.elementPath( element ),
							blockLimit = elementPath.blockLimit;

						if ( blockLimit )
						{
							e = blockLimit.getAscendant( 'div', true );
							
							if( e && (
								e.hasClass( 'juvo-ui-click-target' ) ||
								e.hasClass( 'juvo-ui-click-area' ) ) ) 
							{
								return {
									removeClickArea : CKEDITOR.TRISTATE_OFF
								};
							}
						}

						return null;
					} );
			}
		}
	}
});

CKEDITOR.plugins.add('jsclick',
{
	init: function( editor )
	{
		editor.addCommand( 'insertClickTarget', 
			{
				exec: function( editor )
				{
					_command = juvo('juvo-ui-click-target').instantiate( juvo.ui.clickAreaDiv, {
						editor: editor,
						className: 'juvo-ui-click-target' 
					} );
					_command.createDiv( editor );
				}
			}
		);
		
		editor.addCommand( 'removeClickTarget', 
			{
				exec: function( editor )
				{
					_command = juvo('juvo-ui-click-target').instantiate( juvo.ui.clickAreaDiv, {
						editor: editor,
						className: 'juvo-ui-click-target' 
					} );
					_command.removeDiv( editor );
				}
			}
		);
		editor.ui.addButton( 'jsclick',
			{
				label: 'Click Target',
				command: 'insertClickTarget',
				icon:'/css/juvo/ui/rich-editor/jsexpand_click.png'
			}
		);
	}
});

CKEDITOR.config.extraPlugins = CKEDITOR.config.extraPlugins + ',jsclick,jsarea';

CKEDITOR.config.menu_groups = CKEDITOR.config.menu_groups.replace( ",div", ',jsarea' );

_css = CKEDITOR.config.contentsCss;
if( _css instanceof Array ) {
	CKEDITOR.config.contentsCss[_css.length] = '/css/juvo/ui/rich-editor.css';
} else {
	CKEDITOR.config.contentsCss = [_css, '/css/juvo/ui/rich-editor.css'];
}











});

if (!Array.prototype.indexOf)
  {

       Array.prototype.indexOf = function(searchElement /*, fromIndex */)

    {


    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (len === 0)
      return -1;

    var n = 0;
    if (arguments.length > 0)
    {
      n = Number(arguments[1]);
      if (n !== n)
        n = 0;
      else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
        n = (n > 0 || -1) * Math.floor(Math.abs(n));
    }

    if (n >= len)
      return -1;

    var k = n >= 0
          ? n
          : Math.max(len - Math.abs(n), 0);

    for (; k < len; k++)
    {
      if (k in t && t[k] === searchElement)
        return k;
    }
    return -1;
  };

}


