Feature #17436 » 0005899_v7.patch
t3lib/class.t3lib_tceforms.php (Arbeitskopie) | ||
---|---|---|
var $requiredFields=array(); // Used to register input-field names, which are required. (Done during rendering of the fields). This information is then used later when the JavaScript is made.
|
||
var $requiredAdditional=array(); // Used to register input-field names, which are required an have additional requirements (e.g. like a date/time must be positive integer). The information of this array is merged with $this->requiredFields later.
|
||
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 $requiredNested=array(); // Used to determine where $requiredFields or $requiredElements are nested (in Tabs or IRRE)
|
||
var $renderDepth=0; // Keeps track of the rendering depth of nested records.
|
||
var $savedSchemes=array(); // Color scheme buffer.
|
||
var $dynNestedStack = array(); // holds the path an element is nested in (e.g. required for RTEhtmlarea)
|
||
... | ... | |
foreach ($evalList as $func) {
|
||
switch ($func) {
|
||
case 'required':
|
||
$this->requiredFields[$table.'_'.$row['uid'].'_'.$field]=$PA['itemFormElName'];
|
||
$this->registerRequiredProperty('field', $table.'_'.$row['uid'].'_'.$field, $PA['itemFormElName']);
|
||
// Mark this field for date/time disposal:
|
||
if (array_intersect($evalList, array('date', 'datetime', 'time'))) {
|
||
$this->requiredAdditional[$PA['itemFormElName']]['isPositiveNumber'] = true;
|
||
... | ... | |
$minitems = t3lib_div::intInRange($config['minitems'],0);
|
||
// Register the required number of elements:
|
||
$this->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
|
||
$this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field));
|
||
// Get "removeItems":
|
||
$removeItems = t3lib_div::trimExplode(',',$PA['fieldTSConfig']['removeItems'],1);
|
||
... | ... | |
}
|
||
$item.= '<input type="hidden" name="'.$PA['itemFormElName'].'_mul" value="'.($config['multiple']?1:0).'"'.$disabled.' />';
|
||
$this->requiredElements[$PA['itemFormElName']] = array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field);
|
||
$this->registerRequiredProperty('range', $PA['itemFormElName'], array($minitems,$maxitems,'imgName'=>$table.'_'.$row['uid'].'_'.$field));
|
||
$info='';
|
||
// "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. See http://typo3.org/documentation/document-library/doc_core_api/Wizards_Configuratio/.
|
||
... | ... | |
inline.addToDataArray('.t3lib_div::array2json($this->inline->inlineData).');
|
||
';
|
||
}
|
||
// Registered nested elements for tabs or inline levels:
|
||
if (count($this->requiredNested)) {
|
||
$out .= '
|
||
TBE_EDITOR.addNested('.t3lib_div::array2json($this->requiredNested).');
|
||
';
|
||
}
|
||
// elements which are required or have a range definition:
|
||
if (count($elements)) {
|
||
$out .= '
|
||
... | ... | |
TBE_EDITOR.initRequired()
|
||
';
|
||
}
|
||
// $this->additionalJS_post:
|
||
// $this->additionalJS_submit:
|
||
if ($this->additionalJS_submit) {
|
||
$additionalJS_submit = implode('', $this->additionalJS_submit);
|
||
$additionalJS_submit = str_replace("\r", '', $additionalJS_submit);
|
||
... | ... | |
}
|
||
return ($json ? t3lib_div::array2json($result) : $result);
|
||
}
|
||
/**
|
||
* Takes care of registering properties in requiredFields and requiredElements.
|
||
* The current hierarchy of IRRE and/or Tabs is stored. Thus, it is possible to determine,
|
||
* which required field/element was filled incorrectly and show it, even if the Tab or IRRE
|
||
* level is hidden.
|
||
*
|
||
* @param string $type: Type of requirement ('field' or 'range')
|
||
* @param string $name: The name of the form field
|
||
* @param mixed $value: For type 'field' string, for type 'range' array
|
||
* @return void
|
||
*/
|
||
protected function registerRequiredProperty($type, $name, $value) {
|
||
if ($type == 'field' && is_string($value)) {
|
||
$this->requiredFields[$name] = $value;
|
||
// requiredFields have name/value swapped! For backward compatibility we keep this:
|
||
$itemName = $value;
|
||
} elseif ($type == 'range' && is_array($value)) {
|
||
$this->requiredElements[$name] = $value;
|
||
$itemName = $name;
|
||
}
|
||
// Set the situation of nesting for the current field:
|
||
$this->registerNestedElement($itemName);
|
||
}
|
||
/**
|
||
* Sets the current situation of nested tabs and inline levels for a given element.
|
||
*
|
||
* @param string $itemName: The element the nesting should be stored for
|
||
* @param boolean $setLevel: Set the reverse level lookup - default: true
|
||
* @return void
|
||
*/
|
||
protected function registerNestedElement($itemName, $setLevel=true) {
|
||
$dynNestedStack = $this->getDynNestedStack();
|
||
if (count($dynNestedStack) && preg_match('/^(.+\])\[(\w+)\]$/', $itemName, $match)) {
|
||
array_shift($match);
|
||
$this->requiredNested[$itemName] = array(
|
||
'parts' => $match,
|
||
'level' => $dynNestedStack,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
t3lib/jsfunc.inline.js (Arbeitskopie) | ||
---|---|---|
// Remove from TBE_EDITOR (required fields, required range, etc.):
|
||
if (TBE_EDITOR && TBE_EDITOR.removeElement) {
|
||
var removeStack = [];
|
||
inlineRecords = Element.getElementsByClassName(objectId+'_div', 'inlineRecord');
|
||
// Remove nested child records from TBE_EDITOR required/range checks:
|
||
for (i=inlineRecords.length-1; i>=0; i--) {
|
||
... | ... | |
childObjectId = this.data.map[inlineRecords[i].name];
|
||
childTable = this.data.config[childObjectId].table;
|
||
for (j=records.length-1; j>=0; j--) {
|
||
TBE_EDITOR.removeElement(this.prependFormFieldNames+'['+childTable+']['+records[j]+']');
|
||
removeStack.push(this.prependFormFieldNames+'['+childTable+']['+records[j]+']');
|
||
}
|
||
}
|
||
}
|
||
TBE_EDITOR.removeElement(this.prependFormFieldNames+shortName);
|
||
removeStack.push(this.prependFormFieldNames+shortName);
|
||
TBE_EDITOR.removeElementArray(removeStack);
|
||
}
|
||
// If the record is new and was never saved before, just remove it from DOM:
|
t3lib/class.t3lib_tceforms_inline.php (Arbeitskopie) | ||
---|---|---|
*/
|
||
function renderForeignRecordHeaderControl($parentUid, $foreign_table, $rec, $config = array()) {
|
||
// Initialize:
|
||
$cells=array();
|
||
$cells = array();
|
||
$isNewItem = substr($rec['uid'], 0, 3) == 'NEW';
|
||
$tcaTableCtrl =& $GLOBALS['TCA'][$foreign_table]['ctrl'];
|
||
... | ... | |
// This expresses the edit permissions for this particular element:
|
||
$permsEdit = ($isPagesTable && ($localCalcPerms&2)) || (!$isPagesTable && ($calcPerms&16));
|
||
// Icon to visualize that a required field is nested in this inline level:
|
||
$cells[] = '<img id="'.$nameObjectFtId.'_req" src="clear.gif" width="10" height="10" hspace="4" vspace="3" alt="" />';
|
||
// "Info": (All records)
|
||
if (!$isNewItem)
|
||
$cells[]='<a href="#" onclick="'.htmlspecialchars('top.launchView(\''.$foreign_table.'\', \''.$rec['uid'].'\'); return false;').'">'.
|
typo3/jsfunc.tbe_editor.js (Arbeitskopie) | ||
---|---|---|
*/
|
||
elements: {},
|
||
nested: {'field':{}, 'level':{}},
|
||
ignoreElements: [],
|
||
recentUpdatedElements: {},
|
||
actionChecks: { submit: [] },
|
||
... | ... | |
TBE_EDITOR.recentUpdatedElements = elements;
|
||
TBE_EDITOR.elements = $H(TBE_EDITOR.elements).merge(elements).toObject();
|
||
},
|
||
addNested: function(elements) {
|
||
var name, nested, levelMax, i, currentLevel, subLevel;
|
||
// Merge data structures:
|
||
if (elements) {
|
||
for (name in elements) {
|
||
nested = elements[name];
|
||
if (nested.level && nested.level.length) {
|
||
// If the first level is of type 'inline', it could be created by a AJAX request to IRRE.
|
||
// So, try to get the upper levels this dynamic level is nested in:
|
||
if (typeof inline!='undefined' && nested.level[0][0]=='inline') {
|
||
nested.level = inline.findContinuedNestedLevel(nested.level, nested.level[0][1]);
|
||
}
|
||
levelMax = nested.level.length-1;
|
||
for (i=0; i<=levelMax; i++) {
|
||
currentLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i]);
|
||
if (typeof TBE_EDITOR.nested.level[currentLevel] == 'undefined') {
|
||
TBE_EDITOR.nested.level[currentLevel] = { 'clean': true, 'item': {}, 'sub': {} };
|
||
}
|
||
// Add next sub level to the current level:
|
||
if (i<levelMax) {
|
||
subLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i+1]);
|
||
TBE_EDITOR.nested.level[currentLevel].sub[subLevel] = true;
|
||
// Add the current item to the last level in nesting:
|
||
} else {
|
||
TBE_EDITOR.nested.level[currentLevel].item[name] = nested.parts;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Merge the nested fields:
|
||
TBE_EDITOR.nested.field = $H(TBE_EDITOR.nested.field).merge(elements).toObject();
|
||
}
|
||
},
|
||
removeElement: function(record) {
|
||
if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) {
|
||
// Inform envolved levels the this record is removed and the missing requirements are resolved:
|
||
$H(TBE_EDITOR.elements[record]).each(
|
||
function(pair) {
|
||
TBE_EDITOR.notifyNested(record+'['+pair.key+']', true);
|
||
}
|
||
);
|
||
delete(TBE_EDITOR.elements[record]);
|
||
}
|
||
},
|
||
removeElementArray: function(removeStack) {
|
||
if (removeStack && removeStack.length) {
|
||
TBE_EDITOR.ignoreElements = removeStack;
|
||
for (var i=removeStack.length; i>=0; i--) {
|
||
TBE_EDITOR.removeElement(removeStack[i]);
|
||
}
|
||
TBE_EDITOR.ignoreElements = [];
|
||
}
|
||
},
|
||
getElement: function(record, field, type) {
|
||
var result = null;
|
||
var element;
|
||
... | ... | |
checkElements: function(type, recentUpdated, record, field) {
|
||
var result = 1;
|
||
var elementName, elementData, elementRecord, elementField;
|
||
var source = recentUpdated ? TBE_EDITOR.recentUpdatedElements : TBE_EDITOR.elements;
|
||
var source = (recentUpdated ? TBE_EDITOR.recentUpdatedElements : TBE_EDITOR.elements);
|
||
if (TBE_EDITOR.ignoreElements.length && TBE_EDITOR.ignoreElements.indexOf(record)!=-1) {
|
||
return result;
|
||
}
|
||
if (type) {
|
||
if (record && field) {
|
||
elementName = record+'['+field+']';
|
||
elementData = TBE_EDITOR.getElement(record, field, type);
|
||
if (elementData) {
|
||
if (!TBE_EDITOR.checkElementByType(type, elementName, elementData)) result = 0;
|
||
if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
|
||
result = 0;
|
||
}
|
||
}
|
||
} else {
|
||
... | ... | |
elementData = TBE_EDITOR.getElement(elementRecord, elementField, type);
|
||
if (elementData) {
|
||
elementName = elementRecord+'['+elementField+']';
|
||
if (!TBE_EDITOR.checkElementByType(type, elementName, elementData)) result = 0;
|
||
if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
|
||
result = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
return result;
|
||
},
|
||
checkElementByType: function(type, elementName, elementData) {
|
||
checkElementByType: function(type, elementName, elementData, autoNotify) {
|
||
var result = 1;
|
||
if (type) {
|
||
... | ... | |
var value = document[TBE_EDITOR.formname][elementName].value;
|
||
if (!value || elementData.additional && elementData.additional.isPositiveNumber && (isNaN(value) || Number(value) <= 0)) {
|
||
result = 0;
|
||
TBE_EDITOR.setImage('req_'+elementData.requiredImg, TBE_EDITOR.images.req);
|
||
if (autoNotify) {
|
||
TBE_EDITOR.setImage('req_'+elementData.requiredImg, TBE_EDITOR.images.req);
|
||
TBE_EDITOR.notifyNested(elementName, false);
|
||
}
|
||
}
|
||
} else if (type == 'range' && elementData.range) {
|
||
var formObj = document[TBE_EDITOR.formname][elementName+'_list'];
|
||
... | ... | |
}
|
||
if (!TBE_EDITOR.checkRange(formObj, elementData.range[0], elementData.range[1])) {
|
||
result = 0;
|
||
TBE_EDITOR.setImage('req_'+elementData.rangeImg, TBE_EDITOR.images.req);
|
||
if (autoNotify) {
|
||
TBE_EDITOR.setImage('req_'+elementData.rangeImg, TBE_EDITOR.images.req);
|
||
TBE_EDITOR.notifyNested(elementName, false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
},
|
||
// Notify tabs and inline levels with nested requiredFields/requiredElements:
|
||
notifyNested: function(elementName, resolved) {
|
||
if (TBE_EDITOR.nested.field[elementName]) {
|
||
var i, nested, element, fieldLevels, fieldLevelIdent, nestedLevelType, nestedLevelName;
|
||
fieldLevels = TBE_EDITOR.nested.field[elementName].level;
|
||
TBE_EDITOR.nestedCache = {};
|
||
for (i=fieldLevels.length-1; i>=0; i--) {
|
||
nestedLevelType = fieldLevels[i][0];
|
||
nestedLevelName = fieldLevels[i][1];
|
||
fieldLevelIdent = TBE_EDITOR.getNestedLevelIdent(fieldLevels[i]);
|
||
// Construct the CSS id strings of the image/icon tags showing the notification:
|
||
if (nestedLevelType == 'tab') {
|
||
element = nestedLevelName+'-REQ';
|
||
} else if (nestedLevelType == 'inline') {
|
||
element = nestedLevelName+'_req';
|
||
} else {
|
||
continue;
|
||
}
|
||
// Set the icons:
|
||
if (resolved) {
|
||
if (TBE_EDITOR.checkNested(fieldLevelIdent)) {
|
||
TBE_EDITOR.setImage(element, TBE_EDITOR.images.clear);
|
||
} else {
|
||
break;
|
||
}
|
||
} else {
|
||
if (TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[fieldLevelIdent]) {
|
||
TBE_EDITOR.nested.level[fieldLevelIdent].clean = false;
|
||
}
|
||
TBE_EDITOR.setImage(element, TBE_EDITOR.images.req);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
// Check all the input fields on a given level of nesting - if only on is unfilled, the whole level is marked as required:
|
||
checkNested: function(nestedLevelIdent) {
|
||
var nestedLevel, isClean;
|
||
if (nestedLevelIdent && TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[nestedLevelIdent]) {
|
||
nestedLevel = TBE_EDITOR.nested.level[nestedLevelIdent];
|
||
if (!nestedLevel.clean) {
|
||
if (typeof nestedLevel.item == 'object') {
|
||
$H(nestedLevel.item).each(
|
||
function(pair) {
|
||
if (isClean || typeof isClean == 'undefined') {
|
||
isClean = (
|
||
TBE_EDITOR.checkElements('required', false, pair.value[0], pair.value[1]) &&
|
||
TBE_EDITOR.checkElements('range', false, pair.value[0], pair.value[1])
|
||
);
|
||
}
|
||
}
|
||
);
|
||
if (typeof isClean != 'undefined' && !isClean) {
|
||
return false;
|
||
}
|
||
}
|
||
if (typeof nestedLevel.sub == 'object') {
|
||
$H(nestedLevel.sub).each(
|
||
function(pair) {
|
||
if (isClean || typeof isClean == 'undefined') {
|
||
isClean = TBE_EDITOR.checkNested(pair.key);
|
||
}
|
||
}
|
||
);
|
||
if (typeof isClean != 'undefined' && !isClean) {
|
||
return false;
|
||
}
|
||
}
|
||
// Store the result, that this level (the fields on this and the sub levels) are clean:
|
||
nestedLevel.clean = true;
|
||
}
|
||
}
|
||
return true;
|
||
},
|
||
getNestedLevelIdent: function(level) {
|
||
return level.join('::');
|
||
},
|
||
addActionChecks: function(type, checks) {
|
||
TBE_EDITOR.actionChecks[type].push(checks);
|
||
},
|
||
... | ... | |
if (TBE_EDITOR.getElement(theRecord,field,'required') && document[TBE_EDITOR.formname][theField]) {
|
||
if (TBE_EDITOR.checkElements('required', false, theRecord, field)) {
|
||
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
|
||
TBE_EDITOR.notifyNested(theField, true);
|
||
} else {
|
||
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
|
||
TBE_EDITOR.notifyNested(theField, false);
|
||
}
|
||
}
|
||
if (TBE_EDITOR.getElement(theRecord,field,'range') && document[TBE_EDITOR.formname][theField]) {
|
||
if (TBE_EDITOR.checkElements('range', false, theRecord, field)) {
|
||
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
|
||
TBE_EDITOR.notifyNested(theField, true);
|
||
} else {
|
||
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
|
||
TBE_EDITOR.notifyNested(theField, false);
|
||
}
|
||
}
|
||
... | ... | |
TBE_EDITOR.checkElements('range', true);
|
||
},
|
||
setImage: function(name,image) {
|
||
var object;
|
||
if (document[name]) {
|
||
object = document[name];
|
||
} else if (document.getElementById(name)) {
|
||
object = document.getElementById(name);
|
||
}
|
||
if (object) {
|
||
if (typeof image == 'object') {
|
||
document[name].src = image.src;
|
||
} else {
|
typo3/template.php (Arbeitskopie) | ||
---|---|---|
}
|
||
$mouseOverOut = ' onmouseover="DTM_mouseOver(this);" onmouseout="DTM_mouseOut(this);"';
|
||
$requiredIcon = '<img id="'.$id.'-'.$index.'-REQ" src="clear.gif" width="10" height="10" hspace="4" alt="" />';
|
||
if (!$foldout) {
|
||
// Create TAB cell:
|
||
... | ... | |
($isNotEmpty ? '<a href="#" onclick="'.htmlspecialchars($onclick).'"'.($def['linkTitle'] ? ' title="'.htmlspecialchars($def['linkTitle']).'"':'').'>' : '').
|
||
$def['icon'].
|
||
($def['label'] ? htmlspecialchars($def['label']) : ' ').
|
||
$requiredIcon.
|
||
$this->icons($def['stateIcon'],'margin-left: 10px;').
|
||
($isNotEmpty ? '</a>' :'').
|
||
'</td>';
|
||
... | ... | |
($isNotEmpty ? '<a href="#" onclick="'.htmlspecialchars($onclick).'"'.($def['linkTitle'] ? ' title="'.htmlspecialchars($def['linkTitle']).'"':'').'>' : '').
|
||
$def['icon'].
|
||
($def['label'] ? htmlspecialchars($def['label']) : ' ').
|
||
$requiredIcon .
|
||
($isNotEmpty ? '</a>' : '').
|
||
'</div>';
|
||
}
|