1/* 2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net 3 * Copyright (C) 2003-2007 Frederico Caldeira Knabben 4 * 5 * == BEGIN LICENSE == 6 * 7 * Licensed under the terms of any of the following licenses at your 8 * choice: 9 * 10 * - GNU General Public License Version 2 or later (the "GPL") 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 14 * http://www.gnu.org/licenses/lgpl.html 15 * 16 * - Mozilla Public License Version 1.1 or later (the "MPL") 17 * http://www.mozilla.org/MPL/MPL-1.1.html 18 * 19 * == END LICENSE == 20 * 21 * FCKSpecialCombo Class: represents a special combo. 22 */ 23 24var FCKSpecialCombo = function( caption, fieldWidth, panelWidth, panelMaxHeight, parentWindow ) 25{ 26 // Default properties values. 27 this.FieldWidth = fieldWidth || 100 ; 28 this.PanelWidth = panelWidth || 150 ; 29 this.PanelMaxHeight = panelMaxHeight || 150 ; 30 this.Label = ' ' ; 31 this.Caption = caption ; 32 this.Tooltip = caption ; 33 this.Style = FCK_TOOLBARITEM_ICONTEXT ; 34 35 this.Enabled = true ; 36 37 this.Items = new Object() ; 38 39 this._Panel = new FCKPanel( parentWindow || window ) ; 40 this._Panel.AppendStyleSheet( FCKConfig.SkinPath + 'fck_editor.css' ) ; 41 this._PanelBox = this._Panel.MainNode.appendChild( this._Panel.Document.createElement( 'DIV' ) ) ; 42 this._PanelBox.className = 'SC_Panel' ; 43 this._PanelBox.style.width = this.PanelWidth + 'px' ; 44 45 this._PanelBox.innerHTML = '<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>' ; 46 47 this._ItemsHolderEl = this._PanelBox.getElementsByTagName('TD')[0] ; 48 49 if ( FCK.IECleanup ) 50 FCK.IECleanup.AddItem( this, FCKSpecialCombo_Cleanup ) ; 51 52// this._Panel.StyleSheet = FCKConfig.SkinPath + 'fck_contextmenu.css' ; 53// this._Panel.Create() ; 54// this._Panel.PanelDiv.className += ' SC_Panel' ; 55// this._Panel.PanelDiv.innerHTML = '<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>' ; 56// this._ItemsHolderEl = this._Panel.PanelDiv.getElementsByTagName('TD')[0] ; 57} 58 59function FCKSpecialCombo_ItemOnMouseOver() 60{ 61 this.className += ' SC_ItemOver' ; 62} 63 64function FCKSpecialCombo_ItemOnMouseOut() 65{ 66 this.className = this.originalClass ; 67} 68 69function FCKSpecialCombo_ItemOnClick( ev, specialCombo, itemId ) 70{ 71 this.className = this.originalClass ; 72 73 specialCombo._Panel.Hide() ; 74 75 specialCombo.SetLabel( this.FCKItemLabel ) ; 76 77 if ( typeof( specialCombo.OnSelect ) == 'function' ) 78 specialCombo.OnSelect( itemId, this ) ; 79} 80 81FCKSpecialCombo.prototype.ClearItems = function () 82{ 83 if ( this.Items ) 84 { 85 for ( var key in this.Items ) 86 this.Items[key] = null ; 87 } 88 89 var itemsholder = this._ItemsHolderEl ; 90 while ( itemsholder.firstChild ) 91 itemsholder.removeChild( itemsholder.firstChild ) ; 92} 93 94FCKSpecialCombo.prototype.AddItem = function( id, html, label, bgColor ) 95{ 96 // <div class="SC_Item" onmouseover="this.className='SC_Item SC_ItemOver';" onmouseout="this.className='SC_Item';"><b>Bold 1</b></div> 97 var oDiv = this._ItemsHolderEl.appendChild( this._Panel.Document.createElement( 'DIV' ) ) ; 98 oDiv.className = oDiv.originalClass = 'SC_Item' ; 99 oDiv.innerHTML = html ; 100 oDiv.FCKItemLabel = label || id ; 101 oDiv.Selected = false ; 102 103 // In IE, the width must be set so the borders are shown correctly when the content overflows. 104 if ( FCKBrowserInfo.IsIE ) 105 oDiv.style.width = '100%' ; 106 107 if ( bgColor ) 108 oDiv.style.backgroundColor = bgColor ; 109 110 FCKTools.AddEventListenerEx( oDiv, 'mouseover', FCKSpecialCombo_ItemOnMouseOver ) ; 111 FCKTools.AddEventListenerEx( oDiv, 'mouseout', FCKSpecialCombo_ItemOnMouseOut ) ; 112 FCKTools.AddEventListenerEx( oDiv, 'click', FCKSpecialCombo_ItemOnClick, [ this, id ] ) ; 113 114 this.Items[ id.toString().toLowerCase() ] = oDiv ; 115 116 return oDiv ; 117} 118 119FCKSpecialCombo.prototype.SelectItem = function( item ) 120{ 121 if ( typeof item == 'string' ) 122 item = this.Items[ item.toString().toLowerCase() ] ; 123 124 if ( item ) 125 { 126 item.className = item.originalClass = 'SC_ItemSelected' ; 127 item.Selected = true ; 128 } 129} 130 131FCKSpecialCombo.prototype.SelectItemByLabel = function( itemLabel, setLabel ) 132{ 133 for ( var id in this.Items ) 134 { 135 var oDiv = this.Items[id] ; 136 137 if ( oDiv.FCKItemLabel == itemLabel ) 138 { 139 oDiv.className = oDiv.originalClass = 'SC_ItemSelected' ; 140 oDiv.Selected = true ; 141 142 if ( setLabel ) 143 this.SetLabel( itemLabel ) ; 144 } 145 } 146} 147 148FCKSpecialCombo.prototype.DeselectAll = function( clearLabel ) 149{ 150 for ( var i in this.Items ) 151 { 152 if ( !this.Items[i] ) continue; 153 this.Items[i].className = this.Items[i].originalClass = 'SC_Item' ; 154 this.Items[i].Selected = false ; 155 } 156 157 if ( clearLabel ) 158 this.SetLabel( '' ) ; 159} 160 161FCKSpecialCombo.prototype.SetLabelById = function( id ) 162{ 163 id = id ? id.toString().toLowerCase() : '' ; 164 165 var oDiv = this.Items[ id ] ; 166 this.SetLabel( oDiv ? oDiv.FCKItemLabel : '' ) ; 167} 168 169FCKSpecialCombo.prototype.SetLabel = function( text ) 170{ 171 text = ( !text || text.length == 0 ) ? ' ' : text ; 172 173 if ( text == this.Label ) 174 return ; 175 176 this.Label = text ; 177 178 var labelEl = this._LabelEl ; 179 if ( labelEl ) 180 { 181 labelEl.innerHTML = text ; 182 183 // It may happen that the label is some HTML, including tags. This 184 // would be a problem because when the user click on those tags, the 185 // combo will get the selection from the editing area. So we must 186 // disable any kind of selection here. 187 FCKTools.DisableSelection( labelEl ) ; 188 } 189} 190 191FCKSpecialCombo.prototype.SetEnabled = function( isEnabled ) 192{ 193 this.Enabled = isEnabled ; 194 195 this._OuterTable.className = isEnabled ? '' : 'SC_FieldDisabled' ; 196} 197 198FCKSpecialCombo.prototype.Create = function( targetElement ) 199{ 200 var oDoc = FCKTools.GetElementDocument( targetElement ) ; 201 var eOuterTable = this._OuterTable = targetElement.appendChild( oDoc.createElement( 'TABLE' ) ) ; 202 eOuterTable.cellPadding = 0 ; 203 eOuterTable.cellSpacing = 0 ; 204 205 eOuterTable.insertRow(-1) ; 206 207 var sClass ; 208 var bShowLabel ; 209 210 switch ( this.Style ) 211 { 212 case FCK_TOOLBARITEM_ONLYICON : 213 sClass = 'TB_ButtonType_Icon' ; 214 bShowLabel = false; 215 break ; 216 case FCK_TOOLBARITEM_ONLYTEXT : 217 sClass = 'TB_ButtonType_Text' ; 218 bShowLabel = false; 219 break ; 220 case FCK_TOOLBARITEM_ICONTEXT : 221 bShowLabel = true; 222 break ; 223 } 224 225 if ( this.Caption && this.Caption.length > 0 && bShowLabel ) 226 { 227 var oCaptionCell = eOuterTable.rows[0].insertCell(-1) ; 228 oCaptionCell.innerHTML = this.Caption ; 229 oCaptionCell.className = 'SC_FieldCaption' ; 230 } 231 232 // Create the main DIV element. 233 var oField = FCKTools.AppendElement( eOuterTable.rows[0].insertCell(-1), 'div' ) ; 234 if ( bShowLabel ) 235 { 236 oField.className = 'SC_Field' ; 237 oField.style.width = this.FieldWidth + 'px' ; 238 oField.innerHTML = '<table width="100%" cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldLabel"><label> </label></td><td class="SC_FieldButton"> </td></tr></tbody></table>' ; 239 240 this._LabelEl = oField.getElementsByTagName('label')[0] ; // Memory Leak 241 this._LabelEl.innerHTML = this.Label ; 242 } 243 else 244 { 245 oField.className = 'TB_Button_Off' ; 246 //oField.innerHTML = '<span className="SC_FieldCaption">' + this.Caption + '<table cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldButton" style="border-left: none;"> </td></tr></tbody></table>' ; 247 //oField.innerHTML = '<table cellpadding="0" cellspacing="0" style="TABLE-LAYOUT: fixed;"><tbody><tr><td class="SC_FieldButton" style="border-left: none;"> </td></tr></tbody></table>' ; 248 249 // Gets the correct CSS class to use for the specified style (param). 250 oField.innerHTML = '<table title="' + this.Tooltip + '" class="' + sClass + '" cellspacing="0" cellpadding="0" border="0">' + 251 '<tr>' + 252 //'<td class="TB_Icon"><img src="' + FCKConfig.SkinPath + 'toolbar/' + this.Command.Name.toLowerCase() + '.gif" width="21" height="21"></td>' + 253 '<td><img class="TB_Button_Padding" src="' + FCK_SPACER_PATH + '" /></td>' + 254 '<td class="TB_Text">' + this.Caption + '</td>' + 255 '<td><img class="TB_Button_Padding" src="' + FCK_SPACER_PATH + '" /></td>' + 256 '<td class="TB_ButtonArrow"><img src="' + FCKConfig.SkinPath + 'images/toolbar.buttonarrow.gif" width="5" height="3"></td>' + 257 '<td><img class="TB_Button_Padding" src="' + FCK_SPACER_PATH + '" /></td>' + 258 '</tr>' + 259 '</table>' ; 260 } 261 262 263 // Events Handlers 264 265 FCKTools.AddEventListenerEx( oField, 'mouseover', FCKSpecialCombo_OnMouseOver, this ) ; 266 FCKTools.AddEventListenerEx( oField, 'mouseout', FCKSpecialCombo_OnMouseOut, this ) ; 267 FCKTools.AddEventListenerEx( oField, 'click', FCKSpecialCombo_OnClick, this ) ; 268 269 FCKTools.DisableSelection( this._Panel.Document.body ) ; 270} 271 272function FCKSpecialCombo_Cleanup() 273{ 274 this._LabelEl = null ; 275 this._OuterTable = null ; 276 this._ItemsHolderEl = null ; 277 this._PanelBox = null ; 278 279 if ( this.Items ) 280 { 281 for ( var key in this.Items ) 282 this.Items[key] = null ; 283 } 284} 285 286function FCKSpecialCombo_OnMouseOver( ev, specialCombo ) 287{ 288 if ( specialCombo.Enabled ) 289 { 290 switch ( specialCombo.Style ) 291 { 292 case FCK_TOOLBARITEM_ONLYICON : 293 this.className = 'TB_Button_On_Over'; 294 break ; 295 case FCK_TOOLBARITEM_ONLYTEXT : 296 this.className = 'TB_Button_On_Over'; 297 break ; 298 case FCK_TOOLBARITEM_ICONTEXT : 299 this.className = 'SC_Field SC_FieldOver' ; 300 break ; 301 } 302 } 303} 304 305function FCKSpecialCombo_OnMouseOut( ev, specialCombo ) 306{ 307 switch ( specialCombo.Style ) 308 { 309 case FCK_TOOLBARITEM_ONLYICON : 310 this.className = 'TB_Button_Off'; 311 break ; 312 case FCK_TOOLBARITEM_ONLYTEXT : 313 this.className = 'TB_Button_Off'; 314 break ; 315 case FCK_TOOLBARITEM_ICONTEXT : 316 this.className='SC_Field' ; 317 break ; 318 } 319} 320 321function FCKSpecialCombo_OnClick( e, specialCombo ) 322{ 323 // For Mozilla we must stop the event propagation to avoid it hiding 324 // the panel because of a click outside of it. 325// if ( e ) 326// { 327// e.stopPropagation() ; 328// FCKPanelEventHandlers.OnDocumentClick( e ) ; 329// } 330 331 if ( specialCombo.Enabled ) 332 { 333 var oPanel = specialCombo._Panel ; 334 var oPanelBox = specialCombo._PanelBox ; 335 var oItemsHolder = specialCombo._ItemsHolderEl ; 336 var iMaxHeight = specialCombo.PanelMaxHeight ; 337 338 if ( specialCombo.OnBeforeClick ) 339 specialCombo.OnBeforeClick( specialCombo ) ; 340 341 // This is a tricky thing. We must call the "Load" function, otherwise 342 // it will not be possible to retrieve "oItemsHolder.offsetHeight" (IE only). 343 if ( FCKBrowserInfo.IsIE ) 344 oPanel.Preload( 0, this.offsetHeight, this ) ; 345 346 if ( oItemsHolder.offsetHeight > iMaxHeight ) 347// { 348 oPanelBox.style.height = iMaxHeight + 'px' ; 349 350// if ( FCKBrowserInfo.IsGecko ) 351// oPanelBox.style.overflow = '-moz-scrollbars-vertical' ; 352// } 353 else 354 oPanelBox.style.height = '' ; 355 356// oPanel.PanelDiv.style.width = specialCombo.PanelWidth + 'px' ; 357 358 oPanel.Show( 0, this.offsetHeight, this ) ; 359 } 360 361// return false ; 362} 363 364/* 365Sample Combo Field HTML output: 366 367<div class="SC_Field" style="width: 80px;"> 368 <table width="100%" cellpadding="0" cellspacing="0" style="table-layout: fixed;"> 369 <tbody> 370 <tr> 371 <td class="SC_FieldLabel"><label> </label></td> 372 <td class="SC_FieldButton"> </td> 373 </tr> 374 </tbody> 375 </table> 376</div> 377*/ 378