Feature #23948 » rtehtmlarea_feature_16257.patch
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (copie de travail) | ||
---|---|---|
} else {
|
||
var spans = node.getElementsByTagName("span");
|
||
for (var i = spans.length; --i >= 0;) {
|
||
if (HTMLArea._hasClass(spans[i], "Apple-style-span")) {
|
||
if (HTMLArea.DOM.hasClass(spans[i], "Apple-style-span")) {
|
||
this.removeMarkup(spans[i]);
|
||
}
|
||
}
|
||
var fonts = node.getElementsByTagName("font");
|
||
for (i = fonts.length; --i >= 0;) {
|
||
if (HTMLArea._hasClass(fonts[i], "Apple-style-span")) {
|
||
if (HTMLArea.DOM.hasClass(fonts[i], "Apple-style-span")) {
|
||
this.removeMarkup(fonts[i]);
|
||
}
|
||
}
|
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (copie de travail) | ||
---|---|---|
// Avoid re-initialization on AJax call when HTMLArea object was already initialized
|
||
if (typeof(HTMLArea) == 'undefined') {
|
||
// Establish HTMLArea name space
|
||
Ext.namespace('HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color', 'Ext.ux.form', 'Ext.ux.menu', 'Ext.ux.Toolbar');
|
||
/***************************************************
|
||
* CONSTANTS
|
||
***************************************************/
|
||
Ext.namespace('HTMLArea.CSS', 'HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color', 'Ext.ux.form', 'Ext.ux.menu', 'Ext.ux.Toolbar');
|
||
Ext.apply(HTMLArea, {
|
||
/*************************************************************************
|
||
* THESE BROWSER IDENTIFICATION CONSTANTS ARE DEPRECATED AS OF TYPO3 4.4 *
|
||
... | ... | |
is_safari : Ext.isWebKit,
|
||
is_chrome : Ext.isChrome,
|
||
is_opera : Ext.isOpera,
|
||
// Compile some regular expressions
|
||
/***************************************************
|
||
* COMPILED REGULAR EXPRESSIONS *
|
||
***************************************************/
|
||
RE_htmlTag : /<.[^<>]*?>/g,
|
||
RE_tagName : /(<\/|<)\s*([^ \t\n>]+)/ig,
|
||
RE_head : /<head>((.|\n)*?)<\/head>/i,
|
||
... | ... | |
RE_blockTags : /^(body|p|h1|h2|h3|h4|h5|h6|ul|ol|pre|dl|dt|dd|div|noscript|blockquote|form|hr|table|caption|fieldset|address|td|tr|th|li|tbody|thead|tfoot|iframe)$/i,
|
||
RE_closingTags : /^(p|blockquote|a|li|ol|ul|dl|dt|td|th|tr|tbody|thead|tfoot|caption|colgroup|table|div|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|label|q|samp|small|span|strike|strong|sub|sup|tt|u|var|abbr|acronym|font|center|object|embed|style|script|title|head)$/i,
|
||
RE_noClosingTag : /^(img|br|hr|col|input|area|base|link|meta|param)$/i,
|
||
RE_numberOrPunctuation : /[0-9.(),;:!¡?¿%#$'"_+=\\\/-]*/g
|
||
});
|
||
/***************************************************
|
||
* TROUBLESHOOTING
|
||
***************************************************/
|
||
HTMLArea._appendToLog = function(str){
|
||
if (HTMLArea.enableDebugMode) {
|
||
var log = document.getElementById('HTMLAreaLog');
|
||
if(log) {
|
||
log.appendChild(document.createTextNode(str));
|
||
log.appendChild(document.createElement('br'));
|
||
RE_numberOrPunctuation : /[0-9.(),;:!¡?¿%#$'"_+=\\\/-]*/g,
|
||
/***************************************************
|
||
* TROUBLESHOOTING *
|
||
***************************************************/
|
||
_appendToLog: function(str){
|
||
if (HTMLArea.enableDebugMode) {
|
||
var log = document.getElementById('HTMLAreaLog');
|
||
if(log) {
|
||
log.appendChild(document.createTextNode(str));
|
||
log.appendChild(document.createElement('br'));
|
||
}
|
||
}
|
||
},
|
||
appendToLog: function (editorId, objectName, functionName, text) {
|
||
HTMLArea._appendToLog(editorId + '[' + objectName + '::' + functionName + ']: ' + text);
|
||
},
|
||
/***************************************************
|
||
* LOCALIZATION *
|
||
***************************************************/
|
||
localize: function (label) {
|
||
return HTMLArea.I18N.dialogs[label] || HTMLArea.I18N.tooltips[label] || HTMLArea.I18N.msg[label] || label;
|
||
},
|
||
/***************************************************
|
||
* INITIALIZATION *
|
||
***************************************************/
|
||
init: function () {
|
||
// Apply global configuration settings
|
||
Ext.apply(HTMLArea, RTEarea[0]);
|
||
Ext.applyIf(HTMLArea, {
|
||
editorSkin : HTMLArea.editorUrl + 'skins/default/',
|
||
editorCSS : HTMLArea.editorUrl + 'skins/default/htmlarea.css'
|
||
});
|
||
if (!Ext.isString(HTMLArea.editedContentCSS)) {
|
||
HTMLArea.editedContentCSS = HTMLArea.editorSkin + 'htmlarea-edited-content.css';
|
||
}
|
||
HTMLArea.isReady = true;
|
||
HTMLArea._appendToLog("[HTMLArea::init]: Editor url set to: " + HTMLArea.editorUrl);
|
||
HTMLArea._appendToLog("[HTMLArea::init]: Editor skin CSS set to: " + HTMLArea.editorCSS);
|
||
HTMLArea._appendToLog("[HTMLArea::init]: Editor content skin CSS set to: " + HTMLArea.editedContentCSS);
|
||
}
|
||
};
|
||
});
|
||
/***************************************************
|
||
* HTMLArea INITIALIZATION
|
||
***************************************************/
|
||
HTMLArea.init = function() {
|
||
// Apply global configuration settings
|
||
Ext.apply(HTMLArea, RTEarea[0]);
|
||
Ext.applyIf(HTMLArea, {
|
||
editorSkin : HTMLArea.editorUrl + 'skins/default/',
|
||
editorCSS : HTMLArea.editorUrl + 'skins/default/htmlarea.css'
|
||
});
|
||
if (!Ext.isString(HTMLArea.editedContentCSS)) {
|
||
HTMLArea.editedContentCSS = HTMLArea.editorSkin + 'htmlarea-edited-content.css';
|
||
}
|
||
HTMLArea.isReady = true;
|
||
HTMLArea._appendToLog("[HTMLArea::init]: Editor url set to: " + HTMLArea.editorUrl);
|
||
HTMLArea._appendToLog("[HTMLArea::init]: Editor skin CSS set to: " + HTMLArea.editorCSS);
|
||
HTMLArea._appendToLog("[HTMLArea::init]: Editor content skin CSS set to: " + HTMLArea.editedContentCSS);
|
||
};
|
||
/***************************************************
|
||
* EDITOR CONFIGURATION
|
||
***************************************************/
|
||
HTMLArea.Config = function (editorId) {
|
||
... | ... | |
this.registerPlugin(plugin);
|
||
}
|
||
}, this);
|
||
// Create Ajax object
|
||
this.ajax = new HTMLArea.Ajax({
|
||
editor: this
|
||
});
|
||
// Initialize keyboard input inhibit flag
|
||
this.inhibitKeyboardInput = false;
|
||
this.addEvents(
|
||
... | ... | |
document.getElementById('editorWrap' + this.editorId).style.visibility = 'visible';
|
||
},
|
||
/*
|
||
* Append an entry at the end of the troubleshooting log
|
||
*
|
||
* @param string functionName: the name of the editor function writing to the log
|
||
* @param string text: the text of the message
|
||
*
|
||
* @return void
|
||
*/
|
||
appendToLog: function (objectName, functionName, text) {
|
||
HTMLArea.appendToLog(this.editorId, objectName, functionName, text);
|
||
},
|
||
/*
|
||
* Iframe unload handler: Update the textarea for submission and cleanup
|
||
*/
|
||
onUnload: function (event) {
|
||
... | ... | |
RTEarea[this.editorId].editor = null;
|
||
}
|
||
});
|
||
HTMLArea.Ajax = function (config) {
|
||
Ext.apply(this, config);
|
||
};
|
||
HTMLArea.Ajax = Ext.extend(HTMLArea.Ajax, {
|
||
/*
|
||
* Load a Javascript file asynchronously
|
||
*
|
||
* @param string url: url of the file to load
|
||
* @param function callBack: the callBack function
|
||
* @param object scope: scope of the callbacks
|
||
*
|
||
* @return boolean true on success of the request submission
|
||
*/
|
||
getJavascriptFile: function (url, callback, scope) {
|
||
var success = false;
|
||
var self = this;
|
||
this.editor.appendToLog('HTMLArea.Ajax', 'getJavascriptFile', 'Requesting script ' + url);
|
||
Ext.Ajax.request({
|
||
method: 'GET',
|
||
url: url,
|
||
callback: callback,
|
||
success: function (response) {
|
||
success = true;
|
||
},
|
||
failure: function (response) {
|
||
self.editor.inhibitKeyboardInput = false;
|
||
self.editor.appendToLog('HTMLArea.Ajax', 'getJavascriptFile', 'Unable to get ' + url + ' . Server reported ' + response.status);
|
||
},
|
||
scope: scope
|
||
});
|
||
return success;
|
||
},
|
||
/*
|
||
* Post data to the server
|
||
*
|
||
* @param string url: url to post data to
|
||
* @param object data: data to be posted
|
||
* @param function callback: function that will handle the response returned by the server
|
||
* @param object scope: scope of the callbacks
|
||
*
|
||
* @return boolean true on success
|
||
*/
|
||
postData: function (url, data, callback, scope) {
|
||
var success = false;
|
||
var self = this;
|
||
data.charset = this.editor.config.typo3ContentCharset ? this.editor.config.typo3ContentCharset : 'utf-8';
|
||
var params = '';
|
||
Ext.iterate(data, function (parameter, value) {
|
||
params += (params.length ? '&' : '') + parameter + '=' + encodeURIComponent(value);
|
||
});
|
||
params += this.editor.config.RTEtsConfigParams;
|
||
this.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Posting to ' + url + '. Data: ' + params);
|
||
Ext.Ajax.request({
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
||
},
|
||
url: url,
|
||
params: params,
|
||
callback: Ext.isFunction(callback) ? callback: function (options, success, response) {
|
||
if (success) {
|
||
self.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Post request to ' + url + ' successful. Server response: ' + response.responseText);
|
||
} else {
|
||
self.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Post request to ' + url + ' failed. Server reported ' + response.status);
|
||
}
|
||
},
|
||
success: function (response) {
|
||
success = true;
|
||
},
|
||
failure: function (response) {
|
||
self.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Unable to post ' + url + ' . Server reported ' + response.status);
|
||
},
|
||
scope: scope
|
||
});
|
||
return success;
|
||
}
|
||
});
|
||
/***************************************************
|
||
* HTMLArea.util.TYPO3: Utility functions for dealing with tabs and inline elements in TYPO3 forms
|
||
***************************************************/
|
||
... | ... | |
HTMLArea.checkSupportedBrowser = function() {
|
||
return Ext.isGecko || Ext.isWebKit || Ext.isOpera || Ext.isIE;
|
||
};
|
||
/*
|
||
* Remove a class name from the class attribute of an element
|
||
*
|
||
... | ... | |
* @param string className: the class name to remove
|
||
* @param boolean substring: if true, remove the first class name starting with the given string
|
||
* @return void
|
||
***********************************************
|
||
* THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.5 *
|
||
***********************************************
|
||
*/
|
||
HTMLArea._removeClass = function(el, className, substring) {
|
||
if (!el || !el.className) return;
|
||
var classes = el.className.trim().split(" ");
|
||
var newClasses = new Array();
|
||
for (var i = classes.length; --i >= 0;) {
|
||
if (!substring) {
|
||
if (classes[i] != className) {
|
||
newClasses[newClasses.length] = classes[i];
|
||
}
|
||
} else if (classes[i].indexOf(className) != 0) {
|
||
newClasses[newClasses.length] = classes[i];
|
||
}
|
||
}
|
||
if (newClasses.length == 0) {
|
||
if (!Ext.isOpera) {
|
||
el.removeAttribute("class");
|
||
if (Ext.isIE) {
|
||
el.removeAttribute("className");
|
||
}
|
||
} else {
|
||
el.className = '';
|
||
}
|
||
} else {
|
||
el.className = newClasses.join(" ");
|
||
}
|
||
HTMLArea.DOM.removeClass(el, className, substring);
|
||
};
|
||
/*
|
||
* Add a class name to the class attribute
|
||
***********************************************
|
||
* THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.5 *
|
||
***********************************************
|
||
*/
|
||
HTMLArea._addClass = function(el, addClassName) {
|
||
HTMLArea._removeClass(el, addClassName);
|
||
if (el.className && HTMLArea.classesXOR && HTMLArea.classesXOR.hasOwnProperty(addClassName) && typeof(HTMLArea.classesXOR[addClassName].test) == "function") {
|
||
var classNames = el.className.trim().split(" ");
|
||
for (var i = classNames.length; --i >= 0;) {
|
||
if (HTMLArea.classesXOR[addClassName].test(classNames[i])) {
|
||
HTMLArea._removeClass(el, classNames[i]);
|
||
}
|
||
}
|
||
}
|
||
if (el.className) el.className += " " + addClassName;
|
||
else el.className = addClassName;
|
||
HTMLArea._addClass = function(el, className) {
|
||
HTMLArea.DOM.addClass(el, className);
|
||
};
|
||
/*
|
||
* Check if a class name is in the class attribute of an element
|
||
*
|
||
... | ... | |
* @param string className: the class name to look for
|
||
* @param boolean substring: if true, look for a class name starting with the given string
|
||
* @return boolean true if the class name was found
|
||
***********************************************
|
||
* THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.5 *
|
||
***********************************************
|
||
*/
|
||
HTMLArea._hasClass = function(el, className, substring) {
|
||
if (!el || !el.className) return false;
|
||
var classes = el.className.trim().split(" ");
|
||
for (var i = classes.length; --i >= 0;) {
|
||
if (classes[i] == className || (substring && classes[i].indexOf(className) == 0)) return true;
|
||
}
|
||
return false;
|
||
return HTMLArea.DOM.hasClass(el, className, substring);
|
||
};
|
||
HTMLArea.isBlockElement = function(el) { return el && el.nodeType == 1 && HTMLArea.RE_blockTags.test(el.nodeName.toLowerCase()); };
|
||
... | ... | |
/*****************************************************************
|
||
* HTMLArea.DOM: Utility functions for dealing with the DOM tree *
|
||
*****************************************************************/
|
||
/***************************************************
|
||
* DOM-RELATED CONSTANTS
|
||
***************************************************/
|
||
HTMLArea.DOM = function () {
|
||
return {
|
||
/***************************************************
|
||
* DOM-RELATED CONSTANTS
|
||
***************************************************/
|
||
// DOM node types
|
||
ELEMENT_NODE: 1,
|
||
ATTRIBUTE_NODE: 2,
|
||
... | ... | |
DOCUMENT_NODE: 9,
|
||
DOCUMENT_TYPE_NODE: 10,
|
||
DOCUMENT_FRAGMENT_NODE: 11,
|
||
NOTATION_NODE: 12
|
||
NOTATION_NODE: 12,
|
||
/*
|
||
* Gets the class names assigned to a node, reserved classes removed
|
||
*
|
||
* @param object node: the node
|
||
* @return array array of class names on the node, reserved classes removed
|
||
*/
|
||
getClassNames: function (node) {
|
||
var classNames = [];
|
||
if (node) {
|
||
if (node.className && /\S/.test(node.className)) {
|
||
classNames = node.className.trim().split(' ');
|
||
}
|
||
if (HTMLArea.reservedClassNames.test(node.className)) {
|
||
var cleanClassNames = [];
|
||
var j = -1;
|
||
for (var i = 0; i < classNames.length; ++i) {
|
||
if (!HTMLArea.reservedClassNames.test(classNames[i])) {
|
||
cleanClassNames[++j] = classNames[i];
|
||
}
|
||
}
|
||
classNames = cleanClassNames;
|
||
}
|
||
}
|
||
return classNames;
|
||
},
|
||
/*
|
||
* Check if a class name is in the class attribute of a node
|
||
*
|
||
* @param object node: the node
|
||
* @param string className: the class name to look for
|
||
* @param boolean substring: if true, look for a class name starting with the given string
|
||
* @return boolean true if the class name was found, false otherwise
|
||
*/
|
||
hasClass: function (node, className, substring) {
|
||
var found = false;
|
||
if (node && node.className) {
|
||
var classes = node.className.trim().split(' ');
|
||
for (var i = classes.length; --i >= 0;) {
|
||
found = ((classes[i] == className) || (substring && classes[i].indexOf(className) == 0));
|
||
if (found) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return found;
|
||
},
|
||
/*
|
||
* Add a class name to the class attribute of a node
|
||
*
|
||
* @param object node: the node
|
||
* @param string className: the name of the class to be added
|
||
* @return void
|
||
*/
|
||
addClass: function (node, className) {
|
||
if (node) {
|
||
HTMLArea.DOM.removeClass(node, className);
|
||
// Remove classes configured to be incompatible with the class to be added
|
||
if (node.className && HTMLArea.classesXOR && HTMLArea.classesXOR[className] && Ext.isFunction(HTMLArea.classesXOR[className].test)) {
|
||
var classNames = node.className.trim().split(' ');
|
||
for (var i = classNames.length; --i >= 0;) {
|
||
if (HTMLArea.classesXOR[className].test(classNames[i])) {
|
||
HTMLArea.DOM.removeClass(node, classNames[i]);
|
||
}
|
||
}
|
||
}
|
||
if (node.className) {
|
||
node.className += ' ' + className;
|
||
} else {
|
||
node.className = className;
|
||
}
|
||
}
|
||
},
|
||
/*
|
||
* Remove a class name from the class attribute of a node
|
||
*
|
||
* @param object node: the node
|
||
* @param string className: the class name to removed
|
||
* @param boolean substring: if true, remove the class names starting with the given string
|
||
* @return void
|
||
*/
|
||
removeClass: function (node, className, substring) {
|
||
if (node && node.className) {
|
||
var classes = node.className.trim().split(' ');
|
||
var newClasses = [];
|
||
for (var i = classes.length; --i >= 0;) {
|
||
if ((!substring && classes[i] != className) || (substring && classes[i].indexOf(className) != 0)) {
|
||
newClasses[newClasses.length] = classes[i];
|
||
}
|
||
}
|
||
if (newClasses.length) {
|
||
node.className = newClasses.join(' ');
|
||
} else {
|
||
if (!Ext.isOpera) {
|
||
node.removeAttribute('class');
|
||
if (Ext.isIE) {
|
||
node.removeAttribute('className');
|
||
}
|
||
} else {
|
||
node.className = '';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
}();
|
||
/***************************************************
|
||
... | ... | |
keepTags: /.*/i,
|
||
removeAttributes: /none/i,
|
||
removeTrailingBR: true
|
||
}
|
||
};
|
||
Ext.apply(this, config, configDefaults);
|
||
};
|
||
HTMLArea.DOM.Walker = Ext.extend(HTMLArea.DOM.Walker, {
|
||
... | ... | |
}
|
||
});
|
||
/***************************************************
|
||
* HTMLArea.CSS.Parser: CSS Parser
|
||
***************************************************/
|
||
HTMLArea.CSS.Parser = Ext.extend(Ext.util.Observable, {
|
||
/*
|
||
* HTMLArea.CSS.Parser constructor
|
||
*/
|
||
constructor: function (config) {
|
||
HTMLArea.CSS.Parser.superclass.constructor.call(this, {});
|
||
var configDefaults = {
|
||
parseAttemptsMaximumNumber: 17,
|
||
prefixLabelWithClassName: false,
|
||
postfixLabelWithClassName: false,
|
||
showTagFreeClasses: false,
|
||
tags: null,
|
||
editor: null
|
||
};
|
||
Ext.apply(this, config, configDefaults);
|
||
this.addEvents(
|
||
/*
|
||
* @event HTMLAreaEventCssParsingComplete
|
||
* Fires when parsing of the stylesheets of the iframe is complete
|
||
*/
|
||
'HTMLAreaEventCssParsingComplete'
|
||
);
|
||
},
|
||
/*
|
||
* The parsed classes
|
||
*/
|
||
parsedClasses: {},
|
||
/*
|
||
* Boolean indicating whether are not parsing is complete
|
||
*/
|
||
isReady: false,
|
||
/*
|
||
* Boolean indicating whether or not the stylesheets were accessible
|
||
*/
|
||
cssLoaded: false,
|
||
/*
|
||
* Counter of the number of attempts at parsing the stylesheets
|
||
*/
|
||
parseAttemptsCounter: 0,
|
||
/*
|
||
* Parsing attempt timeout id
|
||
*/
|
||
attemptTimeout: null,
|
||
/*
|
||
* The error that occurred on the last attempt at parsing the stylesheets
|
||
*/
|
||
error: null,
|
||
/*
|
||
* This function gets the parsed css classes
|
||
*
|
||
* @return object this.parsedClasses
|
||
*/
|
||
getClasses: function() {
|
||
return this.parsedClasses;
|
||
},
|
||
/*
|
||
* This function initiates parsing of the stylesheets
|
||
*
|
||
* @return void
|
||
*/
|
||
initiateParsing: function () {
|
||
if (this.editor.config.classesUrl && (typeof(HTMLArea.classesLabels) === 'undefined')) {
|
||
this.editor.ajax.getJavascriptFile(this.editor.config.classesUrl, function (options, success, response) {
|
||
if (success) {
|
||
try {
|
||
if (typeof(HTMLArea.classesLabels) === 'undefined') {
|
||
eval(response.responseText);
|
||
this.editor.appendToLog('HTMLArea.CSS.Parser', 'initiateParsing', 'Javascript file successfully evaluated: ' + this.editor.config.classesUrl);
|
||
}
|
||
} catch(e) {
|
||
this.editor.appendToLog('HTMLArea.CSS.Parser', 'initiateParsing', 'Error evaluating contents of Javascript file: ' + this.editor.config.classesUrl);
|
||
}
|
||
}
|
||
this.parse();
|
||
}, this);
|
||
} else {
|
||
this.parse();
|
||
}
|
||
},
|
||
/*
|
||
* This function parses the stylesheets of the iframe set in config
|
||
*
|
||
* @return void parsed css classes are accumulated in this.parsedClasses
|
||
*/
|
||
parse: function() {
|
||
if (this.editor.document) {
|
||
this.parseStyleSheets();
|
||
if (!this.cssLoaded) {
|
||
if (this.parseAttemptsCounter < this.parseAttemptsMaximumNumber) {
|
||
this.attemptTimeout = this.parse.defer(200, this);
|
||
this.parseAttemptsCounter++;
|
||
} else {
|
||
this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'The stylesheets could not be parsed. Reported error: ' + this.error);
|
||
this.fireEvent('HTMLAreaEventCssParsingComplete');
|
||
}
|
||
} else {
|
||
this.attemptTimeout = null;
|
||
this.isReady = true;
|
||
this.filterAllowedClasses();
|
||
this.sort();
|
||
this.fireEvent('HTMLAreaEventCssParsingComplete');
|
||
}
|
||
}
|
||
},
|
||
/*
|
||
* This function parses the stylesheets of an iframe
|
||
*
|
||
* @return void parsed css classes are accumulated in this.parsedClasses
|
||
*/
|
||
parseStyleSheets: function () {
|
||
this.cssLoaded = true;
|
||
this.error = null;
|
||
for (var i = 0; i < this.editor.document.styleSheets.length; i++) {
|
||
if (!Ext.isIE) {
|
||
try {
|
||
this.parseRules(this.editor.document.styleSheets[i].cssRules);
|
||
} catch (e) {
|
||
this.error = e;
|
||
this.cssLoaded = false;
|
||
this.parsedClasses = {};
|
||
}
|
||
} else {
|
||
try{
|
||
if (this.editor.document.styleSheets[i].imports) {
|
||
this.parseIeRules(this.editor.document.styleSheets[i].imports);
|
||
}
|
||
if (this.editor.document.styleSheets[i].rules) {
|
||
this.parseRules(this.editor.document.styleSheets[i].rules);
|
||
}
|
||
} catch (e) {
|
||
this.error = e;
|
||
this.cssLoaded = false;
|
||
this.parsedClasses = {};
|
||
}
|
||
}
|
||
}
|
||
},
|
||
/*
|
||
* This function parses the set of rules from a standard stylesheet
|
||
*
|
||
* @param array cssRules: the array of rules of a stylesheet
|
||
* @return void
|
||
*/
|
||
parseRules: function (cssRules) {
|
||
for (var rule = 0; rule < cssRules.length; rule++) {
|
||
// Style rule
|
||
if (cssRules[rule].selectorText) {
|
||
this.parseSelectorText(cssRules[rule].selectorText);
|
||
} else {
|
||
// Import rule
|
||
if (cssRules[rule].styleSheet) {
|
||
this.parseRules(cssRules[rule].styleSheet.cssRules);
|
||
}
|
||
// Media rule
|
||
if (cssRules[rule].cssRules) {
|
||
this.parseRules(cssRules[rule].cssRules);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
/*
|
||
* This function parses the set of rules from an IE stylesheet
|
||
*
|
||
* @param array cssRules: the array of rules of a stylesheet
|
||
* @return void
|
||
*/
|
||
parseIeRules: function (cssRules) {
|
||
for (var rule = 0; rule < cssRules.length; rule++) {
|
||
// Import rule
|
||
if (cssRules[rule].imports) {
|
||
this.parseIeRules(cssRules[rule].imports);
|
||
}
|
||
// Style rule
|
||
if (cssRules[rule].rules) {
|
||
this.parseRules(cssRules[rule].rules);
|
||
}
|
||
}
|
||
},
|
||
/*
|
||
* This function parses a selector rule
|
||
*
|
||
* @param string selectorText: the text of the rule to parsed
|
||
* @return void
|
||
*/
|
||
parseSelectorText: function (selectorText) {
|
||
var cssElements = [],
|
||
cssElement = [],
|
||
nodeName, className,
|
||
pattern = /(\S*)\.(\S+)/;
|
||
if (selectorText.search(/:+/) == -1) {
|
||
// Split equal styles
|
||
cssElements = selectorText.split(',');
|
||
for (var k = 0; k < cssElements.length; k++) {
|
||
// Match all classes (<element name (optional)>.<class name>) in selector rule
|
||
var s = cssElements[k], index;
|
||
while ((index = s.search(pattern)) > -1) {
|
||
var match = pattern.exec(s.substring(index));
|
||
s = s.substring(index+match[0].length);
|
||
nodeName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : 'all';
|
||
className = match[2];
|
||
if (className && !HTMLArea.reservedClassNames.test(className)) {
|
||
if (((nodeName != 'all') && (!this.tags || !this.tags[nodeName]))
|
||
|| ((nodeName == 'all') && (!this.tags || !this.tags[nodeName]) && this.showTagFreeClasses)
|
||
|| (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses && this.tags[nodeName].allowedClasses.test(className))) {
|
||
if (!this.parsedClasses[nodeName]) {
|
||
this.parsedClasses[nodeName] = {};
|
||
}
|
||
cssName = className;
|
||
if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
|
||
cssName = this.prefixLabelWithClassName ? (className + ' - ' + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
|
||
cssName = this.postfixLabelWithClassName ? (cssName + ' - ' + className) : cssName;
|
||
}
|
||
this.parsedClasses[nodeName][className] = cssName;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
/*
|
||
* This function filters the class selectors allowed for each nodeName
|
||
*
|
||
* @return void
|
||
*/
|
||
filterAllowedClasses: function() {
|
||
Ext.iterate(this.tags, function (nodeName) {
|
||
var allowedClasses = {};
|
||
// Get classes allowed for all tags
|
||
if (nodeName !== 'all' && Ext.isDefined(this.parsedClasses['all'])) {
|
||
if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
|
||
var allowed = this.tags[nodeName].allowedClasses;
|
||
Ext.iterate(this.parsedClasses['all'], function (cssClass, value) {
|
||
if (allowed.test(cssClass)) {
|
||
allowedClasses[cssClass] = value;
|
||
}
|
||
});
|
||
} else {
|
||
allowedClasses = this.parsedClasses['all'];
|
||
}
|
||
}
|
||
// Merge classes allowed for nodeName
|
||
if (Ext.isDefined(this.parsedClasses[nodeName])) {
|
||
if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
|
||
var allowed = this.tags[nodeName].allowedClasses;
|
||
Ext.iterate(this.parsedClasses[nodeName], function (cssClass, value) {
|
||
if (allowed.test(cssClass)) {
|
||
allowedClasses[cssClass] = value;
|
||
}
|
||
});
|
||
} else {
|
||
Ext.iterate(this.parsedClasses[nodeName], function (cssClass, value) {
|
||
allowedClasses[cssClass] = value;
|
||
});
|
||
}
|
||
}
|
||
this.parsedClasses[nodeName] = allowedClasses;
|
||
}, this);
|
||
// If showTagFreeClasses is set and there is no allowedClasses clause on a tag, merge classes allowed for all tags
|
||
if (this.showTagFreeClasses && Ext.isDefined(this.parsedClasses['all'])) {
|
||
Ext.iterate(this.parsedClasses, function (nodeName) {
|
||
if (nodeName !== 'all' && !this.tags[nodeName]) {
|
||
Ext.iterate(this.parsedClasses['all'], function (cssClass, value) {
|
||
this.parsedClasses[nodeName][cssClass] = value;
|
||
}, this);
|
||
}
|
||
}, this);
|
||
}
|
||
},
|
||
/*
|
||
* This function sorts the class selectors for each nodeName
|
||
*
|
||
* @return void
|
||
*/
|
||
sort: function() {
|
||
Ext.iterate(this.parsedClasses, function (nodeName, value) {
|
||
var classes = [];
|
||
var sortedClasses= {};
|
||
// Collect keys
|
||
Ext.iterate(value, function (cssClass) {
|
||
classes.push(cssClass);
|
||
});
|
||
function compare(a, b) {
|
||
x = value[a];
|
||
y = value[b];
|
||
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
||
}
|
||
// Sort keys by comparing texts
|
||
classes = classes.sort(compare);
|
||
for (var i = 0; i < classes.length; ++i) {
|
||
sortedClasses[classes[i]] = value[classes[i]];
|
||
}
|
||
this.parsedClasses[nodeName] = sortedClasses;
|
||
}, this);
|
||
}
|
||
});
|
||
/***************************************************
|
||
* TIPS ON FORM FIELDS AND MENU ITEMS
|
||
***************************************************/
|
||
/*
|
||
... | ... | |
* @return string the localization of the label
|
||
*/
|
||
localize: function (label) {
|
||
return this.I18N[label] || HTMLArea.I18N.dialogs[label] || HTMLArea.I18N.tooltips[label] || HTMLArea.I18N.msg[label];
|
||
return this.I18N[label] || HTMLArea.localize(label);
|
||
},
|
||
/**
|
||
* Load a Javascript file asynchronously
|
||
... | ... | |
* @return boolean true on success of the request submission
|
||
*/
|
||
getJavascriptFile: function (url, callback) {
|
||
var success = false;
|
||
this.appendToLog('getJavascriptFile', 'Requesting script ' + url);
|
||
Ext.Ajax.request({
|
||
method: 'GET',
|
||
url: url,
|
||
callback: callback,
|
||
success: function (response) {
|
||
success = true;
|
||
},
|
||
failure: function (response) {
|
||
this.editor.inhibitKeyboardInput = false;
|
||
this.appendToLog('getJavascriptFile', 'Unable to get ' + url + ' . Server reported ' + response.status);
|
||
},
|
||
scope: this
|
||
});
|
||
return success;
|
||
return this.editor.ajax.getJavascriptFile(url, callback, this);
|
||
},
|
||
/**
|
||
* Post data to the server
|
||
... | ... | |
*
|
||
* @return boolean true on success
|
||
*/
|
||
postData: function (url, data, callback) {
|
||
var success = false;
|
||
data.charset = this.editorConfiguration.typo3ContentCharset ? this.editorConfiguration.typo3ContentCharset : 'utf-8';
|
||
var params = '';
|
||
Ext.iterate(data, function (parameter, value) {
|
||
params += (params.length ? '&' : '') + parameter + '=' + encodeURIComponent(value);
|
||
});
|
||
params += this.editorConfiguration.RTEtsConfigParams;
|
||
this.appendToLog('postData', 'Posting to ' + url + '. Data: ' + params);
|
||
Ext.Ajax.request({
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
||
},
|
||
url: url,
|
||
params: params,
|
||
callback: Ext.isFunction(callback) ? callback: function (options, success, response) {
|
||
if (success) {
|
||
this.appendToLog('postData', 'Post request to ' + url + ' successful. Server response: ' + response.responseText);
|
||
} else {
|
||
this.appendToLog('postData', 'Post request to ' + url + ' failed. Server reported ' + response.status);
|
||
}
|
||
},
|
||
success: function (response) {
|
||
success = true;
|
||
},
|
||
failure: function (response) {
|
||
this.appendToLog('postData', 'Unable to post ' + url + ' . Server reported ' + response.status);
|
||
},
|
||
scope: this
|
||
});
|
||
return success;
|
||
},
|
||
postData: function (url, data, callback) {
|
||
this.appendToLog('postData', 'Posting to ' + url + '. Data: ' + params);
|
||
return this.editor.ajax.postData(url, data, callback, this);
|
||
},
|
||
/**
|
||
***********************************************
|
||
* THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.4 *
|
||
... | ... | |
* @return void
|
||
*/
|
||
appendToLog: function (functionName, text) {
|
||
HTMLArea._appendToLog('[' + this.name + '::' + functionName + ']: ' + text);
|
||
this.editor.appendToLog(this.name, functionName, text);
|
||
},
|
||
/*
|
||
* Add a config element to config array if not empty
|
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js (copie de travail) | ||
---|---|---|
this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
|
||
}
|
||
} else if (this.isAllowedBlockElement("div")) {
|
||
if (/^div$/i.test(parentElement.nodeName) && !HTMLArea._hasClass(parentElement, this.useClass[buttonId])) {
|
||
HTMLArea._addClass(parentElement, this.useClass[buttonId]);
|
||
} else if (!/^div$/i.test(parentElement.nodeName) && /^div$/i.test(parentElement.parentNode.nodeName) && !HTMLArea._hasClass(parentElement.parentNode, this.useClass[buttonId])) {
|
||
HTMLArea._addClass(parentElement.parentNode, this.useClass[buttonId]);
|
||
if (/^div$/i.test(parentElement.nodeName) && !HTMLArea.DOM.hasClass(parentElement, this.useClass[buttonId])) {
|
||
HTMLArea.DOM.addClass(parentElement, this.useClass[buttonId]);
|
||
} else if (!/^div$/i.test(parentElement.nodeName) && /^div$/i.test(parentElement.parentNode.nodeName) && !HTMLArea.DOM.hasClass(parentElement.parentNode, this.useClass[buttonId])) {
|
||
HTMLArea.DOM.addClass(parentElement.parentNode, this.useClass[buttonId]);
|
||
} else {
|
||
var bookmark = this.editor.getBookmark(range);
|
||
var newBlock = this.wrapSelectionInBlockElement("div", this.useClass[buttonId], null, true);
|
||
... | ... | |
}
|
||
break;
|
||
case "Outdent" :
|
||
if (/^(ol|ul)$/i.test(parentElement.nodeName) && !HTMLArea._hasClass(parentElement, this.useClass.Indent)) {
|
||
if (/^(ol|ul)$/i.test(parentElement.nodeName) && !HTMLArea.DOM.hasClass(parentElement, this.useClass.Indent)) {
|
||
if (/^(li)$/i.test(parentElement.parentNode.nodeName)) {
|
||
if (Ext.isOpera) {
|
||
try {
|
||
... | ... | |
}
|
||
} else if (this.isAllowedBlockElement("div")) {
|
||
for (var i = blockAncestors.length; --i >= 0;) {
|
||
if (HTMLArea._hasClass(blockAncestors[i], this.useClass.Indent)) {
|
||
if (HTMLArea.DOM.hasClass(blockAncestors[i], this.useClass.Indent)) {
|
||
var bookmark = this.editor.getBookmark(range);
|
||
var newBlock = this.wrapSelectionInBlockElement("div", false, blockAncestors[i]);
|
||
// If not directly under the div, we need to backtrack
|
||
... | ... | |
newBlock.appendChild(parent);
|
||
}
|
||
newBlock.className = blockAncestors[i].className;
|
||
HTMLArea._removeClass(newBlock, this.useClass.Indent);
|
||
HTMLArea.DOM.removeClass(newBlock, this.useClass.Indent);
|
||
if (!newBlock.previousSibling) {
|
||
while (newBlock.hasChildNodes()) {
|
||
if (newBlock.firstChild.nodeType == 1) {
|
||
... | ... | |
}
|
||
var blockElement = this.editor._doc.createElement(blockName);
|
||
if (useClass) {
|
||
HTMLArea._addClass(blockElement, useClass);
|
||
HTMLArea.DOM.addClass(blockElement, useClass);
|
||
}
|
||
var contextElement = endAncestors[0];
|
||
if (i) {
|
||
... | ... | |
if (HTMLArea.isBlockElement(block)) {
|
||
switch (buttonId) {
|
||
case "Indent" :
|
||
if (!HTMLArea._hasClass(block, this.useClass[buttonId])) {
|
||
HTMLArea._addClass(block, this.useClass[buttonId]);
|
||
if (!HTMLArea.DOM.hasClass(block, this.useClass[buttonId])) {
|
||
HTMLArea.DOM.addClass(block, this.useClass[buttonId]);
|
||
}
|
||
break;
|
||
case "Outdent" :
|
||
if (HTMLArea._hasClass(block, this.useClass["Indent"])) {
|
||
HTMLArea._removeClass(block, this.useClass["Indent"]);
|
||
if (HTMLArea.DOM.hasClass(block, this.useClass["Indent"])) {
|
||
HTMLArea.DOM.removeClass(block, this.useClass["Indent"]);
|
||
}
|
||
break;
|
||
case "JustifyLeft" :
|
||
... | ... | |
if (this.standardBlockElements.test(buttonId.toLowerCase()) && buttonId.toLowerCase() == block.nodeName.toLowerCase()) {
|
||
this.cleanClasses(block);
|
||
if (className) {
|
||
HTMLArea._addClass(block, className);
|
||
HTMLArea.DOM.addClass(block, className);
|
||
}
|
||
}
|
||
break;
|
||
... | ... | |
toggleAlignmentClass : function(block, buttonId) {
|
||
for (var alignmentButtonId in this.useClass) {
|
||
if (this.useClass.hasOwnProperty(alignmentButtonId) && alignmentButtonId !== "Indent") {
|
||
if (HTMLArea._hasClass(block, this.useClass[alignmentButtonId])) {
|
||
HTMLArea._removeClass(block, this.useClass[alignmentButtonId]);
|
||
if (HTMLArea.DOM.hasClass(block, this.useClass[alignmentButtonId])) {
|
||
HTMLArea.DOM.removeClass(block, this.useClass[alignmentButtonId]);
|
||
} else if (alignmentButtonId === buttonId) {
|
||
HTMLArea._addClass(block, this.useClass[alignmentButtonId]);
|
||
HTMLArea.DOM.addClass(block, this.useClass[alignmentButtonId]);
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
if (!HTMLArea.reservedClassNames.test(classNames[i])) {
|
||
if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
|
||
if (!this.tags[nodeName].allowedClasses.test(classNames[i])) {
|
||
HTMLArea._removeClass(node, classNames[i]);
|
||
HTMLArea.DOM.removeClass(node, classNames[i]);
|
||
}
|
||
} else if (this.tags && this.tags.all && this.tags.all.allowedClasses) {
|
||
if (!this.tags.all.allowedClasses.test(classNames[i])) {
|
||
HTMLArea._removeClass(node, classNames[i]);
|
||
HTMLArea.DOM.removeClass(node, classNames[i]);
|
||
}
|
||
}
|
||
if (this.formatBlockItems[nodeName] && this.formatBlockItems[nodeName].classList && this.formatBlockItems[nodeName].classList.test(classNames[i])) {
|
||
HTMLArea._removeClass(node, classNames[i]);
|
||
HTMLArea.DOM.removeClass(node, classNames[i]);
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
commandState = true;
|
||
} else {
|
||
for (var j = blockAncestors.length; --j >= 0;) {
|
||
if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent) || /^(td|th)$/i.test(blockAncestors[j].nodeName)) {
|
||
if (HTMLArea.DOM.hasClass(blockAncestors[j], this.useClass.Indent) || /^(td|th)$/i.test(blockAncestors[j].nodeName)) {
|
||
commandState = true;
|
||
break;
|
||
}
|
||
... | ... | |
button.setDisabled(false);
|
||
commandState = true;
|
||
for (var block = startAncestors[index]; block; block = block.nextSibling) {
|
||
commandState = commandState && HTMLArea._hasClass(block, this.useClass[button.itemId]);
|
||
commandState = commandState && HTMLArea.DOM.hasClass(block, this.useClass[button.itemId]);
|
||
if (block == endAncestors[index]) {
|
||
break;
|
||
}
|
||
... | ... | |
// Could be a custom item ...
|
||
index = store.findBy(function(record, id) {
|
||
var item = this.formatBlockItems[record.get('value')];
|
||
return item && item.tagName == nodeName && item.addClass && HTMLArea._hasClass(deepestBlockAncestor, item.addClass);
|
||
return item && item.tagName == nodeName && item.addClass && HTMLArea.DOM.hasClass(deepestBlockAncestor, item.addClass);
|
||
}, this);
|
||
if (index == -1) {
|
||
// ... or a standard one
|
typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js (copie de travail) | ||
---|---|---|
* TYPO3 SVN ID: $Id$
|
||
*/
|
||
HTMLArea.BlockStyle = HTMLArea.Plugin.extend({
|
||
|
||
constructor : function(editor, pluginName) {
|
||
this.base(editor, pluginName);
|
||
},
|
||
|
||
/*
|
||
* This function gets called by the class constructor
|
||
*/
|
||
configurePlugin : function(editor) {
|
||
this.cssLoaded = false;
|
||
this.cssTimeout = null;
|
||
this.cssParseCount = 0;
|
||
this.cssArray = new Object();
|
||
|
||
configurePlugin: function (editor) {
|
||
this.cssArray = {};
|
||
this.classesUrl = this.editorConfiguration.classesUrl;
|
||
this.pageTSconfiguration = this.editorConfiguration.buttons.blockstyle;
|
||
this.tags = this.pageTSconfiguration.tags;
|
||
... | ... | |
this.showTagFreeClasses = this.pageTSconfiguration.showTagFreeClasses || this.editorConfiguration.showTagFreeClasses;
|
||
this.prefixLabelWithClassName = this.pageTSconfiguration.prefixLabelWithClassName;
|
||
this.postfixLabelWithClassName = this.pageTSconfiguration.postfixLabelWithClassName;
|
||
|
||
/*
|
||
* Registering plugin "About" information
|
||
*/
|
||
var pluginInformation = {
|
||
version : "1.4",
|
||
developer : "Stanislas Rolland",
|
||
developerUrl : "http://www.sjbr.ca/",
|
||
copyrightOwner : "Stanislas Rolland",
|
||
sponsor : this.localize("Technische Universitat Ilmenau"),
|
||
sponsorUrl : "http://www.tu-ilmenau.de/",
|
||
license : "GPL"
|
||
version : '2.0',
|
||
developer : 'Stanislas Rolland',
|
||
developerUrl : 'http://www.sjbr.ca/',
|
||
copyrightOwner : 'Stanislas Rolland',
|
||
sponsor : this.localize('Technische Universitat Ilmenau'),
|
||
sponsorUrl : 'http://www.tu-ilmenau.de/',
|
||
license : 'GPL'
|
||
};
|
||
this.registerPluginInformation(pluginInformation);
|
||
|
||
/*
|
||
* Registering the drop-down list
|
||
*/
|
||
... | ... | |
this.registerDropDown(dropDownConfiguration);
|
||
return true;
|
||
},
|
||
|
||
/*
|
||
* This function gets called when some block style was selected in the drop-down list
|
||
* This handler gets called when some block style was selected in the drop-down list
|
||
*/
|
||
onChange : function (editor, combo, record, index) {
|
||
onChange: function (editor, combo, record, index) {
|
||
var className = combo.getValue();
|
||
this.editor.focus();
|
||
var blocks = this.getSelectedBlocks();
|
||
... | ... | |
}
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function applies the class change to the node
|
||
*/
|
||
applyClassChange : function (node, className) {
|
||
applyClassChange: function (node, className) {
|
||
if (className == "none") {
|
||
var classNames = node.className.trim().split(" ");
|
||
for (var i = classNames.length; --i >= 0;) {
|
||
if (!HTMLArea.reservedClassNames.test(classNames[i])) {
|
||
HTMLArea._removeClass(node, classNames[i]);
|
||
HTMLArea.DOM.removeClass(node, classNames[i]);
|
||
if (node.nodeName.toLowerCase() === "table" && this.getPluginInstance('TableOperations')) {
|
||
this.getPluginInstance('TableOperations').removeAlternatingClasses(node, classNames[i]);
|
||
this.getPluginInstance('TableOperations').removeCountingClasses(node, classNames[i]);
|
||
... | ... | |
var nodeName = node.nodeName.toLowerCase();
|
||
if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
|
||
if (this.tags[nodeName].allowedClasses.test(className)) {
|
||
HTMLArea._addClass(node, className);
|
||
HTMLArea.DOM.addClass(node, className);
|
||
}
|
||
} else if (this.tags && this.tags.all && this.tags.all.allowedClasses) {
|
||
if (this.tags.all.allowedClasses.test(className)) {
|
||
HTMLArea._addClass(node, className);
|
||
HTMLArea.DOM.addClass(node, className);
|
||
}
|
||
} else {
|
||
HTMLArea._addClass(node, className);
|
||
HTMLArea.DOM.addClass(node, className);
|
||
}
|
||
if (nodeName === "table" && this.getPluginInstance('TableOperations')) {
|
||
this.getPluginInstance('TableOperations').reStyleTable(node);
|
||
}
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function gets the list of selected blocks
|
||
*/
|
||
getSelectedBlocks : function() {
|
||
getSelectedBlocks: function () {
|
||
var block, range, i = 0, blocks = [];
|
||
var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
|
||
if (Ext.isGecko) {
|
||
... | ... | |
return blocks;
|
||
},
|
||
/*
|
||
* This function gets called when the editor is generated
|
||
* This handler gets called when the editor is generated
|
||
*/
|
||
onGenerate: function() {
|
||
onGenerate: function () {
|
||
// Monitor editor changing mode
|
||
this.editor.iframe.mon(this.editor, 'modeChange', this.onModeChange, this);
|
||
if (!Ext.isIE) {
|
||
this.generate(this.editor, 'BlockStyle');
|
||
}
|
||
this.editor.iframe.mon(this.editor, 'HTMLAreaEventModeChange', this.onModeChange, this);
|
||
// Create CSS Parser object
|
||
this.blockStyles = new HTMLArea.CSS.Parser({
|
||
prefixLabelWithClassName: this.prefixLabelWithClassName,
|
||
postfixLabelWithClassName: this.postfixLabelWithClassName,
|
||
showTagFreeClasses: this.showTagFreeClasses,
|
||
tags: this.tags,
|
||
editor: this.editor
|
||
});
|
||
// Monitor css parsing being completed
|
||
this.editor.iframe.mon(this.blockStyles, 'HTMLAreaEventCssParsingComplete', this.onCssParsingComplete, this);
|
||
this.blockStyles.initiateParsing();
|
||
},
|
||
/*
|
||
* This function gets called when the toolbar is being updated
|
||
* This handler gets called when parsing of css classes is completed
|
||
*/
|
||
onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
|
||
if (mode === 'wysiwyg') {
|
||
this.generate(this.editor, button.itemId);
|
||
onCssParsingComplete: function () {
|
||
if (this.blockStyles.isReady) {
|
||
this.cssArray = this.blockStyles.getClasses();
|
||
}
|
||
if (this.getEditorMode() === 'wysiwyg' && this.editor.isEditable()) {
|
||
this.updateValue('BlockStyle');
|
||
}
|
||
},
|
||
/*
|
||
* This function gets called when the editor has changed its mode to "wysiwyg"
|
||
* This handler gets called when the toolbar is being updated
|
||
*/
|
||
onModeChange: function(mode) {
|
||
if (this.getEditorMode() === "wysiwyg") {
|
||
this.generate(this.editor, "BlockStyle");
|
||
onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
|
||
if (mode === 'wysiwyg' && this.editor.isEditable()) {
|
||
this.updateValue(button.itemId);
|
||
}
|
||
},
|
||
/*
|
||
* This function gets called on plugin generation, on toolbar update and on change mode
|
||
* Re-initiate the parsing of the style sheets, if not yet completed, and refresh our toolbar components
|
||
* This handler gets called when the editor has changed its mode to "wysiwyg"
|
||
*/
|
||
generate: function(editor, dropDownId) {
|
||
if (this.cssLoaded && this.getEditorMode() === 'wysiwyg' && this.editor.isEditable()) {
|
||
this.updateValue(dropDownId);
|
||
} else {
|
||
if (this.cssTimeout) {
|
||
window.clearTimeout(this.cssTimeout);
|
||
this.cssTimeout = null;
|
||
}
|
||
if (this.classesUrl && (typeof(HTMLArea.classesLabels) === 'undefined')) {
|
||
this.getJavascriptFile(this.classesUrl, function (options, success, response) {
|
||
if (success) {
|
||
try {
|
||
if (typeof(HTMLArea.classesLabels) === 'undefined') {
|
||
eval(response.responseText);
|
||
this.appendToLog('generate', 'Javascript file successfully evaluated: ' + this.classesUrl);
|
||
}
|
||
} catch(e) {
|
||
this.appendToLog('generate', 'Error evaluating contents of Javascript file: ' + this.classesUrl);
|
||
}
|
||
}
|
||
this.buildCssArray(this.editor, dropDownId);
|
||
});
|
||
} else {
|
||
this.buildCssArray(this.editor, dropDownId);
|
||
}
|
||
onModeChange: function(mode) {
|
||
if (mode === 'wysiwyg' && this.editor.isEditable()) {
|
||
this.updateValue('BlockStyle');
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function updates the current value of the dropdown list
|
||
*/
|
||
updateValue : function(dropDownId) {
|
||
updateValue: function(dropDownId) {
|
||
var dropDown = this.getButton(dropDownId);
|
||
if (dropDown) {
|
||
var classNames = new Array();
|
||
... | ... | |
}
|
||
if (parent) {
|
||
tagName = parent.nodeName.toLowerCase();
|
||
classNames = this.getClassNames(parent);
|
||
classNames = HTMLArea.DOM.getClassNames(parent);
|
||
}
|
||
if (tagName && tagName !== "body"){
|
||
this.buildDropDownOptions(dropDown, tagName);
|
||
... | ... | |
}
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function returns an array containing the class names assigned to the node
|
||
*/
|
||
getClassNames : function (node) {
|
||
var classNames = new Array();
|
||
if (node) {
|
||
if (node.className && /\S/.test(node.className)) {
|
||
classNames = node.className.trim().split(" ");
|
||
}
|
||
if (HTMLArea.reservedClassNames.test(node.className)) {
|
||
var cleanClassNames = new Array();
|
||
var j = -1;
|
||
for (var i = 0; i < classNames.length; ++i) {
|
||
if (!HTMLArea.reservedClassNames.test(classNames[i])) {
|
||
cleanClassNames[++j] = classNames[i];
|
||
}
|
||
}
|
||
return cleanClassNames;
|
||
}
|
||
}
|
||
return classNames;
|
||
},
|
||
|
||
/*
|
||
* This function reinitializes the options of the dropdown
|
||
*/
|
||
initializeDropDown : function (dropDown) {
|
||
initializeDropDown: function (dropDown) {
|
||
var store = dropDown.getStore();
|
||
store.removeAll(false);
|
||
store.insert(0, new store.recordType({
|
||
... | ... | |
}));
|
||
dropDown.setValue('none');
|
||
},
|
||
|
||
/*
|
||
* This function builds the options to be displayed in the dropDown box
|
||
*/
|
||
buildDropDownOptions : function (dropDown, tagName) {
|
||
buildDropDownOptions: function (dropDown, nodeName) {
|
||
var store = dropDown.getStore();
|
||
var cssArray = new Array();
|
||
this.initializeDropDown(dropDown);
|
||
// Get classes allowed for all tags
|
||
if (typeof(this.cssArray.all) !== "undefined") {
|
||
var cssArrayAll = this.cssArray.all;
|
||
if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
|
||
var allowedClasses = this.tags[tagName].allowedClasses;
|
||
for (var cssClass in cssArrayAll) {
|
||
if (cssArrayAll.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) {
|
||
cssArray[cssClass] = cssArrayAll[cssClass];
|
||
}
|
||
}
|
||
} else {
|
||
for (var cssClass in cssArrayAll) {
|
||
if (cssArrayAll.hasOwnProperty(cssClass)) {
|
||
cssArray[cssClass] = cssArrayAll[cssClass];
|
||
}
|
||
}
|
||
if (this.blockStyles.isReady) {
|
||
var allowedClasses = {};
|
||
if (Ext.isDefined(this.cssArray[nodeName])) {
|
||
allowedClasses = this.cssArray[nodeName];
|
||
} else if (this.showTagFreeClasses && Ext.isDefined(this.cssArray['all'])) {
|
||
allowedClasses = this.cssArray['all'];
|
||
}
|
||
}
|
||
// Merge classes allowed for tagName and sort the array
|
||
if (typeof(this.cssArray[tagName]) !== "undefined") {
|
||
var cssArrayTagName = this.cssArray[tagName];
|
||
if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
|
||
var allowedClasses = this.tags[tagName].allowedClasses;
|
||
for (var cssClass in cssArrayTagName) {
|
||
if (cssArrayTagName.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) {
|
||
cssArray[cssClass] = cssArrayTagName[cssClass];
|
||
Ext.iterate(allowedClasses, function (cssClass, value) {
|
||
var style = null;
|
||
if (!this.editor.config.disablePCexamples) {
|
||
if (HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
|
||
style = HTMLArea.classesValues[cssClass];
|
||
} else if (/-[0-9]+$/.test(cssClass) && HTMLArea.classesValues[RegExp.leftContext + '-']) {
|
||
style = HTMLArea.classesValues[RegExp.leftContext + '-'];
|
||
}
|
||
}
|
||
} else {
|
||
for (var cssClass in cssArrayTagName) {
|
||
if (cssArrayTagName.hasOwnProperty(cssClass)) {
|
||
cssArray[cssClass] = cssArrayTagName[cssClass];
|
||
}
|
||
}
|
||
}
|
||
var sortedCssArray = new Object();
|
||
var cssArrayKeys = new Array();
|
||
for (var cssClass in cssArray) {
|
||
if (cssArray.hasOwnProperty(cssClass)) {
|
||
cssArrayKeys.push(cssClass);
|
||
}
|
||
}
|
||
function compare(a, b) {
|
||
x = cssArray[a];
|
||
y = cssArray[b];
|
||
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
||
}
|
||
cssArrayKeys = cssArrayKeys.sort(compare);
|
||
for (var i = 0; i < cssArrayKeys.length; ++i) {
|
||
sortedCssArray[cssArrayKeys[i]] = cssArray[cssArrayKeys[i]];
|
||
}
|
||
cssArray = sortedCssArray;
|
||
store.add(new store.recordType({
|
||
text: value,
|
||
value: cssClass,
|
||
style: style
|
||
}));
|
||
}, this);
|
||
}
|
||
for (var cssClass in cssArray) {
|
||
if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) {
|
||
if (cssClass == 'none') {
|
||
store.getAt(0).set('text', cssArray[cssClass]);
|
||
} else {
|
||
var style = null;
|
||
if (!this.editor.config.disablePCexamples) {
|
||
if (HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
|
||
style = HTMLArea.classesValues[cssClass];
|
||
} else if (/-[0-9]+$/.test(cssClass) && HTMLArea.classesValues[RegExp.leftContext + '-']) {
|
||
style = HTMLArea.classesValues[RegExp.leftContext + '-'];
|
||
}
|
||
}
|
||
store.add(new store.recordType({
|
||
text: cssArray[cssClass],
|
||
value: cssClass,
|
||
style: style
|
||
}));
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function sets the selected option of the dropDown box
|
||
*/
|
||
setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) {
|
||
setSelectedOption: function (dropDown, classNames, noUnknown, defaultClass) {
|
||
var store = dropDown.getStore();
|
||
dropDown.setValue('none');
|
||
if (classNames.length) {
|
||
... | ... | |
});
|
||
}
|
||
dropDown.setDisabled(!(store.getCount()>1));
|
||
},
|
||
|
||
/*
|
||
* This function builds the main array of class selectors
|
||
*/
|
||
buildCssArray : function(editor, dropDownId) {
|
||
this.cssArray = this.parseStyleSheet();
|
||
if (!this.cssLoaded && (this.cssParseCount < 17)) {
|
||
this.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]);
|
||
this.cssParseCount++;
|
||
} else {
|
||
this.cssTimeout = null;
|
||
this.cssLoaded = true;
|
||
this.cssArray = this.sortCssArray(this.cssArray);
|
||
this.updateValue(dropDownId);
|
||
}
|
||
},
|
||
|
||
/*
|
||
* This function parses the stylesheets
|
||
*/
|
||
parseStyleSheet : function() {
|
||
var iframe = this.editor._iframe.contentWindow ? this.editor._iframe.contentWindow.document : this.editor._iframe.contentDocument;
|
||
var newCssArray = new Object();
|
||
this.cssLoaded = true;
|
||
for (var i = 0; i < iframe.styleSheets.length; i++) {
|
||
if (!Ext.isIE) {
|
||
try {
|
||
newCssArray = this.parseCssRule(iframe.styleSheets[i].cssRules, newCssArray);
|
||
} catch(e) {
|
||
this.cssLoaded = false;
|
||
}
|
||
} else {
|
||
try{
|
||
// @import StyleSheets (IE)
|
||
if (iframe.styleSheets[i].imports) {
|
||
newCssArray = this.parseCssIEImport(iframe.styleSheets[i].imports, newCssArray);
|
||
}
|
||
if (iframe.styleSheets[i].rules) {
|
||
newCssArray = this.parseCssRule(iframe.styleSheets[i].rules, newCssArray);
|
||
}
|
||
} catch(e) {
|
||
this.cssLoaded = false;
|
||
}
|
||
}
|
||
}
|
||
return newCssArray;
|
||
},
|
||
|
||
/*
|
||
* This function parses IE import rules
|
||
*/
|
||
parseCssIEImport : function(cssIEImport, cssArray) {
|
||
var newCssArray = new Object();
|
||
newCssArray = cssArray;
|
||
for (var i=0; i < cssIEImport.length; i++) {
|
||
if (cssIEImport[i].imports) {
|
||
newCssArray = this.parseCssIEImport(cssIEImport[i].imports, newCssArray);
|
||
}
|
||
if (cssIEImport[i].rules) {
|
||
newCssArray = this.parseCssRule(cssIEImport[i].rules, newCssArray);
|
||
}
|
||
}
|
||
return newCssArray;
|
||
},
|
||
|
||
/*
|
||
* This function parses gecko css rules
|
||
*/
|
||
parseCssRule : function(cssRules, cssArray) {
|
||
var newCssArray = new Object();
|
||
newCssArray = cssArray;
|
||
for (var rule = 0; rule < cssRules.length; rule++) {
|
||
// StyleRule
|
||
if (cssRules[rule].selectorText) {
|
||
newCssArray = this.parseSelectorText(cssRules[rule].selectorText, newCssArray);
|
||
} else {
|
||
// ImportRule (Mozilla)
|
||
if (cssRules[rule].styleSheet) {
|
||
newCssArray = this.parseCssRule(cssRules[rule].styleSheet.cssRules, newCssArray);
|
||
}
|
||
// MediaRule (Mozilla)
|
||
if (cssRules[rule].cssRules) {
|
||
newCssArray = this.parseCssRule(cssRules[rule].cssRules, newCssArray);
|
||
}
|
||
}
|
||
}
|
||
return newCssArray;
|
||
},
|
||
|
||
/*
|
||
* This function parses each selector rule
|
||
*/
|
||
parseSelectorText : function(selectorText, cssArray) {
|
||
var cssElements = new Array();
|
||
var cssElement = new Array();
|
||
var tagName, className;
|
||
var newCssArray = new Object();
|
||
newCssArray = cssArray;
|
||
if (selectorText.search(/:+/) == -1) {
|
||
// split equal Styles (Mozilla-specific) e.q. head, body {border:0px}
|
||
// for ie not relevant. returns allways one element
|
||
cssElements = selectorText.split(",");
|
||
for (var k = 0; k < cssElements.length; k++) {
|
||
// Match ALL classes (<element name (optional)>.<class name>) in selector rule
|
||
var s = cssElements[k],
|
||
pattern = /(\S*)\.(\S+)/,
|
||
index;
|
||
while ((index = s.search(pattern)) > -1) {
|
||
var match = pattern.exec(s.substring(index));
|
||
s = s.substring(index+match[0].length);
|
||
tagName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : "all";
|
||
className = match[2];
|
||
if (className && !HTMLArea.reservedClassNames.test(className)) {
|
||
if (((tagName != "all") && (!this.tags || !this.tags[tagName]))
|
||
|| ((tagName == "all") && (!this.tags || !this.tags[tagName]) && this.showTagFreeClasses)
|
||
|| (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses && this.tags[tagName].allowedClasses.test(className))) {
|
||
if (!newCssArray[tagName]) {
|
||
newCssArray[tagName] = new Object();
|
||
}
|
||
if (className) {
|