Project

General

Profile

Feature #17436 » 0005899_v7.patch

Administrator Admin, 2008-01-15 11:46

View differences:

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']) : '&nbsp;').
$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']) : '&nbsp;').
$requiredIcon .
($isNotEmpty ? '</a>' : '').
'</div>';
}
(3-3/4)