/** * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.html or http://ckeditor.com/license */ CKEDITOR.dialog.add( 'docProps', function( editor ) { var lang = editor.lang.docprops, langCommon = editor.lang.common, metaHash = {}; function getDialogValue( dialogName, callback ) { var onOk = function() { releaseHandlers( this ); callback( this, this._.parentDialog ); }; var releaseHandlers = function( dialog ) { dialog.removeListener( 'ok', onOk ); dialog.removeListener( 'cancel', releaseHandlers ); }; var bindToDialog = function( dialog ) { dialog.on( 'ok', onOk ); dialog.on( 'cancel', releaseHandlers ); }; editor.execCommand( dialogName ); if ( editor._.storedDialogs.colordialog ) bindToDialog( editor._.storedDialogs.colordialog ); else { CKEDITOR.on( 'dialogDefinition', function( e ) { if ( e.data.name != dialogName ) return; var definition = e.data.definition; e.removeListener(); definition.onLoad = CKEDITOR.tools.override( definition.onLoad, function( orginal ) { return function() { bindToDialog( this ); definition.onLoad = orginal; if ( typeof orginal == 'function' ) orginal.call( this ); }; }); }); } } function handleOther() { var dialog = this.getDialog(), other = dialog.getContentElement( 'general', this.id + 'Other' ); if ( !other ) return; if ( this.getValue() == 'other' ) { other.getInputElement().removeAttribute( 'readOnly' ); other.focus(); other.getElement().removeClass( 'cke_disabled' ); } else { other.getInputElement().setAttribute( 'readOnly', true ); other.getElement().addClass( 'cke_disabled' ); } } function commitMeta( name, isHttp, value ) { return function( doc, html, head ) { var hash = metaHash, val = typeof value != 'undefined' ? value : this.getValue(); if ( !val && ( name in hash ) ) hash[ name ].remove(); else if ( val && ( name in hash ) ) hash[ name ].setAttribute( 'content', val ); else if ( val ) { var meta = new CKEDITOR.dom.element( 'meta', editor.document ); meta.setAttribute( isHttp ? 'http-equiv' : 'name', name ); meta.setAttribute( 'content', val ); head.append( meta ); } }; } function setupMeta( name, ret ) { return function() { var hash = metaHash, result = ( name in hash ) ? hash[ name ].getAttribute( 'content' ) || '' : ''; if ( ret ) return result; this.setValue( result ); return null; }; } function commitMargin( name ) { return function( doc, html, head, body ) { body.removeAttribute( 'margin' + name ); var val = this.getValue(); if ( val !== '' ) body.setStyle( 'margin-' + name, CKEDITOR.tools.cssLength( val ) ); else body.removeStyle( 'margin-' + name ); }; } function createMetaHash( doc ) { var hash = {}, metas = doc.getElementsByTag( 'meta' ), count = metas.count(); for ( var i = 0; i < count; i++ ) { var meta = metas.getItem( i ); hash[ meta.getAttribute( meta.hasAttribute( 'http-equiv' ) ? 'http-equiv' : 'name' ).toLowerCase() ] = meta; } return hash; } // We cannot just remove the style from the element, as it might be affected from non-inline stylesheets. // To get the proper result, we should manually set the inline style to its default value. function resetStyle( element, prop, resetVal ) { element.removeStyle( prop ); if ( element.getComputedStyle( prop ) != resetVal ) element.setStyle( prop, resetVal ); } // Utilty to shorten the creation of color fields in the dialog. var colorField = function( id, label, fieldProps ) { return { type: 'hbox', padding: 0, widths: [ '60%', '40%' ], children: [ CKEDITOR.tools.extend({ type: 'text', id: id, label: lang[ label ] }, fieldProps || {}, 1 ), { type: 'button', id: id + 'Choose', label: lang.chooseColor, className: 'colorChooser', onClick: function() { var self = this; getDialogValue( 'colordialog', function( colorDialog ) { var dialog = self.getDialog(); dialog.getContentElement( dialog._.currentTabId, id ).setValue( colorDialog.getContentElement( 'picker', 'selectedColor' ).getValue() ); }); } } ] }; }; var previewSrc = 'javascript:' + 'void((function(){' + encodeURIComponent( 'document.open();' + ( CKEDITOR.env.isCustomDomain() ? 'document.domain=\'' + document.domain + '\';' : '' ) + 'document.write( \'' + lang.previewHtml + '\' );' + 'document.close();' ) + '})())'; return { title: lang.title, minHeight: 330, minWidth: 500, onShow: function() { var doc = editor.document, html = doc.getElementsByTag( 'html' ).getItem( 0 ), head = doc.getHead(), body = doc.getBody(); metaHash = createMetaHash( doc ); this.setupContent( doc, html, head, body ); }, onHide: function() { metaHash = {}; }, onOk: function() { var doc = editor.document, html = doc.getElementsByTag( 'html' ).getItem( 0 ), head = doc.getHead(), body = doc.getBody(); this.commitContent( doc, html, head, body ); }, contents: [ { id: 'general', label: langCommon.generalTab, elements: [ { type: 'text', id: 'title', label: lang.docTitle, setup: function( doc ) { this.setValue( doc.getElementsByTag( 'title' ).getItem( 0 ).data( 'cke-title' ) ); }, commit: function( doc, html, head, body, isPreview ) { if ( isPreview ) return; doc.getElementsByTag( 'title' ).getItem( 0 ).data( 'cke-title', this.getValue() ); } }, { type: 'hbox', children: [ { type: 'select', id: 'dir', label: langCommon.langDir, style: 'width: 100%', items: [ [ langCommon.notSet, '' ], [ langCommon.langDirLtr, 'ltr' ], [ langCommon.langDirRtl, 'rtl' ] ], setup: function( doc, html, head, body ) { this.setValue( body.getDirection() || '' ); }, commit: function( doc, html, head, body ) { var val = this.getValue(); if ( val ) body.setAttribute( 'dir', val ); else body.removeAttribute( 'dir' ); body.removeStyle( 'direction' ); } }, { type: 'text', id: 'langCode', label: langCommon.langCode, setup: function( doc, html ) { this.setValue( html.getAttribute( 'xml:lang' ) || html.getAttribute( 'lang' ) || '' ); }, commit: function( doc, html, head, body, isPreview ) { if ( isPreview ) return; var val = this.getValue(); if ( val ) html.setAttributes({ 'xml:lang': val, lang: val } ); else html.removeAttributes( { 'xml:lang':1,lang:1 } ); } } ] }, { type: 'hbox', children: [ { type: 'select', id: 'charset', label: lang.charset, style: 'width: 100%', items: [ [ langCommon.notSet, '' ], [ lang.charsetASCII, 'us-ascii' ], [ lang.charsetCE, 'iso-8859-2' ], [ lang.charsetCT, 'big5' ], [ lang.charsetCR, 'iso-8859-5' ], [ lang.charsetGR, 'iso-8859-7' ], [ lang.charsetJP, 'iso-2022-jp' ], [ lang.charsetKR, 'iso-2022-kr' ], [ lang.charsetTR, 'iso-8859-9' ], [ lang.charsetUN, 'utf-8' ], [ lang.charsetWE, 'iso-8859-1' ], [ lang.other, 'other' ] ], 'default': '', onChange: function() { this.getDialog().selectedCharset = this.getValue() != 'other' ? this.getValue() : ''; handleOther.call( this ); }, setup: function() { this.metaCharset = ( 'charset' in metaHash ); var func = setupMeta( this.metaCharset ? 'charset' : 'content-type', 1, 1 ), val = func.call( this ); !this.metaCharset && val.match( /charset=[^=]+$/ ) && ( val = val.substring( val.indexOf( '=' ) + 1 ) ); if ( val ) { this.setValue( val.toLowerCase() ); if ( !this.getValue() ) { this.setValue( 'other' ); var other = this.getDialog().getContentElement( 'general', 'charsetOther' ); other && other.setValue( val ); } this.getDialog().selectedCharset = val; } handleOther.call( this ); }, commit: function( doc, html, head, body, isPreview ) { if ( isPreview ) return; var value = this.getValue(), other = this.getDialog().getContentElement( 'general', 'charsetOther' ); value == 'other' && ( value = other ? other.getValue() : '' ); value && !this.metaCharset && ( value = ( metaHash[ 'content-type' ] ? metaHash[ 'content-type' ].getAttribute( 'content' ).split( ';' )[ 0 ] : 'text/html' ) + '; charset=' + value ); var func = commitMeta( this.metaCharset ? 'charset' : 'content-type', 1, value ); func.call( this, doc, html, head ); } }, { type: 'text', id: 'charsetOther', label: lang.charsetOther, onChange: function() { this.getDialog().selectedCharset = this.getValue(); } } ] }, { type: 'hbox', children: [ { type: 'select', id: 'docType', label: lang.docType, style: 'width: 100%', items: [ [ langCommon.notSet, '' ], [ 'XHTML 1.1', '' ], [ 'XHTML 1.0 Transitional', '' ], [ 'XHTML 1.0 Strict', '' ], [ 'XHTML 1.0 Frameset', '' ], [ 'HTML 5', '' ], [ 'HTML 4.01 Transitional', '' ], [ 'HTML 4.01 Strict', '' ], [ 'HTML 4.01 Frameset', '' ], [ 'HTML 3.2', '' ], [ 'HTML 2.0', '' ], [ lang.other, 'other' ] ], onChange: handleOther, setup: function() { if ( editor.docType ) { this.setValue( editor.docType ); if ( !this.getValue() ) { this.setValue( 'other' ); var other = this.getDialog().getContentElement( 'general', 'docTypeOther' ); other && other.setValue( editor.docType ); } } handleOther.call( this ); }, commit: function( doc, html, head, body, isPreview ) { if ( isPreview ) return; var value = this.getValue(), other = this.getDialog().getContentElement( 'general', 'docTypeOther' ); editor.docType = value == 'other' ? ( other ? other.getValue() : '' ) : value; } }, { type: 'text', id: 'docTypeOther', label: lang.docTypeOther } ] }, { type: 'checkbox', id: 'xhtmlDec', label: lang.xhtmlDec, setup: function() { this.setValue( !!editor.xmlDeclaration ); }, commit: function( doc, html, head, body, isPreview ) { if ( isPreview ) return; if ( this.getValue() ) { editor.xmlDeclaration = ''; html.setAttribute( 'xmlns', 'http://www.w3.org/1999/xhtml' ); } else { editor.xmlDeclaration = ''; html.removeAttribute( 'xmlns' ); } } } ] }, { id: 'design', label: lang.design, elements: [ { type: 'hbox', widths: [ '60%', '40%' ], children: [ { type: 'vbox', children: [ colorField( 'txtColor', 'txtColor', { setup: function( doc, html, head, body ) { this.setValue( body.getComputedStyle( 'color' ) ); }, commit: function( doc, html, head, body, isPreview ) { if ( this.isChanged() || isPreview ) { body.removeAttribute( 'text' ); var val = this.getValue(); if ( val ) body.setStyle( 'color', val ); else body.removeStyle( 'color' ); } } }), colorField( 'bgColor', 'bgColor', { setup: function( doc, html, head, body ) { var val = body.getComputedStyle( 'background-color' ) || ''; this.setValue( val == 'transparent' ? '' : val ); }, commit: function( doc, html, head, body, isPreview ) { if ( this.isChanged() || isPreview ) { body.removeAttribute( 'bgcolor' ); var val = this.getValue(); if ( val ) body.setStyle( 'background-color', val ); else resetStyle( body, 'background-color', 'transparent' ); } } }), { type: 'hbox', widths: [ '60%', '40%' ], padding: 1, children: [ { type: 'text', id: 'bgImage', label: lang.bgImage, setup: function( doc, html, head, body ) { var val = body.getComputedStyle( 'background-image' ) || ''; if ( val == 'none' ) val = ''; else { val = val.replace( /url\(\s*(["']?)\s*([^\)]*)\s*\1\s*\)/i, function( match, quote, url ) { return url; }); } this.setValue( val ); }, commit: function( doc, html, head, body ) { body.removeAttribute( 'background' ); var val = this.getValue(); if ( val ) body.setStyle( 'background-image', 'url(' + val + ')' ); else resetStyle( body, 'background-image', 'none' ); } }, { type: 'button', id: 'bgImageChoose', label: langCommon.browseServer, style: 'display:inline-block;margin-top:10px;', hidden: true, filebrowser: 'design:bgImage' } ] }, { type: 'checkbox', id: 'bgFixed', label: lang.bgFixed, setup: function( doc, html, head, body ) { this.setValue( body.getComputedStyle( 'background-attachment' ) == 'fixed' ); }, commit: function( doc, html, head, body ) { if ( this.getValue() ) body.setStyle( 'background-attachment', 'fixed' ); else resetStyle( body, 'background-attachment', 'scroll' ); } } ] }, { type: 'vbox', children: [ { type: 'html', id: 'marginTitle', html: '
' + lang.margin + '
' }, { type: 'text', id: 'marginTop', label: lang.marginTop, style: 'width: 80px; text-align: center', align: 'center', inputStyle: 'text-align: center', setup: function( doc, html, head, body ) { this.setValue( body.getStyle( 'margin-top' ) || body.getAttribute( 'margintop' ) || '' ); }, commit: commitMargin( 'top' ) }, { type: 'hbox', children: [ { type: 'text', id: 'marginLeft', label: lang.marginLeft, style: 'width: 80px; text-align: center', align: 'center', inputStyle: 'text-align: center', setup: function( doc, html, head, body ) { this.setValue( body.getStyle( 'margin-left' ) || body.getAttribute( 'marginleft' ) || '' ); }, commit: commitMargin( 'left' ) }, { type: 'text', id: 'marginRight', label: lang.marginRight, style: 'width: 80px; text-align: center', align: 'center', inputStyle: 'text-align: center', setup: function( doc, html, head, body ) { this.setValue( body.getStyle( 'margin-right' ) || body.getAttribute( 'marginright' ) || '' ); }, commit: commitMargin( 'right' ) } ] }, { type: 'text', id: 'marginBottom', label: lang.marginBottom, style: 'width: 80px; text-align: center', align: 'center', inputStyle: 'text-align: center', setup: function( doc, html, head, body ) { this.setValue( body.getStyle( 'margin-bottom' ) || body.getAttribute( 'marginbottom' ) || '' ); }, commit: commitMargin( 'bottom' ) } ] } ] } ] }, { id: 'meta', label: lang.meta, elements: [ { type: 'textarea', id: 'metaKeywords', label: lang.metaKeywords, setup: setupMeta( 'keywords' ), commit: commitMeta( 'keywords' ) }, { type: 'textarea', id: 'metaDescription', label: lang.metaDescription, setup: setupMeta( 'description' ), commit: commitMeta( 'description' ) }, { type: 'text', id: 'metaAuthor', label: lang.metaAuthor, setup: setupMeta( 'author' ), commit: commitMeta( 'author' ) }, { type: 'text', id: 'metaCopyright', label: lang.metaCopyright, setup: setupMeta( 'copyright' ), commit: commitMeta( 'copyright' ) } ] }, { id: 'preview', label: langCommon.preview, elements: [ { type: 'html', id: 'previewHtml', html: '', onLoad: function() { this.getDialog().on( 'selectPage', function( ev ) { if ( ev.data.page == 'preview' ) { var self = this; setTimeout( function() { var doc = CKEDITOR.document.getById( 'cke_docProps_preview_iframe' ).getFrameDocument(), html = doc.getElementsByTag( 'html' ).getItem( 0 ), head = doc.getHead(), body = doc.getBody(); self.commitContent( doc, html, head, body, 1 ); }, 50 ); } }); CKEDITOR.document.getById( 'cke_docProps_preview_iframe' ).getAscendant( 'table' ).setStyle( 'height', '100%' ); } } ] } ] }; });