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 (function() 7 { 8 /* 9 * It is possible to set things in three different places. 10 * 1. As attributes in the object tag. 11 * 2. As param tags under the object tag. 12 * 3. As attributes in the embed tag. 13 * It is possible for a single attribute to be present in more than one place. 14 * So let's define a mapping between a sementic attribute and its syntactic 15 * equivalents. 16 * Then we'll set and retrieve attribute values according to the mapping, 17 * instead of having to check and set each syntactic attribute every time. 18 * 19 * Reference: http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_12701 20 */ 21 var ATTRTYPE_OBJECT = 1, 22 ATTRTYPE_PARAM = 2, 23 ATTRTYPE_EMBED = 4; 24 25 var attributesMap = 26 { 27 id : [ { type : ATTRTYPE_OBJECT, name : CKEDITOR.env.ie ? '_cke_saved_id' : 'id' } ], 28 classid : [ { type : ATTRTYPE_OBJECT, name : 'classid' } ], 29 codebase : [ { type : ATTRTYPE_OBJECT, name : 'codebase'} ], 30 pluginspage : [ { type : ATTRTYPE_EMBED, name : 'pluginspage' } ], 31 src : [ { type : ATTRTYPE_PARAM, name : 'movie' }, { type : ATTRTYPE_EMBED, name : 'src' } ], 32 name : [ { type : ATTRTYPE_EMBED, name : 'name' } ], 33 align : [ { type : ATTRTYPE_OBJECT, name : 'align' } ], 34 title : [ { type : ATTRTYPE_OBJECT, name : 'title' }, { type : ATTRTYPE_EMBED, name : 'title' } ], 35 'class' : [ { type : ATTRTYPE_OBJECT, name : 'class' }, { type : ATTRTYPE_EMBED, name : 'class'} ], 36 width : [ { type : ATTRTYPE_OBJECT, name : 'width' }, { type : ATTRTYPE_EMBED, name : 'width' } ], 37 height : [ { type : ATTRTYPE_OBJECT, name : 'height' }, { type : ATTRTYPE_EMBED, name : 'height' } ], 38 hSpace : [ { type : ATTRTYPE_OBJECT, name : 'hSpace' }, { type : ATTRTYPE_EMBED, name : 'hSpace' } ], 39 vSpace : [ { type : ATTRTYPE_OBJECT, name : 'vSpace' }, { type : ATTRTYPE_EMBED, name : 'vSpace' } ], 40 style : [ { type : ATTRTYPE_OBJECT, name : 'style' }, { type : ATTRTYPE_EMBED, name : 'style' } ], 41 type : [ { type : ATTRTYPE_EMBED, name : 'type' } ] 42 }; 43 44 var names = [ 'play', 'loop', 'menu', 'quality', 'scale', 'salign', 'wmode', 'bgcolor', 'base', 'flashvars', 'allowScriptAccess', 45 'allowFullScreen' ]; 46 for ( var i = 0 ; i < names.length ; i++ ) 47 attributesMap[ names[i] ] = [ { type : ATTRTYPE_EMBED, name : names[i] }, { type : ATTRTYPE_PARAM, name : names[i] } ]; 48 names = [ 'allowFullScreen', 'play', 'loop', 'menu' ]; 49 for ( var i = 0 ; i < names.length ; i++ ) 50 attributesMap[ names[i] ][0]['default'] = attributesMap[ names[i] ][1]['default'] = true; 51 52 function loadValue( objectNode, embedNode, paramMap ) 53 { 54 var attributes = attributesMap[ this.id ]; 55 if ( !attributes ) 56 return; 57 58 var isCheckbox = ( this instanceof CKEDITOR.ui.dialog.checkbox ); 59 for ( var i = 0 ; i < attributes.length ; i++ ) 60 { 61 var attrDef = attributes[ i ]; 62 switch ( attrDef.type ) 63 { 64 case ATTRTYPE_OBJECT: 65 if ( !objectNode ) 66 continue; 67 if ( objectNode.getAttribute( attrDef.name ) != null ) 68 { 69 var value = objectNode.getAttribute( attrDef.name ); 70 if ( isCheckbox ) 71 this.setValue( value.toLowerCase() == 'true' ); 72 else 73 this.setValue( value ); 74 return; 75 } 76 else if ( isCheckbox ) 77 this.setValue( !!attrDef[ 'default' ] ); 78 case ATTRTYPE_PARAM: 79 if ( !objectNode ) 80 continue; 81 if ( attrDef.name in paramMap ) 82 { 83 var value = paramMap[ attrDef.name ]; 84 if ( isCheckbox ) 85 this.setValue( value.toLowerCase() == 'true' ); 86 else 87 this.setValue( value ); 88 return; 89 } 90 else if ( isCheckbox ) 91 this.setValue( !!attrDef[ 'default' ] ); 92 case ATTRTYPE_EMBED: 93 if ( !embedNode ) 94 continue; 95 if ( embedNode.getAttribute( attrDef.name ) != null ) 96 { 97 var value = embedNode.getAttribute( attrDef.name ); 98 if ( isCheckbox ) 99 this.setValue( value.toLowerCase() == 'true' ); 100 else 101 this.setValue( value ); 102 return; 103 } 104 else if ( isCheckbox ) 105 this.setValue( !!attrDef[ 'default' ] ); 106 default: 107 } 108 } 109 } 110 111 function commitValue( objectNode, embedNode, paramMap ) 112 { 113 var attributes = attributesMap[ this.id ]; 114 if ( !attributes ) 115 return; 116 117 var isRemove = ( this.getValue() === '' ), 118 isCheckbox = ( this instanceof CKEDITOR.ui.dialog.checkbox ); 119 120 for ( var i = 0 ; i < attributes.length ; i++ ) 121 { 122 var attrDef = attributes[i]; 123 switch ( attrDef.type ) 124 { 125 case ATTRTYPE_OBJECT: 126 if ( !objectNode ) 127 continue; 128 var value = this.getValue(); 129 if ( isRemove || isCheckbox && value === attrDef[ 'default' ] ) 130 objectNode.removeAttribute( attrDef.name ); 131 else 132 objectNode.setAttribute( attrDef.name, value ); 133 break; 134 case ATTRTYPE_PARAM: 135 if ( !objectNode ) 136 continue; 137 var value = this.getValue(); 138 if ( isRemove || isCheckbox && value === attrDef[ 'default' ] ) 139 { 140 if ( attrDef.name in paramMap ) 141 paramMap[ attrDef.name ].remove(); 142 } 143 else 144 { 145 if ( attrDef.name in paramMap ) 146 paramMap[ attrDef.name ].setAttribute( 'value', value ); 147 else 148 { 149 var param = CKEDITOR.dom.element.createFromHtml( '<cke:param></cke:param>', objectNode.getDocument() ); 150 param.setAttributes( { name : attrDef.name, value : value } ); 151 if ( objectNode.getChildCount() < 1 ) 152 param.appendTo( objectNode ); 153 else 154 param.insertBefore( objectNode.getFirst() ); 155 } 156 } 157 break; 158 case ATTRTYPE_EMBED: 159 if ( !embedNode ) 160 continue; 161 var value = this.getValue(); 162 if ( isRemove || isCheckbox && value === attrDef[ 'default' ]) 163 embedNode.removeAttribute( attrDef.name ); 164 else 165 embedNode.setAttribute( attrDef.name, value ); 166 default: 167 } 168 } 169 } 170 171 CKEDITOR.dialog.add( 'flash', function( editor ) 172 { 173 var makeObjectTag = !editor.config.flashEmbedTagOnly, 174 makeEmbedTag = editor.config.flashAddEmbedTag || editor.config.flashEmbedTagOnly; 175 176 var previewAreaHtml = '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.image.preview ) +'<br>' + 177 '<div id="FlashPreviewLoader" style="display:none"><div class="loading"> </div></div>' + 178 '<div id="FlashPreviewBox"></div></div>'; 179 180 return { 181 title : editor.lang.flash.title, 182 minWidth : 450, 183 minHeight : 400, 184 onLoad : function() 185 { 186 if ( editor.config.flashUploadTab == false ) 187 this.hidePage( 'Upload' ); // Hide Upload tab. 188 189 if ( editor.config.flashBrowseServer == false ) 190 this.getContentElement( 'info', 'browse' ).getElement().hide(); 191 }, 192 onShow : function() 193 { 194 // Clear previously saved elements. 195 this.fakeImage = this.objectNode = this.embedNode = null; 196 197 // Try to detect any embed or object tag that has Flash parameters. 198 var fakeImage = this.getSelectedElement(); 199 if ( fakeImage && fakeImage.getAttribute( '_cke_real_element_type' ) && fakeImage.getAttribute( '_cke_real_element_type' ) == 'flash' ) 200 { 201 this.fakeImage = fakeImage; 202 203 var realElement = editor.restoreRealElement( fakeImage ), 204 objectNode = null, embedNode = null, paramMap = {}; 205 if ( realElement.getName() == 'cke:object' ) 206 { 207 objectNode = realElement; 208 var embedList = objectNode.getElementsByTag( 'embed', 'cke' ); 209 if ( embedList.count() > 0 ) 210 embedNode = embedList.getItem( 0 ); 211 var paramList = objectNode.getElementsByTag( 'param', 'cke' ); 212 for ( var i = 0, length = paramList.count() ; i < length ; i++ ) 213 { 214 var item = paramList.getItem( i ), 215 name = item.getAttribute( 'name' ), 216 value = item.getAttribute( 'value' ); 217 paramMap[ name ] = value; 218 } 219 } 220 else if ( realElement.getName() == 'cke:embed' ) 221 embedNode = realElement; 222 223 this.objectNode = objectNode; 224 this.embedNode = embedNode; 225 226 this.setupContent( objectNode, embedNode, paramMap, fakeImage ); 227 } 228 }, 229 onOk : function() 230 { 231 // If there's no selected object or embed, create one. Otherwise, reuse the 232 // selected object and embed nodes. 233 var objectNode = null, 234 embedNode = null, 235 paramMap = null; 236 if ( !this.fakeImage ) 237 { 238 if ( makeObjectTag ) 239 { 240 objectNode = CKEDITOR.dom.element.createFromHtml( '<cke:object></cke:object>', editor.document ); 241 var attributes = { 242 classid : 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000', 243 codebase : 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0' 244 }; 245 objectNode.setAttributes( attributes ); 246 } 247 if ( makeEmbedTag ) 248 { 249 embedNode = CKEDITOR.dom.element.createFromHtml( '<cke:embed></cke:embed>', editor.document ); 250 embedNode.setAttributes( 251 { 252 type : 'application/x-shockwave-flash', 253 pluginspage : 'http://www.macromedia.com/go/getflashplayer' 254 } ); 255 if ( objectNode ) 256 embedNode.appendTo( objectNode ); 257 } 258 } 259 else 260 { 261 objectNode = this.objectNode; 262 embedNode = this.embedNode; 263 } 264 265 // Produce the paramMap if there's an object tag. 266 if ( objectNode ) 267 { 268 paramMap = {}; 269 var paramList = objectNode.getElementsByTag( 'param', 'cke' ); 270 for ( var i = 0, length = paramList.count() ; i < length ; i++ ) 271 paramMap[ paramList.getItem( i ).getAttribute( 'name' ) ] = paramList.getItem( i ); 272 } 273 274 // Apply or remove flash parameters. 275 var extraStyles = {}; 276 this.commitContent( objectNode, embedNode, paramMap, extraStyles ); 277 278 // Refresh the fake image. 279 var newFakeImage = editor.createFakeElement( objectNode || embedNode, 'cke_flash', 'flash', true ); 280 newFakeImage.setStyles( extraStyles ); 281 if ( this.fakeImage ) 282 newFakeImage.replace( this.fakeImage ); 283 else 284 { 285 this.restoreSelection(); 286 editor.insertElement( newFakeImage ); 287 } 288 }, 289 contents : [ 290 { 291 id : 'info', 292 label : editor.lang.common.generalTab, 293 accessKey : 'I', 294 elements : 295 [ 296 { 297 type : 'vbox', 298 padding : 0, 299 children : 300 [ 301 { 302 type : 'html', 303 html : '<span>' + CKEDITOR.tools.htmlEncode( editor.lang.image.url ) + '</span>' 304 }, 305 { 306 type : 'hbox', 307 widths : [ '280px', '110px' ], 308 align : 'right', 309 children : 310 [ 311 { 312 id : 'src', 313 type : 'text', 314 label : '', 315 validate : CKEDITOR.dialog.validate.notEmpty( editor.lang.flash.validateSrc ), 316 setup : loadValue, 317 commit : commitValue, 318 onLoad : function() 319 { 320 var dialog = this.getDialog(); 321 var previewElement = dialog.getContentElement( 'info', 'preview' ).getElement().getChild( 3 ); 322 this.getInputElement().on( 'change', function() 323 { 324 previewElement.setHtml( '<embed height="100%" width="100%" src="' 325 + CKEDITOR.tools.htmlEncode( this.getValue() ) 326 + '" type="application/x-shockwave-flash"></embed>' ); 327 } ); 328 } 329 }, 330 { 331 type : 'button', 332 id : 'browse', 333 align : 'center', 334 label : editor.lang.common.browseServer 335 } 336 ] 337 } 338 ] 339 }, 340 { 341 type : 'hbox', 342 widths : [ '25%', '25%', '25%', '25%', '25%' ], 343 children : 344 [ 345 { 346 type : 'text', 347 id : 'width', 348 label : editor.lang.flash.width, 349 validate : CKEDITOR.dialog.validate.integer( editor.lang.flash.validateWidth ), 350 setup : function( objectNode, embedNode, paramMap, fakeImage ) 351 { 352 loadValue.apply( this, arguments ); 353 if ( fakeImage ) 354 { 355 var fakeImageWidth = parseInt( fakeImage.$.style.width, 10 ); 356 if ( !isNaN( fakeImageWidth ) ) 357 this.setValue( fakeImageWidth ); 358 } 359 }, 360 commit : function( objectNode, embedNode, paramMap, extraStyles ) 361 { 362 commitValue.apply( this, arguments ); 363 if ( this.getValue() != '' ) 364 extraStyles.width = this.getValue() + 'px'; 365 } 366 }, 367 { 368 type : 'text', 369 id : 'height', 370 label : editor.lang.flash.height, 371 validate : CKEDITOR.dialog.validate.integer( editor.lang.flash.validateHeight ), 372 setup : function( objectNode, embedNode, paramMap, fakeImage ) 373 { 374 loadValue.apply( this, arguments ); 375 if ( fakeImage ) 376 { 377 var fakeImageHeight = parseInt( fakeImage.$.style.height, 10 ); 378 if ( !isNaN( fakeImageHeight ) ) 379 this.setValue( fakeImageHeight ); 380 } 381 }, 382 commit : function( objectNode, embedNode, paramMap, extraStyles ) 383 { 384 commitValue.apply( this, arguments ); 385 if ( this.getValue() != '' ) 386 extraStyles.height = this.getValue() + 'px'; 387 } 388 }, 389 { 390 type : 'text', 391 id : 'hSpace', 392 label : editor.lang.flash.hSpace, 393 validate : CKEDITOR.dialog.validate.integer( editor.lang.flash.validateHSpace ), 394 setup : loadValue, 395 commit : commitValue 396 }, 397 { 398 type : 'text', 399 id : 'vSpace', 400 label : editor.lang.flash.vSpace, 401 validate : CKEDITOR.dialog.validate.integer( editor.lang.flash.validateVSpace ), 402 setup : loadValue, 403 commit : commitValue 404 } 405 ] 406 }, 407 408 { 409 type : 'vbox', 410 children : 411 [ 412 { 413 type : 'html', 414 id : 'preview', 415 style : 'width:95%;', 416 html : previewAreaHtml 417 } 418 ] 419 } 420 ] 421 }, 422 { 423 id : 'Upload', 424 label : editor.lang.common.upload, 425 elements : 426 [ 427 { 428 type : 'file', 429 id : 'upload', 430 label : editor.lang.common.upload, 431 action : editor.config.image_uploadAction, 432 size : 38 433 }, 434 { 435 type : 'fileButton', 436 id : 'uploadButton', 437 label : editor.lang.common.uploadSubmit, 438 'for' : [ 'Upload', 'upload' ] 439 } 440 ] 441 }, 442 { 443 id : 'properties', 444 label : editor.lang.flash.propertiesTab, 445 elements : 446 [ 447 { 448 type : 'hbox', 449 widths : [ '50%', '50%' ], 450 children : 451 [ 452 { 453 id : 'scale', 454 type : 'select', 455 label : editor.lang.flash.scale, 456 'default' : '', 457 style : 'width : 100%;', 458 items : 459 [ 460 [ editor.lang.common.notSet , ''], 461 [ editor.lang.flash.scaleAll, 'showall' ], 462 [ editor.lang.flash.scaleNoBorder, 'noborder' ], 463 [ editor.lang.flash.scaleFit, 'exactfit' ] 464 ], 465 setup : loadValue, 466 commit : commitValue 467 }, 468 { 469 id : 'allowScriptAccess', 470 type : 'select', 471 label : editor.lang.flash.access, 472 'default' : '', 473 style : 'width : 100%;', 474 items : 475 [ 476 [ editor.lang.common.notSet , ''], 477 [ editor.lang.flash.accessAlways, 'always' ], 478 [ editor.lang.flash.accessSameDomain, 'samedomain' ], 479 [ editor.lang.flash.accessNever, 'never' ] 480 ], 481 setup : loadValue, 482 commit : commitValue 483 } 484 ] 485 }, 486 { 487 type : 'hbox', 488 widths : [ '50%', '50%' ], 489 children : 490 [ 491 { 492 id : 'wmode', 493 type : 'select', 494 label : editor.lang.flash.windowMode, 495 'default' : '', 496 style : 'width : 100%;', 497 items : 498 [ 499 [ editor.lang.common.notSet , ''], 500 [ 'window' ], 501 [ 'opaque' ], 502 [ 'transparent' ] 503 ], 504 setup : loadValue, 505 commit : commitValue 506 }, 507 { 508 id : 'quality', 509 type : 'select', 510 label : editor.lang.flash.quality, 511 'default' : 'high', 512 style : 'width : 100%;', 513 items : 514 [ 515 [ editor.lang.common.notSet , ''], 516 [ 'best' ], 517 [ 'high' ], 518 [ 'autohigh' ], 519 [ 'medium' ], 520 [ 'autolow' ], 521 [ 'low' ] 522 ], 523 setup : loadValue, 524 commit : commitValue 525 }, 526 ] 527 }, 528 { 529 type : 'hbox', 530 widths : [ '50%', '50%' ], 531 children : 532 [ 533 { 534 id : 'align', 535 type : 'select', 536 label : editor.lang.flash.align, 537 'default' : '', 538 style : 'width : 100%;', 539 items : 540 [ 541 [ editor.lang.common.notSet , ''], 542 [ editor.lang.image.alignLeft , 'left'], 543 [ editor.lang.image.alignAbsBottom , 'absBottom'], 544 [ editor.lang.image.alignAbsMiddle , 'absMiddle'], 545 [ editor.lang.image.alignBaseline , 'baseline'], 546 [ editor.lang.image.alignBottom , 'bottom'], 547 [ editor.lang.image.alignMiddle , 'middle'], 548 [ editor.lang.image.alignRight , 'right'], 549 [ editor.lang.image.alignTextTop , 'textTop'], 550 [ editor.lang.image.alignTop , 'top'] 551 ], 552 setup : loadValue, 553 commit : commitValue 554 }, 555 { 556 type : 'html', 557 html : '<div></div>' 558 } 559 ] 560 }, 561 { 562 type : 'vbox', 563 padding : 0, 564 children : 565 [ 566 { 567 type : 'html', 568 html : CKEDITOR.tools.htmlEncode( editor.lang.flash.flashvars ) 569 }, 570 { 571 type : 'checkbox', 572 id : 'menu', 573 label : editor.lang.flash.chkMenu, 574 'default' : true, 575 setup : loadValue, 576 commit : commitValue 577 }, 578 { 579 type : 'checkbox', 580 id : 'play', 581 label : editor.lang.flash.chkPlay, 582 'default' : true, 583 setup : loadValue, 584 commit : commitValue 585 }, 586 { 587 type : 'checkbox', 588 id : 'loop', 589 label : editor.lang.flash.chkLoop, 590 'default' : true, 591 setup : loadValue, 592 commit : commitValue 593 }, 594 { 595 type : 'checkbox', 596 id : 'allowFullScreen', 597 label : editor.lang.flash.chkFull, 598 'default' : true, 599 setup : loadValue, 600 commit : commitValue 601 } 602 ] 603 } 604 ] 605 }, 606 { 607 id : 'advanced', 608 label : editor.lang.common.advancedTab, 609 elements : 610 [ 611 { 612 type : 'hbox', 613 widths : [ '45%', '55%' ], 614 children : 615 [ 616 { 617 type : 'text', 618 id : 'id', 619 label : editor.lang.common.id, 620 setup : loadValue, 621 commit : commitValue 622 }, 623 { 624 type : 'text', 625 id : 'title', 626 label : editor.lang.common.advisoryTitle, 627 setup : loadValue, 628 commit : commitValue 629 } 630 ] 631 }, 632 { 633 type : 'hbox', 634 widths : [ '45%', '55%' ], 635 children : 636 [ 637 { 638 type : 'text', 639 id : 'bgcolor', 640 label : editor.lang.flash.bgcolor, 641 setup : loadValue, 642 commit : commitValue 643 }, 644 { 645 type : 'text', 646 id : 'class', 647 label : editor.lang.common.cssClass, 648 setup : loadValue, 649 commit : commitValue 650 } 651 ] 652 }, 653 { 654 type : 'text', 655 id : 'style', 656 label : editor.lang.common.cssStyle, 657 setup : loadValue, 658 commit : commitValue 659 } 660 ] 661 } 662 ] 663 }; 664 } ); 665 })(); 666