Index: _source/lang/en.js =================================================================== --- _source/lang/en.js (revision 6658) +++ _source/lang/en.js (working copy) @@ -749,5 +749,50 @@ { ltr : 'Text direction from left to right', rtl : 'Text direction from right to left' + }, + + docprops : + { + label : 'Document Properties', + title : 'Document Properties', + background : 'Background', + colors : 'Colors', + meta : 'Meta Tags', + chooseColor : 'Choose', + other : 'Other...', + docTitle : 'Page Title', + charset : 'Character Set Encoding', + charsetOther : 'Other Character Set Encoding', + charsetASCII : 'ASCII', + charsetCE : 'Central European', + charsetCT : 'Chinese Traditional (Big5)', + charsetCR : 'Cyrillic', + charsetGR : 'Greek', + charsetJP : 'Japanese', + charsetKR : 'Korean', + charsetTR : 'Turkish', + charsetUN : 'Unicode (UTF-8)', + charsetWE : 'Westren European', + docType : 'Document Type Heading', + docTypeOther : 'Other Document Type Heading', + xhtmlDec : 'Include XHTML Declarations', + bgColor : 'Background Color', + bgImage : 'Background Image URL', + bgFixed : 'Nonscrolling (Fixed) Background', + txtColor : 'Text Color', + linkColor : 'Link Color', + hLinkColor : 'Hover Link Color', + vLinkColor : 'Visited Link Color', + aLinkColor : 'Active Link Color', + margin : 'Page Margins', + marginTop : 'Top', + marginLeft : 'Left', + marginRight : 'Right', + marginBottom : 'Bottom', + metaKeywords : 'Document Indexing Keywords (comma separated)', + metaDescription : 'Document Description', + metaAuthor : 'Author', + metaCopyright : 'Copyright', + previewHtml : '
This is some sample text. You are using CKEditor.
' } }; Index: _source/plugins/dialogui/plugin.js =================================================================== --- _source/plugins/dialogui/plugin.js (revision 6658) +++ _source/plugins/dialogui/plugin.js (working copy) @@ -618,7 +618,7 @@ for ( var i = 0, item ; i < elementDefinition.items.length && ( item = elementDefinition.items[i] ) ; i++ ) { innerHTML.push( ' ', + CKEDITOR.tools.htmlEncode( item[1] !== undefined ? item[1] : item[0] ).replace( /"/g, '"' ), '" /> ', CKEDITOR.tools.htmlEncode( item[0] ) ); } Index: _source/plugins/docprops/dialogs/docprops.js =================================================================== --- _source/plugins/docprops/dialogs/docprops.js (revision 0) +++ _source/plugins/docprops/dialogs/docprops.js (revision 0) @@ -0,0 +1,645 @@ +/* +Copyright (c) 2003-2011, 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; + + 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 = this.getDialog().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 = this.getDialog().metaHash, + result = ( name in hash ) ? hash[ name ].getAttribute( 'content' ) || '' : ''; + if ( ret ) + return result; + this.setValue( result ); + }; + } + 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, btnProps ) + { + return { + type : 'hbox', + padding : 0, + widths : [ '60%', '40%' ], + children : [ + CKEDITOR.tools.extend( { + type : 'text', + id : id, + label : lang[ label ] + }, fieldProps || {}, 1 ), + CKEDITOR.tools.extend( { + 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() + ); + }); + } + }, btnProps || {}, 1 ) + ] + }; + }; + 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(); + this.metaHash = createMetaHash( doc ); + this.setupContent( doc, html, head, body ); + }, + onHide : function() + { + this.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() + { + var func = setupMeta( 'content-type', 1, 1 ), + val = func.call( this ), + match = val.match( /charset=[^=]+$/ ); + if ( match ) + { + val = val.substring( val.indexOf( '=' ) + 1 ); + 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' ); + var func = commitMeta( 'content-type', 1, 'text/html; charset=' + ( value == 'other' ? ( other ? other.getValue() : '' ) : 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 : 'bg', + label : lang.background, + elements : [ + 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 ) + { + 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%' ], + 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 : 'bg: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' ); + } + } + ] + }, + { + id : 'colors', + label : lang.colors, + elements : [ + { + type : 'hbox', + widths : [ '60%', '40%' ], + children : [ + { + type : 'vbox', + children : [ + colorField( 'txtColor', 'txtColor' ), + colorField( 'linkColor', 'linkColor' ), + colorField( 'hoverLinkColor', 'hLinkColor' ), + colorField( 'visitedLinkColor', 'vLinkColor' ), + colorField( 'activeLinkColor', 'aLinkColor' ) + ] + }, + { + type : 'vbox', + children : [ + { + type : 'html', + id : 'marginTitle', + html : '