1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 CKEDITOR.plugins.add( 'panel', 7 { 8 beforeInit : function( editor ) 9 { 10 editor.ui.addHandler( CKEDITOR.UI_PANEL, CKEDITOR.ui.panel.handler ); 11 } 12 }); 13 14 /** 15 * Panel UI element. 16 * @constant 17 * @example 18 */ 19 CKEDITOR.UI_PANEL = 2; 20 21 CKEDITOR.ui.panel = function( document, definition ) 22 { 23 // Copy all definition properties to this object. 24 if ( definition ) 25 CKEDITOR.tools.extend( this, definition ); 26 27 // Set defaults. 28 CKEDITOR.tools.extend( this, 29 { 30 className : '', 31 css : [] 32 }); 33 34 this.id = CKEDITOR.tools.getNextNumber(); 35 this.document = document; 36 37 this._ = 38 { 39 blocks : {} 40 }; 41 }; 42 43 /** 44 * Transforms a rich combo definition in a {@link CKEDITOR.ui.richCombo} 45 * instance. 46 * @type Object 47 * @example 48 */ 49 CKEDITOR.ui.panel.handler = 50 { 51 create : function( definition ) 52 { 53 return new CKEDITOR.ui.panel( definition ); 54 } 55 }; 56 57 CKEDITOR.ui.panel.prototype = 58 { 59 renderHtml : function( editor ) 60 { 61 var output = []; 62 this.render( editor, output ); 63 return output.join( '' ); 64 }, 65 66 /** 67 * Renders the combo. 68 * @param {CKEDITOR.editor} editor The editor instance which this button is 69 * to be used by. 70 * @param {Array} output The output array to which append the HTML relative 71 * to this button. 72 * @example 73 */ 74 render : function( editor, output ) 75 { 76 var id = 'cke_' + this.id; 77 78 output.push( 79 '<div class="', editor.skinClass ,'">' + 80 '<div id=', id, ' class="cke_panel' ); 81 82 if ( this.className ) 83 output.push( ' ', this.className ); 84 85 output.push( 86 '">' ); 87 88 if ( this.forceIFrame || this.css.length ) 89 { 90 output.push( 91 '<iframe id="', id, '_frame"' + 92 ' frameborder="0"' + 93 ' src="javascript:void(0)"' + 94 '></iframe>' ); 95 } 96 97 output.push( 98 '</div>' + 99 '</div>' ); 100 101 return id; 102 }, 103 104 getHolderElement : function() 105 { 106 var holder = this._.holder; 107 108 if ( !holder ) 109 { 110 if ( this.forceIFrame || this.css.length ) 111 { 112 var iframe = this.document.getById( 'cke_' + this.id + '_frame' ); 113 var doc = new CKEDITOR.dom.document( iframe.$.contentWindow.document ); 114 115 var className = iframe.getParent().getParent().getAttribute( 'class' ); 116 117 // Initialize the IFRAME document body. 118 doc.$.open(); 119 doc.$.write( 120 '<!DOCTYPE html>' + 121 '<html>' + 122 '<head>' + 123 '<link type="text/css" rel=stylesheet href="' + this.css.join( '"><link type="text/css" rel="stylesheet" href="' ) + '">' + 124 '<style>.' + className + '_container{visibility:hidden}</style>' + 125 '</head>' + 126 '<body class="' + className + '_container cke_panel_frame" style="margin:0;padding:0">' + 127 '</body>' + 128 '<\/html>' ); 129 doc.$.close(); 130 131 var win = doc.getWindow(); 132 133 // Register the CKEDITOR global. 134 win.$.CKEDITOR = CKEDITOR; 135 136 win.on( 'load', function( ev ) 137 { 138 this.isLoaded = true; 139 if ( this.onLoad ) 140 this.onLoad(); 141 }, 142 this); 143 144 doc.on( 'keydown', function( evt ) 145 { 146 var keystroke = evt.data.getKeystroke(); 147 148 // Delegate key processing to block. 149 if ( this._.onKeyDown && this._.onKeyDown( keystroke ) === false ) 150 { 151 evt.data.preventDefault(); 152 return; 153 } 154 155 if ( keystroke == 27 ) // ESC 156 this.onEscape && this.onEscape(); 157 }, 158 this ); 159 160 holder = doc.getBody(); 161 } 162 else 163 holder = this.document.getById( 'cke_' + this.id ); 164 165 this._.holder = holder; 166 } 167 168 return holder; 169 }, 170 171 addBlock : function( name, block ) 172 { 173 block = this._.blocks[ name ] = block || new CKEDITOR.ui.panel.block( this.getHolderElement() ); 174 175 if ( !this._.currentBlock ) 176 this.showBlock( name ); 177 178 return block; 179 }, 180 181 getBlock : function( name ) 182 { 183 return this._.blocks[ name ]; 184 }, 185 186 showBlock : function( name ) 187 { 188 var blocks = this._.blocks, 189 block = blocks[ name ], 190 current = this._.currentBlock; 191 192 if ( current ) 193 current.hide(); 194 195 this._.currentBlock = block; 196 197 // Reset the focus index, so it will always go into the first one. 198 block._.focusIndex = -1; 199 200 this._.onKeyDown = block.onKeyDown && CKEDITOR.tools.bind( block.onKeyDown, block ); 201 202 block.show(); 203 204 return block; 205 } 206 }; 207 208 CKEDITOR.ui.panel.block = CKEDITOR.tools.createClass( 209 { 210 $ : function( blockHolder ) 211 { 212 this.element = blockHolder.append( 213 blockHolder.getDocument().createElement( 'div', 214 { 215 attributes : 216 { 217 'class' : 'cke_panel_block' 218 }, 219 styles : 220 { 221 display : 'none' 222 } 223 }) ); 224 225 this.keys = {}; 226 227 this._.focusIndex = -1; 228 }, 229 230 _ : {}, 231 232 proto : 233 { 234 show : function() 235 { 236 this.element.setStyle( 'display', '' ); 237 }, 238 239 hide : function() 240 { 241 this.element.setStyle( 'display', 'none' ); 242 }, 243 244 onKeyDown : function( keystroke ) 245 { 246 var keyAction = this.keys[ keystroke ]; 247 switch ( keyAction ) 248 { 249 // Move forward. 250 case 'next' : 251 var index = this._.focusIndex, 252 links = this.element.getElementsByTag( 'a' ), 253 link; 254 255 while ( ( link = links.getItem( ++index ) ) ) 256 { 257 // Move the focus only if the element is marked with 258 // the _cke_focus and it it's visible (check if it has 259 // width). 260 if ( link.getAttribute( '_cke_focus' ) && link.$.offsetWidth ) 261 { 262 this._.focusIndex = index; 263 link.focus(); 264 break; 265 } 266 } 267 return false; 268 269 // Move backward. 270 case 'prev' : 271 var index = this._.focusIndex, 272 links = this.element.getElementsByTag( 'a' ), 273 link; 274 275 while ( index > 0 && ( link = links.getItem( --index ) ) ) 276 { 277 // Move the focus only if the element is marked with 278 // the _cke_focus and it it's visible (check if it has 279 // width). 280 if ( link.getAttribute( '_cke_focus' ) && link.$.offsetWidth ) 281 { 282 this._.focusIndex = index; 283 link.focus(); 284 break; 285 } 286 } 287 return false; 288 289 case 'click' : 290 var index = this._.focusIndex, 291 link = index >= 0 && this.element.getElementsByTag( 'a' ).getItem( index ); 292 293 if ( link ) 294 link.$.click(); 295 296 return false; 297 } 298 } 299 } 300 }); 301