Bug #17101 » 0005177_v11.patch
t3lib/class.t3lib_tceforms.php (Arbeitskopie) | ||
---|---|---|
var $requiredElements=array(); // Used to register the min and max number of elements for selectorboxes where that apply (in the "group" type for instance)
|
||
var $renderDepth=0; // Keeps track of the rendering depth of nested records.
|
||
var $savedSchemes=array(); // Color scheme buffer.
|
||
var $dynTabLevelStack = array(); // holds tab dividers which were cascaded, required for RTE&IRRE
|
||
var $dynNestedStack = array(); // holds the path an element is nested in (e.g. required for RTEhtmlarea)
|
||
// Internal, registers for user defined functions etc.
|
||
var $additionalCode_pre = array(); // Additional HTML code, printed before the form.
|
||
... | ... | |
if (strstr($itemList, '--div--') !== false && $this->enableTabMenu && $TCA[$table]['ctrl']['dividers2tabs']) {
|
||
$tabIdentString = 'TCEforms:'.$table.':'.$row['uid'];
|
||
$tabIdentStringMD5 = $GLOBALS['TBE_TEMPLATE']->getDynTabMenuId('TCEforms:'.$table.':'.$row['uid']);
|
||
$this->dynTabLevelStack[$tabIdentStringMD5] = 1;
|
||
}
|
||
// Explode the field list and possibly rearrange the order of the fields, if configured for
|
||
... | ... | |
if ($this->enableTabMenu && $TCA[$table]['ctrl']['dividers2tabs']) {
|
||
$this->wrapBorder($out_array[$out_sheet],$out_pointer);
|
||
// Remove last tab entry from the dynNestedStack:
|
||
$out_sheet++;
|
||
// remember what sheet we're currently in
|
||
$this->dynTabLevelStack[$tabIdentStringMD5] = $out_sheet+1;
|
||
// Remove the previous sheet from stack (if any):
|
||
$this->popFromDynNestedStack('tab', $tabIdentStringMD5.'-'.($out_sheet));
|
||
// Remember on which sheet we're currently working:
|
||
$this->pushToDynNestedStack('tab', $tabIdentStringMD5.'-'.($out_sheet+1));
|
||
$out_array[$out_sheet] = array();
|
||
$out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
|
||
}
|
||
} else { // Setting alternative title for "General" tab if "--div--" is the very first element.
|
||
$out_array_meta[$out_sheet]['title'] = $this->sL($parts[1]);
|
||
// Only add the first tab to the dynNestedStack if there are more tabs:
|
||
if (strpos($itemList, '--div--', strlen($fieldInfo))) {
|
||
$this->pushToDynNestedStack('tab', $tabIdentStringMD5.'-1');
|
||
}
|
||
}
|
||
} elseif($theField=='--palette--') {
|
||
if ($parts[2] && !isset($this->palettesRendered[$this->renderDepth][$table][$parts[2]])) {
|
||
... | ... | |
);
|
||
}
|
||
// unset the current level of tab menus
|
||
unset($this->dynTabLevelStack[$tabIdentStringMD5]);
|
||
// Unset the current level of tab menus:
|
||
$this->popFromDynNestedStack('tab', $tabIdentStringMD5.'-'.($out_sheet+1));
|
||
return '
|
||
<tr>
|
||
... | ... | |
}
|
||
|
||
/**
|
||
* Get a list, depending on $this->dynTabLevelStack, that has the information
|
||
* in which tab (--div--) fields are inserted.
|
||
* Push a new element to the dynNestedStack. Thus, every object know, if it's
|
||
* nested in a tab or IRRE level and in which order this was processed.
|
||
*
|
||
* @param string $appendString: String to append for each item
|
||
* @return string A list of cascaded tab divs, like "DTM-2e8791854a-1,DTM-f3c79a0523-4"
|
||
* @param string $type: Type of the level, e.g. "tab" or "inline"
|
||
* @param string $ident: Identifier of the level
|
||
* @return void
|
||
*/
|
||
function getDynTabLevelState($appendString = '') {
|
||
$levels = array();
|
||
foreach ($this->dynTabLevelStack as $tabIdent => $divId) {
|
||
$levels[] = $tabIdent.'-'.$divId.$appendString;
|
||
function pushToDynNestedStack($type, $ident) {
|
||
$this->dynNestedStack[] = array($type, $ident);
|
||
}
|
||
/**
|
||
* Remove an element from the dynNestedStack. If $type and $ident
|
||
* are set, the last element will only be removed, if it matches
|
||
* what is expected to be removed.
|
||
*
|
||
* @param string $type: Type of the level, e.g. "tab" or "inline"
|
||
* @param string $ident: Identifier of the level
|
||
* @return void
|
||
*/
|
||
function popFromDynNestedStack($type=null, $ident=null) {
|
||
if ($type!=null && $ident!=null) {
|
||
$last = end($this->dynNestedStack);
|
||
if ($type==$last[0] && $ident==$last[1]) {
|
||
array_pop($this->dynNestedStack);
|
||
}
|
||
} else {
|
||
array_pop($this->dynNestedStack);
|
||
}
|
||
return implode(',', $levels);
|
||
}
|
||
/**
|
||
* Get the dynNestedStack as associative array.
|
||
* It has the keys raw, tab, inline and sorted.
|
||
* The key "sorted" contains the levels in the sorting order they have been applied.
|
||
*
|
||
* @param boolean $json: Return a JSON string instead of an array
|
||
* @param string $tabSuffix: Add a suffix (e.g. "-DIV") to each tab level
|
||
* @param string $tabSuffix: Add a suffix to each inline level
|
||
* @return mixed Returns an associative array (default), if $json is true, it will be returned as JSON string.
|
||
*/
|
||
function getDynNestedStack($json=false, $tabSuffix='', $inlineSuffix='') {
|
||
$tab = array();
|
||
$inline = array();
|
||
$sorted = array();
|
||
foreach ($this->dynNestedStack as $level) {
|
||
if ($level[0]=='tab') {
|
||
$tab[] = $level[1].$tabSuffix;
|
||
$sorted[] = $level[1].$tabSuffix;
|
||
} elseif ($level[0]=='inline') {
|
||
$inline[] = $level[1].$inlineSuffix;
|
||
$sorted[] = $level[1].$inlineSuffix;
|
||
}
|
||
}
|
||
$result = array(
|
||
// 'raw' => $this->dynNestedStack,
|
||
'tab' => $tab,
|
||
'inline' => $inline,
|
||
'sorted' => $sorted,
|
||
// 'tabSuffix' => $tabSuffix,
|
||
// 'inlineSuffix' => $inlineSuffix,
|
||
);
|
||
return ($json ? $this->inline->getJSON($result) : $result);
|
||
}
|
||
}
|
||
t3lib/class.t3lib_tceforms_inline.php (Arbeitskopie) | ||
---|---|---|
'config' => $config,
|
||
);
|
||
$this->updateStructureNames();
|
||
// Put the current level also to the dynNestedStack of TCEforms:
|
||
$this->fObj->pushToDynNestedStack('inline', $this->inlineNames['object']);
|
||
}
|
||
... | ... | |
$popItem = array_pop($this->inlineStructure['stable']);
|
||
$this->updateStructureNames();
|
||
}
|
||
// Remove the current level also from the dynNestedStack of TCEforms:
|
||
$this->fObj->popFromDynNestedStack();
|
||
return $popItem;
|
||
}
|
||
... | ... | |
* @return integer A pixel value for the margin of each new inline level.
|
||
*/
|
||
function getLevelMargin() {
|
||
$margin = $this->inlineStyles['margin-right'];
|
||
$margin = ($this->inlineStyles['margin-right']+1)*2;
|
||
return $margin;
|
||
}
|
||
}
|
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js (Arbeitskopie) | ||
---|---|---|
HTMLArea.prototype._initEditMode = function () {
|
||
// We can't set designMode when we are in a hidden TYPO3 tab
|
||
// Then we will set it when the tab comes in the front.
|
||
var inTYPO3Tab = false;
|
||
var DTMDiv = this._textArea;
|
||
while (DTMDiv && (DTMDiv.nodeType == 1) && (DTMDiv.tagName.toLowerCase() != "body")) {
|
||
if (DTMDiv.tagName.toLowerCase() == "div" && DTMDiv.id.indexOf("DTM-") != -1 && DTMDiv.id.indexOf("-DIV") != -1 && DTMDiv.className == "c-tablayer") {
|
||
inTYPO3Tab = true;
|
||
break;
|
||
} else {
|
||
DTMDiv = DTMDiv.parentNode;
|
||
}
|
||
var isNested = false;
|
||
var allDisplayed = true;
|
||
|
||
if (this.nested.sorted && this.nested.sorted.length) {
|
||
isNested = true;
|
||
allDisplayed = HTMLArea.allElementsAreDisplayed(this.nested.sorted);
|
||
}
|
||
if (!HTMLArea.is_wamcom) {
|
||
try {
|
||
if (!(inTYPO3Tab && DTMDiv.style.display == "none")) this._doc.designMode = "on";
|
||
if (!isNested || allDisplayed) this._doc.designMode = "on";
|
||
} catch(e) { }
|
||
} else {
|
||
try {
|
||
this._doc.designMode = "on";
|
||
} catch(e) {
|
||
if (!(inTYPO3Tab && DTMDiv.style.display == "none")) {
|
||
if (!isNested || allDisplayed) {
|
||
this._doc.open();
|
||
this._doc.close();
|
||
this._initIframeTimer = window.setTimeout("HTMLArea.initIframe(" + this._editorNumber + ");", 500);
|
||
... | ... | |
// When the TYPO3 TCA feature div2tab is used, the editor iframe may become hidden with style.display = "none"
|
||
// This breaks the editor in Mozilla/Firefox browsers: the designMode attribute needs to be resetted after the style.display of the containing div is resetted to "block"
|
||
// Here we rely on TYPO3 naming conventions for the div id and class name
|
||
if (inTYPO3Tab) HTMLArea._addEvent(DTMDiv, "DOMAttrModified", HTMLArea.DTMDivHandler(this, DTMDiv));
|
||
if (this.nested.sorted && this.nested.sorted.length) {
|
||
var nestedObj, listenerFunction;
|
||
for (var i=0, length=this.nested.sorted.length; i < length; i++) {
|
||
nestedObj = document.getElementById(this.nested.sorted[i]);
|
||
listenerFunction = HTMLArea.NestedListener(this, nestedObj, false);
|
||
HTMLArea._addEvent(nestedObj, 'DOMAttrModified', listenerFunction);
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
... | ... | |
***************************************************/
|
||
/*
|
||
* TYPO3 hidden tab handler
|
||
* TYPO3 hidden tab and inline event listener (gets event calls)
|
||
*/
|
||
HTMLArea.DTMDivHandler = function (editor,DTMDiv) {
|
||
HTMLArea.NestedListener = function (editor,nestedObj,noOpenCloseAction) {
|
||
return (function(ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
HTMLArea.NestedHandler(ev,editor,nestedObj,noOpenCloseAction);
|
||
});
|
||
};
|
||
/*
|
||
* TYPO3 hidden tab and inline event handler (performs actions on event calls)
|
||
*/
|
||
HTMLArea.NestedHandler = function(ev,editor,nestedObj,noOpenCloseAction) {
|
||
window.setTimeout(function() {
|
||
var target = (ev.target) ? ev.target : ev.srcElement;
|
||
if(target == DTMDiv && editor._editMode == "wysiwyg" && DTMDiv.style.display == "block") {
|
||
window.setTimeout( function() {
|
||
try {
|
||
editor._doc.designMode = "on";
|
||
if (editor.config.sizeIncludesToolbar && editor._initialToolbarOffsetHeight != editor._toolbar.offsetHeight) editor.sizeIframe(-2);
|
||
} catch(e) {
|
||
editor._doc.open();
|
||
editor._doc.close();
|
||
editor.initIframe();
|
||
}
|
||
}, 20);
|
||
if(target == nestedObj && editor._editMode == "wysiwyg" && ev.attrName=='style' && (target.style.display == '' || target.style.display == 'block')) {
|
||
// Check if all affected nested elements are displayed (style.display!='none'):
|
||
if (HTMLArea.allElementsAreDisplayed(editor.nested.sorted)) {
|
||
window.setTimeout(function() {
|
||
try {
|
||
editor._doc.designMode = "on";
|
||
if (editor.config.sizeIncludesToolbar && editor._initialToolbarOffsetHeight != editor._toolbar.offsetHeight) {
|
||
editor.sizeIframe(-2);
|
||
}
|
||
} catch(e) {
|
||
// If an event of a parent tab ("nested tabs") is triggered, the following lines should not be
|
||
// processed, because this causes some trouble on all event handlers...
|
||
if (!noOpenCloseAction) {
|
||
editor._doc.open();
|
||
editor._doc.close();
|
||
}
|
||
editor.initIframe();
|
||
}
|
||
}, 50);
|
||
}
|
||
HTMLArea._stopEvent(ev);
|
||
}
|
||
});
|
||
}, 50);
|
||
};
|
||
/*
|
||
* Handle statusbar element events
|
||
*/
|
||
HTMLArea.statusBarHandler = function (ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
var target = (ev.target) ? ev.target : ev.srcElement;
|
||
var editor = target.editor;
|
typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js (Arbeitskopie) | ||
---|---|---|
* Handle statusbar element events
|
||
*/
|
||
HTMLArea.statusBarHandler = function (ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
var target = (ev.target) ? ev.target : ev.srcElement;
|
||
var editor = target.editor;
|
typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js (Arbeitskopie) | ||
---|---|---|
* Handle toolbar element events handler
|
||
*/
|
||
HTMLArea.toolBarButtonHandler = function(ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
var target = (ev.target) ? ev.target : ev.srcElement;
|
||
while (target.tagName.toLowerCase() == "img" || target.tagName.toLowerCase() == "div") target = target.parentNode;
|
||
... | ... | |
* Size the iframe according to user's prefs or initial textarea
|
||
*/
|
||
HTMLArea.prototype.sizeIframe = function(diff) {
|
||
var i;
|
||
var height = (this.config.height == "auto" ? (this._textArea.style.height) : this.config.height);
|
||
var textareaHeight = height;
|
||
// All nested tabs and inline levels in the sorting order they were applied:
|
||
this.nested = RTEarea[this._editorNumber].tceformsNested;
|
||
// Clone the array instead of using a reference (this.accessParentElements will change the array):
|
||
var parentElements = (this.nested.sorted && this.nested.sorted.length ? [].concat(this.nested.sorted) : []);
|
||
// Walk through all nested tabs and inline levels to make a correct positioning:
|
||
var dimensions = this.accessParentElements(parentElements, 'this.getDimensions()');
|
||
var inlineObject = RTEarea[this._editorNumber].tceformsInlineObject;
|
||
var dynTabs = RTEarea[this._editorNumber].tceformsDynTabs;
|
||
var parentElements = new Array();
|
||
if (dynTabs) parentElements = dynTabs.split(',');
|
||
if (inlineObject) parentElements.push(inlineObject);
|
||
var dimensions = this.accessParentElements(parentElements, 'this.getDimensions()');
|
||
|
||
if(height.indexOf("%") == -1) {
|
||
height = parseInt(height) - diff;
|
||
if (this.config.sizeIncludesToolbar) {
|
||
... | ... | |
};
|
||
/**
|
||
* Access an inline relational element and make it "accesible".
|
||
* Access an inline relational element or tab menu and make it "accesible".
|
||
* If a parent object has the style "display: none", offsetWidth & offsetHeight are '0'.
|
||
*
|
||
* @params object callbackFunc: A function to be called, when the embedded objects are "accessible".
|
||
... | ... | |
if (parentElements.length) {
|
||
var currentElement = parentElements.pop();
|
||
var elementStyle = document.getElementById(currentElement).style;
|
||
var actionRequired = elementStyle.display == 'none';
|
||
var actionRequired = (elementStyle.display == 'none' ? true : false);
|
||
|
||
if (actionRequired) {
|
||
var originalVisibility = elementStyle.visibility;
|
||
... | ... | |
HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["keydown","keypress","mousedown","mouseup","drag"], HTMLArea._editorEvent, true);
|
||
|
||
// add unload handler
|
||
HTMLArea._addEvent((this._iframe.contentWindow ? this._iframe.contentWindow : this._iframe.contentDocument), "unload", HTMLArea.removeEditorEvents);
|
||
if (!HTMLArea.hasUnloadHandler) {
|
||
HTMLArea.hasUnloadHandler = true;
|
||
HTMLArea._addEvent((this._iframe.contentWindow ? this._iframe.contentWindow : this._iframe.contentDocument), "unload", HTMLArea.removeEditorEvents);
|
||
}
|
||
|
||
// set cleanWordOnPaste and intercept paste, dragdrop and drop events for wordClean
|
||
if (this.config.cleanWordOnPaste) HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], HTMLArea.cleanWordOnPaste, true);
|
||
... | ... | |
* When we have a form, on reset, re-initialize the HTMLArea content and update the toolbar
|
||
*/
|
||
HTMLArea.resetHandler = function(ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
var form = (ev.target) ? ev.target : ev.srcElement;
|
||
var editor = RTEarea[form._editorNumber]["editor"];
|
||
... | ... | |
HTMLArea.removeEditorEvents = function(ev) {
|
||
if(!ev) var ev = window.event;
|
||
HTMLArea._stopEvent(ev);
|
||
if (HTMLArea.stopAllEvent) { return false; }
|
||
HTMLArea.stopAllEvents = true;
|
||
if (Dialog._modal) {
|
||
Dialog._modal.close();
|
||
Dialog._modal = null;
|
||
... | ... | |
window.clearInterval(editor._timerUndo);
|
||
editor._undoQueue = null;
|
||
// release events
|
||
if (HTMLArea._eventCache && !HTMLArea.is_opera) HTMLArea._eventCache.flush();
|
||
if (HTMLArea.is_ie) HTMLArea._cleanup(editor);
|
||
}
|
||
}
|
||
if (HTMLArea._eventCache && !HTMLArea.is_opera) HTMLArea._eventCache.flush();
|
||
};
|
||
/*
|
||
... | ... | |
* Handler for paste, dragdrop and drop events
|
||
*/
|
||
HTMLArea.cleanWordOnPaste = function(ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
var target = (ev.target) ? ev.target : ev.srcElement;
|
||
var owner = (target.ownerDocument) ? target.ownerDocument : target;
|
||
... | ... | |
* A generic event handler for things that happen in the IFRAME's document.
|
||
*/
|
||
HTMLArea._editorEvent = function(ev) {
|
||
if (HTMLArea.stopAllEvents) { return false; }
|
||
if(!ev) var ev = window.event;
|
||
var target = (ev.target) ? ev.target : ev.srcElement;
|
||
var owner = (target.ownerDocument) ? target.ownerDocument : target;
|
||
... | ... | |
document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
|
||
}
|
||
};
|
||
HTMLArea.allElementsAreDisplayed = function(elements) {
|
||
for (var i=0, length=elements.length; i < length; i++) {
|
||
if (document.getElementById(elements[i]).style.display == 'none') {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php (Arbeitskopie) | ||
---|---|---|
$RTEHeight = $RTEHeight + ($pObj->docLarge ? (isset($BE_USER->userTS['options.']['RTELargeHeightIncrement']) ? $BE_USER->userTS['options.']['RTELargeHeightIncrement'] : 0) : 0);
|
||
$editorWrapWidth = $RTEWidth . 'px';
|
||
$editorWrapHeight = $RTEHeight . 'px';
|
||
$this->RTEdivStyle = $this->RTEdivStyle ? $this->RTEdivStyle : 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:'.$RTEWidth.'px; border: 1px solid black; padding: 2px 0px 2px 2px;';
|
||
$this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:'.$RTEWidth.'px; border: 1px solid black; padding: 2px 0px 2px 2px;';
|
||
$this->toolbar_level_size = $RTEWidth;
|
||
/* =======================================
|
||
... | ... | |
function registerRTEinJS($number, $table='', $uid='', $field='') {
|
||
global $TSFE, $TYPO3_CONF_VARS;
|
||
// if this RTE is shown inline of an IRRE record, the JS functions need to know about that
|
||
if ($this->TCEform->inline->inlineNames['object']) {
|
||
$tceformsInlineObject = $this->TCEform->inline->inlineNames['object'].'['.$table.']['.$uid.']_fields';
|
||
}
|
||
// if this RTE is shown inline of an IRRE record or a Tab sheet, the JS functions need to know about that
|
||
$tabSuffix = '-DIV';
|
||
$inlineSuffix = '['.$table.']['.$uid.']_fields';
|
||
|
||
$registerRTEinJSString = (!is_object($TSFE) ? '' : '
|
||
' . '/*<![CDATA[*/') . '
|
||
... | ... | |
RTEarea['.$number.']["showTagFreeClasses"] = ' . (trim($this->thisConfig['showTagFreeClasses'])?'true':'false') . ';
|
||
RTEarea['.$number.']["useHTTPS"] = ' . ((trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'])?'true':'false') . ';
|
||
RTEarea['.$number.']["enableMozillaExtension"] = ' . (($this->client['BROWSER'] == 'gecko' && $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableMozillaExtension'])?'true':'false') . ';
|
||
RTEarea['.$number.']["tceformsInlineObject"] = "' . $tceformsInlineObject . '";
|
||
RTEarea['.$number.']["tceformsDynTabs"] = "' . $this->TCEform->getDynTabLevelState('-DIV') . '";';
|
||
|
||
RTEarea['.$number.']["tceformsNested"] = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(true, $tabSuffix, $inlineSuffix) : '[]') . ';';
|
||
// The following properties apply only to the backend
|
||
if (!is_object($TSFE)) {
|
||
$registerRTEinJSString .= '
|
||
... | ... | |
RTEarea['.$number.']["enablePersonalDicts"] = ' . ($this->spellCheckerPersonalDicts ? 'true' : 'false') . ';
|
||
RTEarea['.$number.']["userUid"] = "' . $this->userUid . '";';
|
||
}
|
||
|
||
// Setting the plugin flags
|
||
$registerRTEinJSString .= '
|
||
RTEarea['.$number.']["plugin"] = new Object();';
|