Index: branches/5.1.x/core/kernel/db/dbitem.php
===================================================================
--- branches/5.1.x/core/kernel/db/dbitem.php	(revision 14407)
+++ branches/5.1.x/core/kernel/db/dbitem.php	(revision 14408)
@@ -1,1551 +1,1569 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 defined('FULL_PATH') or die('restricted access!');
 
 /**
 * DBItem
 *
 * Desciption
 * @package kernel4
 */
 class kDBItem extends kDBBase {
 
 	/**
 	* Description
 	*
 	* @var array Associative array of current item' field values
 	* @access public
 	*/
 	var $FieldValues;
 
 	/**
 	 * Unformatted field values, before parse
 	 *
 	 * @var Array
 	 * @access private
 	 */
 	var $DirtyFieldValues = Array();
 
 	/**
 	 * Holds item values after loading (not affected by submit)
 	 *
 	 * @var Array
 	 * @access private
 	 */
 	var $OriginalFieldValues = Array ();
 
 	var $FieldErrors;
 
 	var $ErrorMsgs = Array();
 
 	/**
 	* If set to true, Update will skip Validation before running
 	*
 	* @var array Associative array of current item' field values
 	* @access public
 	*/
 	var $IgnoreValidation = false;
 
 	var $Loaded = false;
 
 	/**
 	* Holds item' primary key value
 	*
 	* @var int Value of primary key field for current item
 	* @access public
 	*/
 	var $ID;
 
 	/**
 	 * This object is used in cloning operations
 	 *
 	 * @var bool
 	 */
 	var $inCloning = false;
 
 	function kDBItem()
 	{
 		parent::kDBBase();
 		$this->ErrorMsgs['required'] = '!la_err_required!'; //'Field is required';
 		$this->ErrorMsgs['unique'] = '!la_err_unique!'; //'Field value must be unique';
 		$this->ErrorMsgs['value_out_of_range'] = '!la_err_value_out_of_range!'; //'Field is out of range, possible values from %s to %s';
 		$this->ErrorMsgs['length_out_of_range'] = '!la_err_length_out_of_range!'; //'Field is out of range';
 		$this->ErrorMsgs['bad_type'] = '!la_err_bad_type!'; //'Incorrect data format, please use %s';
 		$this->ErrorMsgs['invalid_format'] = '!la_err_invalid_format!'; //'Incorrect data format, please use %s';
 		$this->ErrorMsgs['bad_date_format'] = '!la_err_bad_date_format!'; //'Incorrect date format, please use (%s) ex. (%s)';
 		$this->ErrorMsgs['primary_lang_required'] = '!la_err_primary_lang_required!';
 	}
 
 	function SetDirtyField($field_name, $field_value)
 	{
 		$this->DirtyFieldValues[$field_name] = $field_value;
 	}
 
 	function GetDirtyField($field_name)
 	{
 		return $this->DirtyFieldValues[$field_name];
 	}
 
 	function GetOriginalField($field_name, $formatted = false, $format=null)
 	{
 		if (array_key_exists($field_name, $this->OriginalFieldValues)) {
 			// item was loaded before
 			$value = $this->OriginalFieldValues[$field_name];
 		}
 		else {
 			// no original fields -> use default field value
 			$value = $this->Fields[$field_name]['default'];
 		}
 
 		if (!$formatted) {
 			return $value;
 		}
 
 		$options = $this->GetFieldOptions($field_name);
 		$res = $value;
 		if (array_key_exists('formatter', $options)) {
 			$formatter =& $this->Application->recallObject($options['formatter']);
 			/* @var $formatter kFormatter */
 
 			$res = $formatter->Format($value, $field_name, $this, $format);
 		}
 		return $res;
 	}
 
 	/**
 	 * Sets original field value (useful for custom virtual fields)
 	 *
 	 * @param string $field_name
 	 */
 	function SetOriginalField($field_name, $field_value)
 	{
 		$this->OriginalFieldValues[$field_name] = $field_value;
 	}
 
 	/**
 	 * Set's default values for all fields
 	 *
 	 * @param bool $populate_ml_fields create all ml fields from db in config or not
 	 *
 	 * @access public
 	 */
 	function SetDefaultValues($populate_ml_fields = false)
 	{
 		parent::SetDefaultValues($populate_ml_fields);
 		if ($populate_ml_fields) {
 			$this->PopulateMultiLangFields();
 		}
 
 		foreach ($this->Fields as $field => $params) {
 			if ( isset($params['default']) ) {
 				$this->SetDBField($field, $params['default']);
 			}
 			else {
 				$this->SetDBField($field, NULL);
 			}
 		}
 	}
 
 	/**
 	* Sets current item field value
 	* (applies formatting)
 	*
 	* @access public
 	* @param string $name Name of the field
 	* @param mixed $value Value to set the field to
 	* @return void
 	*/
 	function SetField($name,$value)
 	{
 		$options = $this->GetFieldOptions($name);
 		$parsed = $value;
 		if ($value == '') {
 			$parsed = NULL;
 		}
 
 		// kFormatter is always used, to make sure, that numeric value is converted to normal representation
 		// according to regional format, even when formatter is not set (try seting format to 1.234,56 to understand why)
 		$formatter =& $this->Application->recallObject(isset($options['formatter']) ? $options['formatter'] : 'kFormatter');
 		$parsed = $formatter->Parse($value, $name, $this);
 
 		$this->SetDBField($name,$parsed);
 	}
 
 	/**
 	* Sets current item field value
 	* (doesn't apply formatting)
 	*
 	* @access public
 	* @param string $name Name of the field
 	* @param mixed $value Value to set the field to
 	* @return void
 	*/
 	function SetDBField($name,$value)
 	{
 		$this->FieldValues[$name] = $value;
 		/*if (isset($this->Fields[$name]['formatter'])) {
 			$formatter =& $this->Application->recallObject($this->Fields[$name]['formatter']);
 			$formatter->UpdateSubFields($name, $value, $this->Fields[$name], $this);
 		}*/
 	}
 
 	/**
 	 * Set's field error, if pseudo passed not found then create it with message text supplied.
 	 * Don't owerrite existing pseudo translation.
 	 *
 	 * @param string $field
 	 * @param string $pseudo
 	 * @param string $error_label
 	 *
 	 * @return bool
 	 */
 	function SetError($field, $pseudo, $error_label = null, $error_params = null)
 	{
 		$error_field = isset($this->Fields[$field]['error_field']) ? $this->Fields[$field]['error_field'] : $field;
 		if (isset($this->FieldErrors[$error_field]['pseudo'])) {
 			// don't set more then one error on field
 			return false;
 		}
 
 		$this->FieldErrors[$error_field]['pseudo'] = $pseudo;
 
 		if (isset($error_params)) {
 			if (array_key_exists('value', $error_params)) {
 				$this->FieldErrors[$error_field]['value'] = $error_params['value'];
 				unset($error_params['value']);
 			}
 
 			// additional params, that helps to determine error sources
 			$this->FieldErrors[$error_field]['params'] = $error_params;
 		}
 
 		if (isset($error_label) && !isset($this->ErrorMsgs[$pseudo])) {
 			// label for error (only when not already set)
 			$this->ErrorMsgs[$pseudo] = (substr($error_label, 0, 1) == '+') ? substr($error_label, 1) : '!'.$error_label.'!';
 		}
 
 		return true;
 	}
 
 	/**
 	* Return current item' field value by field name
 	* (doesn't apply formatter)
 	*
 	* @access public
 	* @param string $name field name to return
 	* @return mixed
 	*/
 	function GetDBField($name)
 	{
 		/*if (!array_key_exists($name, $this->FieldValues) && defined('DEBUG_MODE') && DEBUG_MODE) {
 			$this->Application->Debugger->appendTrace();
 		}*/
 
 		return $this->FieldValues[$name];
 	}
 
 	function HasField($name)
 	{
 		return isset($this->FieldValues[$name]);
 	}
 
 	function GetFieldValues()
 	{
 		return $this->FieldValues;
 	}
 
 	/**
 	* Sets item' fields corresponding to elements in passed $hash values.
 	*
 	* The function sets current item fields to values passed in $hash, by matching $hash keys with field names
 	* of current item. If current item' fields are unknown {@link kDBItem::PrepareFields()} is called before acutally setting the fields
 	*
 	* @access public
 	* @param Array $hash
 	* @param Array $set_fields Optional param, field names in target object to set, other fields will be skipped
 	* @return void
 	*/
 	function SetFieldsFromHash($hash, $set_fields = null)
 	{
 		// used in formatter which work with multiple fields together
 		foreach($hash as $field_name => $field_value) {
 			if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) {
 				continue;
 			}
 
 			if (is_array($set_fields) && !in_array($field_name, $set_fields)) {
 				continue;
 			}
 
 			$this->SetDirtyField($field_name, $field_value);
 		}
 
 		// formats all fields using associated formatters
 		foreach ($hash as $field_name => $field_value)
 		{
 			if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) {
 				continue;
 			}
 
 			if (is_array($set_fields) && !in_array($field_name, $set_fields)) {
 				continue;
 			}
 
 			$this->SetField($field_name,$field_value);
 		}
 	}
 
 	function SetDBFieldsFromHash($hash, $set_fields = null)
 	{
 		foreach ($hash as $field_name => $field_value) {
 			if (is_numeric($field_name) || !array_key_exists($field_name, $this->Fields)) {
 				continue;
 			}
 
 			if (is_array($set_fields) && !in_array($field_name, $set_fields)) {
 				continue;
 			}
 
 			$this->SetDBField($field_name, $field_value);
 		}
 	}
 
 	/**
 	* Returns part of SQL WHERE clause identifing the record, ex. id = 25
 	*
 	* @access public
 	* @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
 	* @param Array $keys_hash alternative, then item id, keys hash to load item by
 	* @return void
 	* @see kDBItem::Load()
 	* @see kDBItem::Update()
 	* @see kDBItem::Delete()
 	*/
 	function GetKeyClause($method=null, $keys_hash = null)
 	{
 		if (!isset($keys_hash)) {
 			$keys_hash = Array ($this->IDField => $this->ID);
 		}
 
 		$ret = '';
 
 		foreach ($keys_hash as $field => $value) {
 			if (!preg_match('/\./', $field)) {
 				$ret .= '(`' . $this->TableName . '`.' . $field . ' = ' . $this->Conn->qstr($value) . ') AND ';
 			}
 			else {
 				$ret .= '(' . $field . ' = ' . $this->Conn->qstr($value) . ') AND ';
 			}
 		}
 
 		return substr($ret, 0, -5);
 	}
 
 	/**
 	* Loads item from the database by given id
 	*
 	* @access public
 	* @param mixed $id item id of keys->values hash to load item by
 	* @param string $id_field_name Optional parameter to load item by given Id field
 	* @param bool $cachable cache this query result based on it's prefix serial
 	* @return bool True if item has been loaded, false otherwise
 	*/
 	function Load($id, $id_field_name = null, $cachable = false)
 	{
 		if ( isset($id_field_name) ) {
 			$this->SetIDField($id_field_name); // set new IDField
 		}
 
 		$keys_sql = '';
 		if (is_array($id)) {
 			$keys_sql = $this->GetKeyClause('load', $id);
 		}
 		else {
 			$this->setID($id);
 			$keys_sql = $this->GetKeyClause('load');
 		}
 
 		if ( isset($id_field_name) ) {
 			// restore original IDField from unit config
 			$this->setIDField( $this->Application->getUnitOption($this->Prefix, 'IDField') );
 		}
 
 		if (($id === false) || !$keys_sql) {
 			return $this->Clear();
 		}
 
 		if (!$this->raiseEvent('OnBeforeItemLoad', $id)) {
 			return false;
 		}
 
 		$q = $this->GetSelectSQL() . ' WHERE ' . $keys_sql;
 
 		if ($cachable && $this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
 			$serial_name = $this->Application->incrementCacheSerial($this->Prefix == 'st' ? 'c' : $this->Prefix, isset($id_field_name) ? null : $id, false);
 			$cache_key = 'kDBItem::Load_' . crc32(serialize($id) . '-' . $this->IDField) . '[%' . $serial_name . '%]';
 			$field_values = $this->Application->getCache($cache_key, false);
 
 			if ($field_values === false) {
 				$field_values = $this->Conn->GetRow($q);
 
 				if ($field_values !== false) {
 					// only cache, when data was retrieved
 					$this->Application->setCache($cache_key, $field_values);
 				}
 			}
 		}
 		else {
 			$field_values = $this->Conn->GetRow($q);
 		}
 
 		if ($field_values) {
 			$this->FieldValues = array_merge_recursive2($this->FieldValues, $field_values);
 			$this->OriginalFieldValues = $this->FieldValues;
 		}
 		else {
 			return $this->Clear();
 		}
 
 		if (is_array($id) || isset($id_field_name)) {
 			$this->setID($this->FieldValues[$this->IDField]);
 		}
 
 		$this->UpdateFormattersSubFields(); // used for updating separate virtual date/time fields from DB timestamp (for example)
 
 		$this->raiseEvent('OnAfterItemLoad', $this->GetID());
 		$this->Loaded = true;
 
 		return true;
 	}
 
 	/**
 	 * Loads object from hash (not db)
 	 *
 	 * @param Array $fields_hash
 	 * @param string $id_field
 	 */
 	function LoadFromHash($fields_hash, $id_field = null)
 	{
 		if (!isset($id_field)) {
 			$id_field = $this->IDField;
 		}
 
 		$this->Clear();
 
 		if (!$fields_hash || !array_key_exists($id_field, $fields_hash)) {
 			// no data OR id field missing
 			return false;
 		}
 
 		$id = $fields_hash[$id_field];
 
 		if ( !$this->raiseEvent('OnBeforeItemLoad', $id) ) {
 			return false;
 		}
 
 		$this->FieldValues = array_merge_recursive2($this->FieldValues, $fields_hash);
 		$this->OriginalFieldValues = $this->FieldValues;
 
 		$this->setID($id);
 		$this->UpdateFormattersSubFields(); // used for updating separate virtual date/time fields from DB timestamp (for example)
 
 		$this->raiseEvent('OnAfterItemLoad', $id);
 
 		$this->Loaded = true;
 
 		return true;
 	}
 
 	/**
 	* Builds select sql, SELECT ... FROM parts only
 	*
 	* @access public
 	* @return string
 	*/
 	function GetSelectSQL()
 	{
 		$sql = $this->addCalculatedFields($this->SelectClause);
 		return parent::GetSelectSQL($sql);
 	}
 
 	function UpdateFormattersMasterFields()
 	{
 		foreach ($this->Fields as $field => $options) {
 			if (isset($options['formatter'])) {
 				$formatter =& $this->Application->recallObject($options['formatter']);
 				$formatter->UpdateMasterFields($field, $this->GetDBField($field), $options, $this);
 			}
 		}
 	}
 
 	/**
 	 * Allows to skip certain fields from getting into sql queries
 	 *
 	 * @param string $field_name
 	 * @param mixed $force_id
 	 * @return bool
 	 */
 	function skipField($field_name, $force_id = false)
 	{
 		$skip = false;
 
 		// 1. skipping 'virtual' field
 		$skip = $skip || array_key_exists($field_name, $this->VirtualFields);
 
 		// 2. don't write empty field value to db, when "skip_empty" option is set
 		$field_value = array_key_exists($field_name, $this->FieldValues) ? $this->FieldValues[$field_name] : false;
 
 		if (array_key_exists($field_name, $this->Fields)) {
 			$skip_empty = array_key_exists('skip_empty', $this->Fields[$field_name]) ? $this->Fields[$field_name]['skip_empty'] : false;
 		}
 		else {
 			// field found in database, but not declared in unit config
 			$skip_empty = false;
 		}
 
 		$skip = $skip || (!$field_value && $skip_empty);
 
 		// 3. skipping field not in Fields (nor virtual, nor real)
 		$skip = $skip || !array_key_exists($field_name, $this->Fields);
 
 		return $skip;
 	}
 
 	/**
 	* Updates previously loaded record with current item' values
 	*
 	* @access public
 	* @param int Primery Key Id to update
 	* @return bool
 	*/
 	function Update($id = null, $system_update = false)
 	{
 		if (isset($id)) {
 			$this->setID($id);
 		}
 
 		if (!$this->raiseEvent('OnBeforeItemUpdate')) {
 			return false;
 		}
 
 		if (!isset($this->ID)) {
 			// ID could be set inside OnBeforeItemUpdate event, so don't combine this check with previous one
 			return false;
 		}
 
 		// validate before updating
 		if (!$this->Validate()) {
 			return false;
 		}
 
 	    if (!$this->FieldValues) {
 	    	// nothing to update
 	    	return true;
 	    }
 
 	    $sql = '';
 
 	    foreach ($this->FieldValues as $field_name => $field_value) {
 	    	if ($this->skipField($field_name)) {
 	    		continue;
 	    	}
 
 	    	if ( is_null($field_value) ) {
 	    		if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) {
 	    			// "kFormatter::Parse" methods converts empty values to NULL and for
 	    			// not-null fields they are replaced with default value here
 	    			$field_value = $this->Fields[$field_name]['default'];
 	    		}
 	    	}
 
 	    	$sql .= '`' . $field_name . '` = ' . $this->Conn->qstr($field_value) . ', ';
 	   	}
 
 	   	$sql = 'UPDATE ' . $this->TableName . '
 	   			SET ' . substr($sql, 0, -2) . '
 	   			WHERE ' . $this->GetKeyClause('update');
 
 	    if ($this->Conn->ChangeQuery($sql) === false) {
 	    	// there was and sql error
 	    	return false;
 	    }
 
 		$affected_rows = $this->Conn->getAffectedRows();
 
 		if (!$system_update && ($affected_rows > 0)) {
 			$this->setModifiedFlag(clUPDATE);
 		}
 
 		$this->saveCustomFields();
 	    $this->raiseEvent('OnAfterItemUpdate');
 	    $this->OriginalFieldValues = $this->FieldValues;
 	    $this->Loaded = true;
 
 	    if ($this->mode != 't') {
 			$this->Application->resetCounters($this->TableName);
 		}
 
 		return true;
 	}
 
 	function ValidateField($field)
 	{
 		$options = $this->Fields[$field];
 
 		/*if (isset($options['formatter'])) {
 			$formatter =& $this->Application->recallObject($options['formatter']);
 			$formatter->UpdateMasterFields($field, $this->GetDBField($field), $options, $this);
 		}*/
 
 		$error_field = isset($options['error_field']) ? $options['error_field'] : $field;
 		$res = !isset($this->FieldErrors[$error_field]['pseudo']) || !$this->FieldErrors[$error_field]['pseudo'];
 
 		$res = $res && $this->ValidateRequired($field, $options);
 		$res = $res && $this->ValidateType($field, $options);
 		$res = $res && $this->ValidateRange($field, $options);
 		$res = $res && $this->ValidateUnique($field, $options);
 		$res = $res && $this->CustomValidation($field, $options);
 
 		return $res;
 	}
 
 	/**
 	 * Validate all item fields based on
 	 * constraints set in each field options
 	 * in config
 	 *
 	 * @return bool
 	 * @access private
 	 */
 	function Validate()
 	{
 		$this->UpdateFormattersMasterFields(); //order is critical - should be called BEFORE checking errors
 
 		if ($this->IgnoreValidation) {
 			return true;
 		}
 
 		// will apply any custom validation to the item
 		$this->raiseEvent('OnBeforeItemValidate');
 
 		$global_res = true;
 		foreach ($this->Fields as $field => $params) {
 			$res = $this->ValidateField($field);
 
 
 			$global_res = $global_res && $res;
 		}
 
 		if (!$global_res && $this->Application->isDebugMode()) {
 			$error_msg = '	Validation failed in prefix <strong>'.$this->Prefix.'</strong>,
 							FieldErrors follow (look at items with <strong>"pseudo"</strong> key set)<br />
 							You may ignore this notice if submitted data really has a validation error';
 			trigger_error(trim($error_msg), E_USER_NOTICE);
 			$this->Application->Debugger->dumpVars($this->FieldErrors);
 		}
 
 		if ($global_res) {
 			// no validation errors
 			$this->raiseEvent('OnAfterItemValidate');
 		}
 
 		return $global_res;
 	}
 
 	/**
 	 * Check field value by user-defined alghoritm
 	 *
 	 * @param string $field field name
 	 * @param Array $params field options from config
 	 * @return bool
 	 */
 	function CustomValidation($field, $params)
 	{
 		return true;
 	}
 
 	/**
 	 * Check if item has errors
 	 *
 	 * @param Array $skip_fields fields to skip during error checking
 	 * @return bool
 	 */
 	function HasErrors($skip_fields)
 	{
 		$global_res = false;
 
 		foreach ($this->Fields as $field => $field_params) {
 			// If Formatter has set some error messages during values parsing
 			if ( !( in_array($field, $skip_fields) ) &&
 				isset($this->FieldErrors[$field]['pseudo']) && $this->FieldErrors[$field] != '') {
 				$global_res = true;
 			}
 		}
 		return $global_res;
 	}
 
 	/**
 	 * Check if value in field matches field type specified in config
 	 *
 	 * @param string $field field name
 	 * @param Array $params field options from config
 	 * @return bool
 	 */
 	function ValidateType($field, $params)
 	{
 		$res = true;
 		$val = $this->FieldValues[$field];
 		if ( 	$val != '' &&
 					isset($params['type']) &&
 					preg_match("#int|integer|double|float|real|numeric|string#", $params['type'])
 				) {
 			if ($params['type'] == 'numeric') {
 				trigger_error('Invalid field type <strong>'.$params['type'].'</strong> (in ValidateType method), please use <strong>float</strong> instead', E_USER_NOTICE);
 				$params['type'] = 'float';
 			}
 			$res = is_numeric($val);
 			if ($params['type']=='string' || $res) {
 				$f = 'is_'.$params['type'];
 				settype($val, $params['type']);
 				$res = $f($val) && ($val == $this->FieldValues[$field]);
 			}
 			if (!$res) {
 				$this->SetError($field, 'bad_type', null, $params['type']);
 			}
 		}
 		return $res;
 	}
 
 	/**
 	 * Check if value is set for required field
 	 *
 	 * @param string $field field name
 	 * @param Array $params field options from config
 	 * @return bool
 	 * @access private
 	 */
 	function ValidateRequired($field, $params)
 	{
 		$res = true;
 		if (isset($params['required']) && $params['required']) {
 			$check_value = $this->FieldValues[$field];
 			if ($this->Application->ConfigValue('TrimRequiredFields')) {
 				$check_value = trim($check_value);
 			}
 			$res = ((string)$check_value != '');
 		}
 
 		if (!$res) {
 			$this->SetError($field, 'required');
 		}
 
 		return $res;
 	}
 
 	/**
 	 * Validates that current record has unique field combination among other table records
 	 *
 	 * @param string $field field name
 	 * @param Array $params field options from config
 	 * @return bool
 	 * @access private
 	 */
 	function ValidateUnique($field, $params)
 	{
 		$res = true;
 		$unique_fields = getArrayValue($params,'unique');
 		if($unique_fields !== false)
 		{
 			$where = Array();
 			array_push($unique_fields,$field);
 			foreach($unique_fields as $unique_field)
 			{
 				// if field is not empty or if it is required - we add where condition
 				if ((string)$this->GetDBField($unique_field) != '' || (isset($this->Fields[$unique_field]['required']) && $this->Fields[$unique_field]['required'])) {
 					$where[] = '`'.$unique_field.'` = '.$this->Conn->qstr( $this->GetDBField($unique_field) );
 				}
 				else {
 					// not good if we check by less fields than indicated
 					return true;
 				}
 			}
 			// This can ONLY happen if all unique fields are empty and not required.
 			// In such case we return true, because if unique field is not required there may be numerous empty values
 //			if (!$where) return true;
 
 			$sql = 'SELECT COUNT(*) FROM %s WHERE ('.implode(') AND (',$where).') AND ('.$this->IDField.' <> '.(int)$this->ID.')';
 
 			$res_temp = $this->Conn->GetOne( str_replace('%s', $this->TableName, $sql) );
 
 			$current_table_only = getArrayValue($params, 'current_table_only'); // check unique record only in current table
 			$res_live = $current_table_only ? 0 : $this->Conn->GetOne( str_replace('%s', $this->Application->GetLiveName($this->TableName), $sql) );
 
 			$res = ($res_temp == 0) && ($res_live == 0);
 
 			if (!$res) {
 				$this->SetError($field, 'unique');
 			}
 		}
 		return $res;
 	}
 
 	/**
 	 * Check if field value is in range specified in config
 	 *
 	 * @param string $field field name
 	 * @param Array $params field options from config
 	 * @return bool
 	 * @access private
 	 */
 	function ValidateRange($field, $params)
 	{
 		$res = true;
 		$val = $this->FieldValues[$field];
 
 		if ( isset($params['type']) && preg_match("#int|integer|double|float|real#", $params['type']) && strlen($val) > 0 ) {
 			if ( isset($params['max_value_inc'])) {
 				$res = $res && $val <= $params['max_value_inc'];
 				$max_val = $params['max_value_inc'].' (inclusive)';
 			}
 			if ( isset($params['min_value_inc'])) {
 				$res = $res && $val >= $params['min_value_inc'];
 				$min_val = $params['min_value_inc'].' (inclusive)';
 			}
 			if ( isset($params['max_value_exc'])) {
 				$res = $res && $val < $params['max_value_exc'];
 				$max_val = $params['max_value_exc'].' (exclusive)';
 			}
 			if ( isset($params['min_value_exc'])) {
 				$res = $res && $val > $params['min_value_exc'];
 				$min_val = $params['min_value_exc'].' (exclusive)';
 			}
 		}
 		if (!$res) {
 			if ( !isset($min_val) ) $min_val = '-&infin;';
 			if ( !isset($max_val) ) $max_val = '&infin;';
 
 			$this->SetError($field, 'value_out_of_range', null, Array ($min_val, $max_val));
 			return $res;
 		}
 		if ( isset($params['max_len'])) {
 			$res = $res && mb_strlen($val) <= $params['max_len'];
 		}
 		if ( isset($params['min_len'])) {
 			$res = $res && mb_strlen($val) >= $params['min_len'];
 		}
 		if (!$res) {
 			$error_params = Array (getArrayValue($params, 'min_len'), getArrayValue($params, 'max_len'));
 			$this->SetError($field, 'length_out_of_range', null, $error_params);
 			return $res;
 		}
 		return $res;
 	}
 
 	/**
 	 * Return error message for field
 	 *
 	 * @param string $field
 	 * @return string
 	 * @access public
 	 */
 	function GetErrorMsg($field, $force_escape = null)
 	{
 		if( !isset($this->FieldErrors[$field]) ) return '';
 
 		$err = getArrayValue($this->FieldErrors[$field], 'pseudo');
 		if (!$err) return '';
 		// if special error msg defined in config
 		if( isset($this->Fields[$field]['error_msgs'][$err]) )
 		{
 			$msg = $this->Fields[$field]['error_msgs'][$err];
 		}
 		else //fall back to defaults
 		{
 			if( !isset($this->ErrorMsgs[$err]) ) {
 				trigger_error('No user message is defined for pseudo error <b>'.$err.'</b><br>', E_USER_WARNING);
 				return $err; //return the pseudo itself
 			}
 			$msg = $this->ErrorMsgs[$err];
 		}
 		$msg = $this->Application->ReplaceLanguageTags($msg, $force_escape);
 
 		if ( isset($this->FieldErrors[$field]['params']) )
 		{
 			return vsprintf($msg, $this->FieldErrors[$field]['params']);
 		}
 		return $msg;
 	}
 
 	/**
 	* Creates a record in the database table with current item' values
 	*
 	* @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE!
 	* @access public
 	* @return bool
 	*/
 	function Create($force_id = false, $system_create = false)
 	{
 		if (!$this->raiseEvent('OnBeforeItemCreate')) {
 			return false;
 		}
 
 		// Validating fields before attempting to create record
 		if (!$this->Validate()) {
 			return false;
 		}
 
 		if (is_int($force_id)) {
 			$this->FieldValues[$this->IDField] = $force_id;
 		}
 		elseif (!$force_id || !is_bool($force_id)) {
 			$this->FieldValues[$this->IDField] = $this->generateID();
 		}
 
 		$fields_sql = '';
 		$values_sql = '';
 		foreach ($this->FieldValues as $field_name => $field_value) {
 			if ($this->skipField($field_name, $force_id)) {
 				continue;
 			}
 
 			if (is_null($field_value)) {
 				if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) {
 					// "kFormatter::Parse" methods converts empty values to NULL and for
 	    			// not-null fields they are replaced with default value here
 					$values_sql .= $this->Conn->qstr($this->Fields[$field_name]['default']);
 				}
 				else {
 					$values_sql .= $this->Conn->qstr($field_value);
 				}
 			}
 			else {
 				if (($field_name == $this->IDField) && ($field_value == 0) && !is_int($force_id)) {
 					// don't skip IDField in INSERT statement, just use DEFAULT keyword as it's value
 					$values_sql .= 'DEFAULT';
 				}
 				else {
 					$values_sql .= $this->Conn->qstr($field_value);
 				}
 			}
 
 			$fields_sql .= '`' . $field_name . '`, '; //Adding field name to fields block of Insert statement
 			$values_sql .= ', ';
 		}
 
 		$sql = 'INSERT INTO ' . $this->TableName . ' (' . substr($fields_sql, 0, -2) . ')
 				VALUES (' . substr($values_sql, 0, -2) . ')';
 
 		//Executing the query and checking the result
 		if ($this->Conn->ChangeQuery($sql) === false) {
 			return false;
 		}
 
 		$insert_id = $this->Conn->getInsertID();
 		if ($insert_id == 0) {
 			// insert into temp table (id is not auto-increment field)
 			$insert_id = $this->FieldValues[$this->IDField];
 		}
 		$this->setID($insert_id);
 
 		$this->OriginalFieldValues = $this->FieldValues;
 
 		if (!$system_create){
 			$this->setModifiedFlag(clCREATE);
 		}
 
 		$this->saveCustomFields();
 		if ($this->mode != 't') {
 			$this->Application->resetCounters($this->TableName);
 		}
 
 		if ($this->IsTempTable() && ($this->Application->GetTopmostPrefix($this->Prefix) != $this->Prefix) && !is_int($force_id)) {
 			// temp table + subitem = set negative id
 			$this->setTempID();
 		}
 
 		$this->raiseEvent('OnAfterItemCreate');
 		$this->Loaded = true;
 
 		return true;
 	}
 
 	/**
 	* Deletes the record from databse
 	*
 	* @access public
 	* @return bool
 	*/
 	function Delete($id = null)
 	{
 		if (isset($id)) {
 			$this->setID($id);
 		}
 
 		if (!$this->raiseEvent('OnBeforeItemDelete')) {
 			return false;
 		}
 
 		$sql = 'DELETE FROM ' . $this->TableName . '
 				WHERE ' . $this->GetKeyClause('Delete');
 
 		$ret = $this->Conn->ChangeQuery($sql);
 		$affected_rows = $this->Conn->getAffectedRows();
 
 		if ($affected_rows > 0) {
 			$this->setModifiedFlag(clDELETE); // will change affected rows, so get it before this line
 
 			// something was actually deleted
 			$this->raiseEvent('OnAfterItemDelete');
 		}
 
 		if ($this->mode != 't') {
 			$this->Application->resetCounters($this->TableName);
 		}
 
 		return $ret;
 	}
 
 	function PopulateMultiLangFields()
 	{
 		foreach ($this->Fields as $field => $options) {
 			// master field is set only for CURRENT language
 			$formatter = array_key_exists('formatter', $options) ? $options['formatter'] : false;
 
 			if (($formatter == 'kMultiLanguage') && array_key_exists('master_field', $options) && array_key_exists('error_field', $options)) {
 				// MuliLanguage formatter sets error_field to master_field, but in PopulateMlFields mode,
 				// we display ML fields directly so we set it back to itself, otherwise error will not be displayed
 				unset($this->Fields[$field]['error_field']);
 			}
 		}
 	}
 
 	/**
 	 * Sets new name for item in case if it is beeing copied
 	 * in same table
 	 *
 	 * @param array $master Table data from TempHandler
 	 * @param int $foreign_key ForeignKey value to filter name check query by
 	 * @param string $title_field FieldName to alter, by default - TitleField of the prefix
 	 * @param string $format sprintf-style format of renaming pattern, by default Copy %1$s of %2$s which makes it Copy [Number] of Original Name
 	 * @access private
 	 */
 	function NameCopy($master=null, $foreign_key=null, $title_field=null, $format='Copy %1$s of %2$s')
 	{
 		if (!isset($title_field)) {
 		$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
 		if (!$title_field || isset($this->CalculatedFields[$title_field]) ) return;
 		}
 
 		$new_name = $this->GetDBField($title_field);
 		$original_checked = false;
 		do {
 			if ( preg_match('/'.sprintf($format, '([0-9]*) *', '(.*)').'/', $new_name, $regs) ) {
 				$new_name = sprintf($format, ($regs[1]+1), $regs[2]);
 			}
 			elseif ($original_checked) {
 				$new_name = sprintf($format, '', $new_name);
 			}
 
 			// if we are cloning in temp table this will look for names in temp table,
 			// since object' TableName contains correct TableName (for temp also!)
 			// if we are cloning live - look in live
 			$query = 'SELECT '.$title_field.' FROM '.$this->TableName.'
 								WHERE '.$title_field.' = '.$this->Conn->qstr($new_name);
 
 			$foreign_key_field = getArrayValue($master, 'ForeignKey');
 			$foreign_key_field = is_array($foreign_key_field) ? $foreign_key_field[ $master['ParentPrefix'] ] : $foreign_key_field;
 
 			if ($foreign_key_field && isset($foreign_key)) {
 				$query .= ' AND '.$foreign_key_field.' = '.$foreign_key;
 			}
 
 			$res = $this->Conn->GetOne($query);
 
 			/*// if not found in live table, check in temp table if applicable
 			if ($res === false && $object->Special == 'temp') {
 				$query = 'SELECT '.$name_field.' FROM '.$this->GetTempName($master['TableName']).'
 									WHERE '.$name_field.' = '.$this->Conn->qstr($new_name);
 				$res = $this->Conn->GetOne($query);
 			}*/
 
 			$original_checked = true;
 		} while ($res !== false);
 		$this->SetDBField($title_field, $new_name);
 	}
 
 	function raiseEvent($name, $id = null, $additional_params = Array())
 	{
 		if( !isset($id) ) $id = $this->GetID();
 		$event = new kEvent( Array('name'=>$name,'prefix'=>$this->Prefix,'special'=>$this->Special) );
 		$event->setEventParam('id', $id);
 
 		if ($additional_params) {
 			foreach ($additional_params as $ap_name => $ap_value) {
 				$event->setEventParam($ap_name, $ap_value);
 			}
 		}
 
 		$this->Application->HandleEvent($event);
 		return $event->status == erSUCCESS ? true : false;
 	}
 
 	/**
 	 * Set's new ID for item
 	 *
 	 * @param int $new_id
 	 * @access public
 	 */
 	function setID($new_id)
 	{
 		$this->ID = $new_id;
 		$this->SetDBField($this->IDField, $new_id);
 	}
 
 	/**
 	 * Generate and set new temporary id
 	 *
 	 * @access private
 	 */
 	function setTempID()
 	{
 		$new_id = (int)$this->Conn->GetOne('SELECT MIN('.$this->IDField.') FROM '.$this->TableName);
 		if($new_id > 0) $new_id = 0;
 		--$new_id;
 
 		$this->Conn->Query('UPDATE '.$this->TableName.' SET `'.$this->IDField.'` = '.$new_id.' WHERE `'.$this->IDField.'` = '.$this->GetID());
 
 		if ($this->ShouldLogChanges(true)) {
 			// Updating TempId in ChangesLog, if changes are disabled
 			$ses_var_name = $this->Application->GetTopmostPrefix($this->Prefix) . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
 			$changes = $this->Application->RecallVar($ses_var_name);
 			$changes = $changes ? unserialize($changes) : Array ();
 
 			if ($changes) {
 				foreach ($changes as $key => $rec) {
 					if ($rec['Prefix'] == $this->Prefix && $rec['ItemId'] == $this->GetID()) {
 						// change log for record, that's ID was just updated -> update in change log record too
 						$changes[$key]['ItemId'] = $new_id;
 					}
 
 					if ($rec['MasterPrefix'] == $this->Prefix && $rec['MasterId'] == $this->GetID()) {
 						// master item id was changed
 						$changes[$key]['MasterId'] = $new_id;
 					}
 
 					if (in_array($this->Prefix, $rec['ParentPrefix']) && $rec['ParentId'][$this->Prefix] == $this->GetID()) {
 						// change log record of given item's sub item -> update changed id's in dependent fields
 						$changes[$key]['ParentId'][$this->Prefix] = $new_id;
 
 						if (array_key_exists('DependentFields', $rec)) {
 							// these are fields from table of $rec['Prefix'] table!
 							// when one of dependent fields goes into idfield of it's parent item, that was changed
 							$parent_table_key = $this->Application->getUnitOption($rec['Prefix'], 'ParentTableKey');
 							$parent_table_key = is_array($parent_table_key) ? $parent_table_key[$this->Prefix] : $parent_table_key;
 
 							if ($parent_table_key == $this->IDField) {
 								$foreign_key = $this->Application->getUnitOption($rec['Prefix'], 'ForeignKey');
 								$foreign_key = is_array($foreign_key) ? $foreign_key[$this->Prefix] : $foreign_key;
 
 								$changes[$key]['DependentFields'][$foreign_key] = $new_id;
 							}
 						}
 					}
 				}
 			}
 
 			$this->Application->StoreVar($ses_var_name, serialize($changes));
 		}
 
 		$this->SetID($new_id);
 	}
 
 	/**
 	 * Set's modification flag for main prefix of current prefix to true
 	 *
 	 * @access private
 	 * @author Alexey
 	 */
 	function setModifiedFlag($mode = null)
 	{
 		$main_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
 		$this->Application->StoreVar($main_prefix . '_modified', '1', true); // true for optional
 
 		if ($this->ShouldLogChanges(true)) {
 			$this->LogChanges($main_prefix, $mode);
 
 			if (!$this->IsTempTable()) {
 				$handler =& $this->Application->recallObject($this->Prefix . '_EventHandler');
 				/* @var $handler kDBEventHandler */
 
 				$ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
 				$handler->SaveLoggedChanges($ses_var_name, $this->ShouldLogChanges());
 			}
 		}
 	}
 
 	/**
 	 * Determines, that changes made to this item should be written to change log
 	 *
 	 * @param bool $log_changes
 	 * @return bool
 	 */
 	function ShouldLogChanges($log_changes = null)
 	{
 		if (!isset($log_changes)) {
 			// specific logging mode no forced -> use global logging settings
 			$log_changes = $this->Application->getUnitOption($this->Prefix, 'LogChanges') || $this->Application->ConfigValue('UseChangeLog');
 		}
 
 		return $log_changes && !$this->Application->getUnitOption($this->Prefix, 'ForceDontLogChanges');
 	}
 
 	function LogChanges($main_prefix, $mode)
 	{
 		if (!$mode) {
 			return ;
 		}
 
 		$ses_var_name = $main_prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
 		$changes = $this->Application->RecallVar($ses_var_name);
 		$changes = $changes ? unserialize($changes) : Array ();
 
 		$fields_hash = Array (
 			'Prefix' => $this->Prefix,
 			'ItemId' => $this->GetID(),
 			'OccuredOn' => adodb_mktime(),
 			'MasterPrefix' => $main_prefix,
 			'Action' => $mode,
 		);
 
 		if ($this->Prefix == $main_prefix) {
 			// main item
 			$fields_hash['MasterId'] = $this->GetID();
 			$fields_hash['ParentPrefix'] = Array ($main_prefix);
 			$fields_hash['ParentId'] = Array ($main_prefix => $this->GetID());
 		}
 		else {
 			// sub item
 			// collect foreign key values (for serial reset)
 			$foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey');
 			$dependent_fields = $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = Array ();
 
 			if (is_array($foreign_keys)) {
 				foreach ($foreign_keys as $prefix => $field_name) {
 					$dependent_fields[$field_name] = $this->GetDBField($field_name);
 					$fields_hash['ParentPrefix'][] = $prefix;
 					$fields_hash['ParentId'][$prefix] = $this->getParentId($prefix);
 				}
 			}
 			else {
 				$dependent_fields[$foreign_keys] = $this->GetDBField($foreign_keys);
 				$fields_hash['ParentPrefix'] = Array ( $this->Application->getUnitOption($this->Prefix, 'ParentPrefix') );
 				$fields_hash['ParentId'][ $fields_hash['ParentPrefix'][0] ] = $this->getParentId('auto');
 			}
 
 			$fields_hash['DependentFields'] = $dependent_fields;
 
 
 			// works only, when main item is present in url, when subitem is changed
 			$master_id = $this->Application->GetVar($main_prefix . '_id');
 
 			if ($master_id === false) {
 				// works in case of we are not editing topmost item, when subitem is created/updated/deleted
 				$master_id = $this->getParentId('auto', true);
 			}
 
 			$fields_hash['MasterId'] = $master_id;
 		}
 
 		switch ($mode) {
 			case clUPDATE:
 				$to_save = array_merge($this->GetTitleField(), $this->GetChangedFields());
 				break;
 
 			case clCREATE:
 				$to_save = $this->GetTitleField();
 				break;
 
 			case clDELETE:
 				$to_save = array_merge($this->GetTitleField(), $this->GetRealFields());
 				break;
 		}
 
 		$fields_hash['Changes'] = serialize($to_save);
 		$changes[] = $fields_hash;
 
 		$this->Application->StoreVar($ses_var_name, serialize($changes));
 	}
 
 	/**
 	 * Returns current item parent's ID
 	 *
 	 * @param bool $top_most return topmost parent, when used
 	 * @return int
 	 */
 	function getParentId($parent_prefix, $top_most = false)
 	{
 		$current_id = $this->GetID();
 		$current_prefix = $this->Prefix;
 
 		if ($parent_prefix == 'auto') {
 			$parent_prefix = $this->Application->getUnitOption($current_prefix, 'ParentPrefix');
 		}
 
 		if (!$parent_prefix) {
 			return $current_id;
 		}
 
 		do {
 			// field in this table
 			$foreign_key = $this->Application->getUnitOption($current_prefix, 'ForeignKey');
 			$foreign_key = is_array($foreign_key) ? $foreign_key[$parent_prefix] : $foreign_key;
 
 			// get foreign key value for $current_prefix
 			if ($current_prefix == $this->Prefix) {
 				$foreign_key_value = $this->GetDBField($foreign_key);
 			}
 			else {
 				$id_field = $this->Application->getUnitOption($current_prefix, 'IDField');
 				$table_name = $this->Application->getUnitOption($current_prefix, 'TableName');
 
 				if ($this->IsTempTable()) {
 					$table_name = $this->Application->GetTempName($table_name, 'prefix:' . $current_prefix);
 				}
 
 				$sql = 'SELECT ' . $foreign_key . '
 						FROM ' . $table_name . '
 						WHERE ' . $id_field . ' = ' . $current_id;
 				$foreign_key_value = $this->Conn->GetOne($sql);
 			}
 
 			// field in parent table
 			$parent_table_key = $this->Application->getUnitOption($current_prefix, 'ParentTableKey');
 			$parent_table_key = is_array($parent_table_key) ? $parent_table_key[$parent_prefix] : $parent_table_key;
 
 			$parent_id_field = $this->Application->getUnitOption($parent_prefix, 'IDField');
 			$parent_table_name = $this->Application->getUnitOption($parent_prefix, 'TableName');
 
 			if ($this->IsTempTable()) {
 				$parent_table_name = $this->Application->GetTempName($parent_table_name, 'prefix:' . $current_prefix);
 			}
 
 			if ($parent_id_field == $parent_table_key) {
 				// sub-item is related by parent item idfield
 				$current_id = $foreign_key_value;
 			}
 			else {
 				// sub-item is related by other parent item field
 				$sql = 'SELECT ' . $parent_id_field . '
 						FROM ' . $parent_table_name . '
 						WHERE ' . $parent_table_key . ' = ' . $foreign_key_value;
 				$current_id = $this->Conn->GetOne($sql);
 			}
 
 			$current_prefix = $parent_prefix;
 
 			if (!$top_most) {
 				break;
 			}
 		} while ( $parent_prefix = $this->Application->getUnitOption($current_prefix, 'ParentPrefix') );
 
 		return $current_id;
 	}
 
 	/**
 	 * Returns title field (if any)
 	 *
 	 * @return Array
 	 */
 	function GetTitleField()
 	{
 		$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
 
 		if ($title_field) {
 			$value = $this->GetField($title_field);
 			return $value ? Array ($title_field => $value) : Array ();
 		}
 
 		return Array ();
 	}
 
 	/**
 	 * Returns only fields, that are present in database (no virtual and no calculated fields)
 	 *
 	 * @return Array
 	 */
 	function GetRealFields()
 	{
 		if (function_exists('array_diff_key')) {
 			$db_fields = array_diff_key($this->FieldValues, $this->VirtualFields, $this->CalculatedFields);
 		}
 		else {
 			$db_fields = Array();
 
 			foreach ($this->FieldValues as $key => $value) {
 				if (array_key_exists($key, $this->VirtualFields) || array_key_exists($key, $this->CalculatedFields)) {
 					continue;
 				}
 
 				$db_fields[$key] = $value;
 			}
 		}
 
 		return $db_fields;
 	}
 
 	/**
 	 * Returns only changed database field
 	 *
 	 * @param bool $include_virtual_fields
 	 * @return Array
 	 */
 	function GetChangedFields($include_virtual_fields = false)
 	{
 		$changes = Array ();
 		$fields = $include_virtual_fields ? $this->FieldValues : $this->GetRealFields();
 		$diff = array_diff_assoc($fields, $this->OriginalFieldValues);
 
 		foreach ($diff as $field => $new_value) {
 			$old_value = $this->GetOriginalField($field, true);
 			$new_value = $this->GetField($field);
 
 			if ($old_value != $new_value) {
 				// "0.00" and "0.0000" are stored as strings and will differ. Double check to prevent that.
 				$changes[$field] = Array ('old' => $old_value, 'new' => $new_value);
 			}
 		}
 
 		return $changes;
 	}
 
 	/**
 	 * Returns ID of currently processed record
 	 *
 	 * @return int
 	 * @access public
 	 */
 	function GetID()
 	{
 		return $this->ID;
 	}
 
 	/**
 	 * Generates ID for new items before inserting into database
 	 *
 	 * @return int
 	 * @access private
 	 */
 	function generateID()
 	{
 		return 0;
 	}
 
 	/**
 	 * Returns true if item was loaded successfully by Load method
 	 *
 	 * @return bool
 	 */
 	function isLoaded()
 	{
 		return $this->Loaded;
 	}
 
 	/**
 	 * Checks if field is required
 	 *
 	 * @param string $field
 	 * @return bool
 	 */
 	function isRequired($field)
 	{
 		return getArrayValue( $this->Fields[$field], 'required' );
 	}
 
 	/**
 	 * Sets new required flag to field
 	 *
 	 * @param string $field
 	 * @param bool $is_required
 	 */
 	function setRequired($field, $is_required = true)
 	{
 		$this->Fields[$field]['required'] = $is_required;
 	}
 
 	function Clear($new_id = null)
 	{
 		$this->Loaded = false;
 		$this->FieldValues = Array();
 		$this->OriginalFieldValues = Array ();
 		$this->SetDefaultValues(); // will wear off kDBItem::setID effect, so set it later
 		$this->FieldErrors = Array();
 
 		$this->setID($new_id);
 
 		return $this->Loaded;
 	}
 
 	function Query($force = false)
 	{
 		if ($this->Application->isDebugMode()) {
 			$this->Application->Debugger->appendTrace();
 		}
 
 		trigger_error('<b>Query</b> method is called in class <b>'.get_class($this).'</b> for prefix <b>'.$this->getPrefixSpecial().'</b>', E_USER_ERROR);
 	}
 
 	function saveCustomFields()
 	{
 		if (!$this->customFields || $this->inCloning) {
 			return true;
 		}
 
-		$cdata_key = rtrim($this->Prefix.'-cdata.'.$this->Special, '.');
-		$cdata =& $this->Application->recallObject($cdata_key, null, Array('skip_autoload' => true, 'populate_ml_fields' => true));
+		$cdata_key = rtrim($this->Prefix . '-cdata.' . $this->Special, '.');
+
+		$cdata =& $this->Application->recallObject($cdata_key, null, Array('skip_autoload' => true));
+		/* @var $cdata kDBItem */
 
 		$resource_id = $this->GetDBField('ResourceId');
 		$cdata->Load($resource_id, 'ResourceId');
 		$cdata->SetDBField('ResourceId', $resource_id);
 
 		$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
 		/* @var $ml_formatter kMultiLanguage */
 
+		$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
+		/* @var $ml_helper kMultiLanguageHelper */
+
 		foreach ($this->customFields as $custom_id => $custom_name) {
-			$force_primary = isset($cdata->Fields['cust_'.$custom_id]['force_primary']) && $cdata->Fields['cust_'.$custom_id]['force_primary'];
-			$cdata->SetDBField($ml_formatter->LangFieldName('cust_'.$custom_id, $force_primary), $this->GetDBField('cust_'.$custom_name));
+			$field_options = $cdata->GetFieldOptions('cust_' . $custom_id);
+			$force_primary = isset($field_options['force_primary']) && $field_options['force_primary'];
+
+			if ($force_primary) {
+				$cdata->SetDBField($ml_formatter->LangFieldName('cust_' . $custom_id, true), $this->GetDBField('cust_' . $custom_name));
+			}
+			else {
+				for ($language_id = 1; $language_id <= $ml_helper->languageCount; $language_id++) {
+					if (!$ml_helper->LanguageFound($language_id)) {
+						continue;
+					}
+
+					$cdata->SetDBField('l' . $language_id . '_cust_' . $custom_id, $this->GetDBField('l' . $language_id . '_cust_' . $custom_name));
+				}
+			}
 		}
 
 		return $cdata->isLoaded() ? $cdata->Update() : $cdata->Create();
 	}
 
 	/**
 	 * Returns specified field value from all selected rows.
 	 * Don't affect current record index
 	 *
 	 * @param string $field
 	 * @param bool $formatted
 	 * @param string $format
 	 * @return Array
 	 */
 	function GetCol($field, $formatted = false, $format = null)
 	{
 		if ($formatted) {
 			return Array (0 => $this->GetField($field, $format));
 		}
 
 		return Array (0 => $this->GetDBField($field));
 	}
 
 }
\ No newline at end of file
Index: branches/5.1.x/core/units/custom_fields/custom_fields_tag_processor.php
===================================================================
--- branches/5.1.x/core/units/custom_fields/custom_fields_tag_processor.php	(revision 14407)
+++ branches/5.1.x/core/units/custom_fields/custom_fields_tag_processor.php	(revision 14408)
@@ -1,154 +1,165 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class CustomFieldsTagProcessor extends kDBTagProcessor {
 
 		/**
 		 * Return LEFT JOINed custom field name from main item config
 		 *
 		 * @param Array $params
 		 * @return string
 		 */
 		function GetMainField($params)
 		{
 			$object =& $this->getObject($params);
 			$append = isset($params['append']) && $params['append'] ? $params['append'] : '';
 			return 'cust_'.$object->GetDBField('FieldName').$append;
 		}
 
 		function CustomField($params)
 		{
 			$params['name'] = $this->GetMainField($params);
 			$source_prefix = $this->Application->Parser->GetParam('SourcePrefix');
 			return $this->Application->ProcessParsedTag($source_prefix, 'Field', $params);
 		}
 
 		function CustomFormat($params)
 		{
 			$params['name'] = $this->GetMainField($params);
 			$source_prefix = $this->Application->Parser->GetParam('SourcePrefix');
 			return $this->Application->ProcessParsedTag($source_prefix, 'Format', $params);
 		}
 
 		function CustomInputName($params)
 		{
 			$params['name'] = $this->GetMainField($params);
 			$source_prefix = $this->Application->Parser->GetParam('SourcePrefix');
 			return $this->Application->ProcessParsedTag($source_prefix, 'InputName', $params);
 		}
 
 		function setParamValue(&$params, $param_name)
 		{
 			// $deep_level if GetParam = 1 used in case if PrintList is called during parsing "grid" block (=> +1 to deep_level)
 			if (!isset($params[$param_name])) {
 				$params[$param_name] = $this->Application->Parser->GetParam($param_name, 1);
 			}
 
 			return $params[$param_name];
 		}
 
 		/**
 		 * Prints list content using block specified
 		 *
 		 * @param Array $params
 		 * @return string
 		 * @access public
 		 */
 		function PrintList($params)
 		{
 			$this->setParamValue($params, 'SourcePrefix');
 			$this->setParamValue($params, 'value_field');
 
 			$list =& $this->GetList($params);
 			$id_field = $this->Application->getUnitOption($this->Prefix,'IDField');
 
 			$list->Query();
 			$o = '';
 			$list->GoFirst();
 
 			$block_params = $this->prepareTagParams($params);
 			$block_params['name'] = $this->SelectParam($params, 'render_as,block');
 			$block_params['pass_params'] = 'true';
 
 			$prev_heading = '';
 			$display_original = false;
 			$source_prefix = getArrayValue($params, 'SourcePrefix');
 			if ($source_prefix) {
 				$source_object =& $this->Application->recallObject($source_prefix, null, Array ('raise_warnings' => 0)); // it's possible, that in some cases object will not be loaded
 				/* @var $source_object kCatDBItem */
 
 				$display_original = $this->Application->ProcessParsedTag($source_prefix, 'DisplayOriginal', Array('display_original' => $this->setParamValue($params, 'display_original')));
 			}
 
 			if ($display_original) {
 				$block_params['display_original'] = $display_original;
 				$block_params['original_title'] = $this->setParamValue($params, 'original_title');
 				$original_object =& $this->Application->recallObject($source_prefix.'.original', null, Array ('raise_warnings' => 0)); // it's possible, that in some cases object will not be loaded
 			}
 
 			if ($this->Special == 'general') {
 				$this->groupRecords($list->Records, 'Heading');
 			}
 
 			$i = 0;
 			while (!$list->EOL())
 			{
 				$block_params['is_last'] = ($i == $list->SelectedCount - 1);
 				$block_params['not_last'] = !$block_params['is_last']; // for front-end
 
 				$this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET
 
 				if ($source_prefix) {
-					$list->SetDBField($params['value_field'], $source_object->GetDBField('cust_'.$list->GetDBField('FieldName')));
+					$options = $source_object->GetFieldOptions('cust_'.$list->GetDBField('FieldName'));
+
+					if ( isset($options['formatter']) && $options['formatter'] == 'kMultiLanguage' ) {
+						$language_prefix = 'l' . $this->Application->GetVar('m_lang') . '_';
+					}
+					else {
+						$language_prefix = '';
+					}
+
+					$list->SetDBField($params['value_field'], $source_object->GetDBField($language_prefix . 'cust_'.$list->GetDBField('FieldName')));
+
 					if ($display_original) {
 						$list->SetDBField('OriginalValue', $original_object->GetField('cust_'.$list->GetDBField('FieldName')));
 					}
+
 					$block_params['field'] = $block_params['virtual_field'] = 'cust_'.$list->GetDBField('FieldName');
 					$block_params['show_heading'] = ($prev_heading != $list->GetDBField('Heading') ) ? 1 : 0;
 
-					$options = $source_object->GetFieldOptions('cust_'.$list->GetDBField('FieldName'));
+
 					$list->SetDBField('DirectOptions', isset($options['options']) ? $options['options'] : false);
 				}
 
 				$o.= $this->Application->ParseBlock($block_params);
 				$prev_heading = $list->GetDBField('Heading');
 				$list->GoNext();
 				$i++;
 			}
 
 			$this->Application->SetVar( $this->getPrefixSpecial().'_id', '');
 			return $o;
 		}
 
 		/**
 		 * If data was modfied & is in TempTables mode, then parse block with name passed;
 		 * remove modification mark if not in TempTables mode
 		 *
 		 * @param Array $params
 		 * @return string
 		 * @access public
 		 * @author Alexey
 		 */
 		function SaveWarning($params)
 		{
 			$source_prefix = array_key_exists('SourcePrefix', $params) ? $params['SourcePrefix'] : false;
 			if ($source_prefix && $source_prefix == 'c') {
 				return $this->Application->ProcessParsedTag('c', 'SaveWarning', $params);
 			}
 
 			return parent::SaveWarning($params);
 		}
 	}
\ No newline at end of file
Index: branches/5.1.x/core/units/custom_fields/custom_fields_config.php
===================================================================
--- branches/5.1.x/core/units/custom_fields/custom_fields_config.php	(revision 14407)
+++ branches/5.1.x/core/units/custom_fields/custom_fields_config.php	(revision 14408)
@@ -1,189 +1,162 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 defined('FULL_PATH') or die('restricted access!');
 
 	$config =	Array(
 					'Prefix'			=>	'cf',
 					'ItemClass'			=>	Array('class'=>'kDBItem','file'=>'','build_event'=>'OnItemBuild'),
 					'ListClass'			=>	Array('class'=>'kDBList','file'=>'','build_event'=>'OnListBuild'),
 					'EventHandlerClass'	=>	Array('class'=>'CustomFieldsEventHandler','file'=>'custom_fields_event_handler.php','build_event'=>'OnBuild'),
 					'TagProcessorClass' =>	Array('class'=>'CustomFieldsTagProcessor','file'=>'custom_fields_tag_processor.php','build_event'=>'OnBuild'),
 					'AutoLoad'			=>	true,
 					'hooks'				=>	Array(),
 					'QueryString'		=>	Array(
 												1	=>	'id',
 												2	=>	'Page',
 												3	=>	'PerPage',
 												4	=>	'event',
 												5	=>	'type',
 												6	=>	'mode',
 											),
 
 					'Hooks'				=>	Array(
 													Array(
 														'Mode' => hAFTER,
 														'Conditional' => false,
 														'HookToPrefix' => 'cf',
 														'HookToSpecial' => '*',
 														'HookToEvent' => Array('OnSave'),	// edit cloned fields to made alters :)
 														'DoPrefix' => 'cf',
 														'DoSpecial' => '*',
 														'DoEvent' => 'OnSaveCustomField',
 													),
 											),
 
 					'IDField'			=>	'CustomFieldId',
 					'OrderField'		=>	'DisplayOrder',
 
 					'TitleField'		=>	'FieldName',		// field, used in bluebar when editing existing item
 
 					'TitlePhrase'		=> 'la_title_CustomFields',
 
 					'TitlePresets'		=>	Array(
 												'default'	=>	Array(	'new_status_labels'		=> Array('cf'=>'!la_title_addingCustom!'),
 																		'edit_status_labels'	=> Array('cf'=>'!la_title_Editing_CustomField!'),
 																		'new_titlefield'		=> Array('cf'=>''),
 																),
 
 												'custom_fields_list'=>Array(	'prefixes'				=> Array('cf_List'),
 																		'format'				=>	"!la_tab_ConfigCustom!",
 																),
 
 												'custom_fields_edit'=>Array(	'prefixes'				=> Array('cf'),
 																		'new_titlefield'		=> Array('cf'=>''),
 																		'format'				=> "#cf_status# '#cf_titlefield#'",
 																),
 											),
 
 					'TableName'			=>	TABLE_PREFIX.'CustomField',
 
 					'ListSQLs'			=>	Array(	''=>'SELECT * FROM %s',
 																		), // key - special, value - list select sql
 
 					'ListSortings'	=> 	Array(
 												''			=>	Array(
 																		'ForcedSorting' => Array('DisplayOrder' => 'asc'),
 																		'Sorting' => Array('FieldName' => 'asc'),
 																),
 
 												'general'	=>	Array(
 																	'Sorting' => Array('DisplayOrder' => 'asc')
 																),
 
 										),
 
 					'ItemSQLs'			=>	Array(	''=>'SELECT * FROM %s',
 																		),
 					'SubItems'			=>	Array('confs-cf'),
 
 					'Fields'			=>	Array (
 										            'CustomFieldId' => Array('type' => 'int', 'not_null' => 1, 'default' => 0),
 										            'Type' => Array('type' => 'int', 'not_null' => 1, 'default' => 0),
 										            'FieldName' => Array('required'=>'1', 'type' => 'string','not_null' => 1,'default' => ''),
 										            'FieldLabel' => Array('type' => 'string', 'required' => 1, 'default' => null),
 										            'MultiLingual' => Array (
 														'type' => 'int',
 														'formatter' => 'kOptionsFormatter',
 														'options' => Array (0 => 'la_No', 1 => 'la_Yes'), 'use_phrases' => 1,
 														'not_null' => 1, 'default' => 1,
 													),
 										            'Heading' => Array('type' => 'string', 'required' => 1, 'default' => null),
 										            'Prompt' => Array('type' => 'string','default' => null),
 										            'ElementType' => Array('required'=>'1', 'type'=>'string', 'not_null'=>1, 'default'=>'', 'formatter'=>'kOptionsFormatter', 'use_phrases' => 1, 'options'=>Array('text' => 'la_type_text', 'select' => 'la_type_select', 'multiselect' => 'la_type_multiselect', 'radio' => 'la_type_radio', 'checkbox' => 'la_type_checkbox', 'password' => 'la_type_password', 'textarea' => 'la_type_textarea', 'label' => 'la_type_label', 'date' => 'la_type_date', 'datetime' => 'la_type_datetime')),
 										            'ValueList' => Array('type' => 'string','default' => null),
 										            'DefaultValue' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''),
 										            'DisplayOrder' => Array('type' => 'int', 'not_null' => 1, 'default' => 0),
 										            'OnGeneralTab' => Array (
 														'type' => 'int',
 														'formatter' => 'kOptionsFormatter',
 														'options' => Array (0 => 'la_No', 1 => 'la_Yes'), 'use_phrases' => 1,
 														'not_null' => 1, 'default' => 0,
 													),
 										            'IsSystem' => Array (
 														'type' => 'int',
 														'formatter' => 'kOptionsFormatter',
 														'options' => Array (0 => 'la_No', 1 => 'la_Yes'), 'use_phrases' => 1,
 														'not_null' => 1, 'default' => 0,
 													),
 										            'IsRequired' => Array (
 														'type' => 'int',
 														'formatter' => 'kOptionsFormatter',
 														'options' => Array (0 => 'la_No', 1 => 'la_Yes'), 'use_phrases' => 1,
 														'not_null' => 1, 'default' => 0,
 													),
 					),
 
 					'VirtualFields'	=> 	Array(
 													'Value'			=>	Array('type' => 'string', 'default' => ''),
 													'OriginalValue'	=>	Array('type' => 'string', 'default' => ''),
 													'Error'			=>	Array('type' => 'string', 'default' => ''),
 													'DirectOptions' =>	Array('type' => 'string', 'default' => ''),
 
 													'SortValues'	=>	Array (
 														'type' => 'int',
 														'formatter' => 'kOptionsFormatter',
 														'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
 														'default' => 0,
 													),
 
 													// for ValueList field editing via "inp_edit_minput" control
 													'OptionKey' => Array ('type' => 'string', 'default' => ''),
 													'OptionTitle' => Array ('type' => 'string', 'default' => ''),
 													'Options' => Array ('type' => 'string', 'default' => ''),
 
 										),
 
 					'Grids'	=> Array(
 										'Default' => Array (
 											'Icons' => Array (
 												'default' => 'icon16_item.png',
 											),
 											'Fields' => Array (
 												'CustomFieldId' => Array ( 'title'=>'la_col_Id', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_range_filter', 'width' => 70, ),
 												'FieldName' => Array ( 'title'=>'la_prompt_FieldName', 'width' => 250, ),
 												'FieldLabel' => Array ( 'title'=>'la_prompt_FieldLabel', 'data_block' => 'cf_grid_data_td', 'width' => 250, ),
 												'DisplayOrder' => Array ('title' => 'la_prompt_DisplayOrder', 'filter_block' => 'grid_range_filter', 'width' => 105, ),
 //												'IsSystem' => Array ('title' => 'la_col_IsSystem', 'filter_block' => 'grid_options_filter'),
 											),
 										),
-
-										'SeparateTab' => Array (
-											'Icons' => Array (
-												'default' => 'icon16_item.png',
-											),
-											'Selector' => '',
-											'Fields' => Array (
-												'FieldName' => Array ( 'title'=>'la_col_FieldName', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_like_filter', 'width' => 200, ),
-												'Prompt' => Array ( 'title'=>'la_col_Prompt', 'data_block' => 'grid_data_label_ml_td', 'ElementTypeField' => 'ElementType', 'filter_block' => 'grid_empty_filter', 'width' => 200, ),
-												'Value' => Array ( 'title'=>'la_col_Value', 'data_block' => 'edit_custom_td', 'filter_block' => 'grid_empty_filter', 'width' => 200, ),
-												'Error' => Array ( 'title'=>'la_col_Error', 'data_block' => 'custom_error_td', 'filter_block' => 'grid_empty_filter', 'width' => 100, ),
-											),
-										),
-
-										'SeparateTabOriginal' => Array (
-											'Icons' => Array (
-												'default' => 'icon16_item.png',
-											),
-											'Selector' => '',
-											'Fields' => Array (
-												'FieldName' => Array ( 'title'=>'la_col_FieldName', 'data_block' => 'grid_icon_td', 'filter_block' => 'grid_like_filter'),
-												'Prompt' =>	Array ( 'title'=>'la_col_Prompt', 'data_block' => 'grid_data_label_ml_td', 'ElementTypeField' => 'ElementType', 'filter_block' => 'grid_empty_filter'),
-												'Value' => Array ( 'title'=>'la_col_Value', 'data_block' => 'edit_custom_td', 'filter_block' => 'grid_empty_filter'),
-												'OriginalValue'	=> Array ( 'title'=>'la_col_OriginalValue', 'data_block' => 'grid_original_td', 'filter_block' => 'grid_like_filter'),
-											),
-										),
-
 								),
 	);
\ No newline at end of file
Index: branches/5.1.x/core/units/custom_data/custom_data_event_handler.php
===================================================================
--- branches/5.1.x/core/units/custom_data/custom_data_event_handler.php	(revision 14407)
+++ branches/5.1.x/core/units/custom_data/custom_data_event_handler.php	(revision 14408)
@@ -1,219 +1,218 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class CustomDataEventHandler extends kDBEventHandler {
 
 		/**
 		 * [HOOK] Allows to apply custom fields functionality to specific config
 		 * When main item is created, then cdata config is cloned
 		 *
 		 * @param kEvent $event
 		 */
 		function OnDefineCustomFields(&$event)
 		{
 			// 1. clone customdata table
 			$clones = $this->Application->getUnitOption('cdata', 'Clones');
 			$clones[$event->MasterEvent->Prefix.'-cdata'] = Array (
 				'ParentPrefix' => $event->MasterEvent->Prefix,
 				'TableName' => $this->Application->getUnitOption($event->MasterEvent->Prefix, 'TableName').'CustomData',
 			);
 			$this->Application->setUnitOption('cdata', 'Clones', $clones);
 
 			// 2. add custom field information to main item
 			$this->createCustomFields($event->MasterEvent->Prefix);
 		}
 
 		function scanCustomFields($prefix)
 		{
 			static $custom_fields = Array ();
 
 			if (defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound('CustomField')) {
 				return false;
 			}
 
 			if (!$prefix) {
 				// prefix not specified
 				return false;
 			}
 
 			$item_type = $this->Application->getUnitOption($prefix, 'ItemType');
 			if (!$item_type) {
 				// no main config of such type
 				return false;
 			}
 
 			$no_caching = (defined('IS_INSTALL') && IS_INSTALL) || (defined('CUSTOM_FIELD_ADDED') && CUSTOM_FIELD_ADDED);
 
 			if (!$custom_fields || $no_caching) {
 				// query all custom fields at once -> saves 4 sqls queries
 
 				if ($no_caching) {
 					$all_custom_fields = $this->getCustomFields();
 				}
 				else {
 					$cache_key = 'all_custom_fields[%CfSerial%][%ModSerial%]';
 					$all_custom_fields = $this->Application->getCache($cache_key, false);
 
 					if ($all_custom_fields === false) {
 						$this->Conn->nextQueryCachable = true;
 						$all_custom_fields = $this->getCustomFields();
 						$this->Application->setCache($cache_key, $all_custom_fields);
 					}
 				}
 
 				foreach ($all_custom_fields as $custom_field_id => $custom_field_data) {
 					$cf_type = $custom_field_data['Type'];
 					if (!array_key_exists($cf_type, $custom_fields)) {
 						$custom_fields[$cf_type] = Array ();
 					}
 
 					$custom_fields[$cf_type][$custom_field_id] = $custom_field_data;
 				}
 			}
 
 			return array_key_exists($item_type, $custom_fields) ? $custom_fields[$item_type] : false;
 		}
 
 		/**
 		 * Returns sorted list of all custom fields
 		 *
 		 * @return Array
 		 */
 		function getCustomFields()
 		{
 			$sql = 'SELECT *
 					FROM '.TABLE_PREFIX.'CustomField';
 			$ret = $this->Conn->Query($sql, 'CustomFieldId');
 
 			ksort($ret);
 
 			return $ret;
 		}
 
 		/**
 		 * Fills cloned cdata config with data from it's parent
 		 *
 		 * @param kEvent $event
 		 */
 		function OnAfterConfigRead(&$event)
 		{
 			$main_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
 			if (!$main_prefix) {
 				return false;
 			}
 
 			$custom_fields = $this->scanCustomFields($main_prefix);
 			if (!$custom_fields) {
 				return false;
 			}
 
 			// 2. create fields (for customdata item)
 			$fields = $this->Application->getUnitOption($event->Prefix, 'Fields', Array());
 			$field_options = Array('type' => 'string', 'formatter' => 'kMultiLanguage', 'db_type' => 'text', 'default' => '');
 			foreach ($custom_fields as $custom_id => $custom_params) {
 				if (isset($fields['cust_'.$custom_id])) continue;
 				$fields['cust_'.$custom_id] = $field_options;
 				$fields['cust_'.$custom_id]['force_primary'] = !$custom_params['MultiLingual'];
 			}
 			$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
 		}
 
 		/**
 		 * Creates "cust_<custom_name>" virtual fields for main item
 		 *
 		 * @param string $prefix
 		 */
 		function createCustomFields($prefix)
 		{
 			$custom_fields = $this->scanCustomFields($prefix);
 			if (!$custom_fields) {
 				return false;
 			}
 
 			$calculated_fields = Array();
 			$virtual_fields = $this->Application->getUnitOption($prefix, 'VirtualFields', Array());
 
 			$cf_helper =& $this->Application->recallObject('InpCustomFieldsHelper');
-			$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
-			/* @var $ml_formatter kMultiLanguage */
+			/* @var $cf_helper InpCustomFieldsHelper */
 
 			$is_install = defined('IS_INSTALL') && IS_INSTALL;
 
 			foreach ($custom_fields as $custom_id => $custom_params) {
 				$custom_name = $custom_params['FieldName'];
 				$field_options = Array('type' => 'string', 'default' => $custom_params['DefaultValue']);
 
 				// raises warnings during 4.3.9 -> 5.0.0 upgrade, no fatal sqls though
-				if ($custom_params['IsRequired']) {
+				if ( $custom_params['IsRequired'] ) {
 					$field_options['required'] = 1;
 				}
 
+				$calculated_fields['cust_' . $custom_name] = 'cust.l' . $this->Application->GetDefaultLanguageId() .'_cust_' . $custom_id;
+
 				switch ($custom_params['ElementType']) {
 					case 'date':
 						unset($field_options['options']);
 						$field_options['formatter'] = 'kDateFormatter';
 						$field_options['input_time_format'] = '';
 						$field_options['time_format'] = '';
 						break;
 
 					case 'datetime':
 						unset($field_options['options']);
 						$field_options['formatter'] = 'kDateFormatter';
 						break;
 
 					case 'select':
 					case 'multiselect':
 					case 'radio':
 						if ($custom_params['ValueList']) {
 							// $is_install check prevents 335 bad phrase sql errors on upgrade to 5.1.0
 							$field_options['options'] = $is_install ? Array () : $cf_helper->GetValuesHash($custom_params['ValueList']);
 							$field_options['formatter'] = 'kOptionsFormatter';
 							$field_options['multiple'] = $custom_params['ElementType'] == 'multiselect';
 						}
 						break;
 
 					default:
 						if ($custom_params['MultiLingual']) {
-							$calculated_fields['cust_'.$custom_name.'_Primary'] = 'cust.'.$ml_formatter->LangFieldName('cust_'.$custom_id, true);
-							$virtual_fields['cust_'.$custom_name.'_Primary'] = $field_options;
-							$field_options['master_field'] = 'cust_'.$custom_name.'_Primary';
-							$field_options['formatter'] = 'kCustomFieldFormatter';
+							$field_options['formatter'] = 'kMultiLanguage';
+							$calculated_fields['cust_' . $custom_name] = 'cust.l%2$s_cust_' . $custom_id;
 						}
 						break;
 				}
 
-				$calculated_fields['cust_'.$custom_name] = 'cust.'.$ml_formatter->LangFieldName('cust_'.$custom_id, !$custom_params['MultiLingual']);
-				if (!isset($virtual_fields['cust_'.$custom_name])) {
-					$virtual_fields['cust_'.$custom_name] = Array();
+				if ( !isset($virtual_fields['cust_' . $custom_name]) ) {
+					$virtual_fields['cust_' . $custom_name] = Array ();
 				}
-				$virtual_fields['cust_'.$custom_name] = array_merge_recursive2($field_options, $virtual_fields['cust_'.$custom_name]);
+
+				$virtual_fields['cust_' . $custom_name] = array_merge_recursive2($field_options, $virtual_fields['cust_' . $custom_name]);
 				$custom_fields[$custom_id] = $custom_name;
 			}
 
 			$config_calculated_fields = $this->Application->getUnitOption($prefix, 'CalculatedFields', Array());
 			foreach ($config_calculated_fields as $special => $special_fields) {
 				if ($special == '-virtual') {
 					continue;
 				}
 
 				$config_calculated_fields[$special] = array_merge_recursive2($config_calculated_fields[$special], $calculated_fields);
 			}
 			$this->Application->setUnitOption($prefix, 'CalculatedFields', $config_calculated_fields);
 
 			$this->Application->setUnitOption($prefix, 'CustomFields', $custom_fields);
 			$this->Application->setUnitOption($prefix, 'VirtualFields', $virtual_fields);
 		}
 	}
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/categories/categories_edit_custom.tpl
===================================================================
--- branches/5.1.x/core/admin_templates/categories/categories_edit_custom.tpl	(revision 14407)
+++ branches/5.1.x/core/admin_templates/categories/categories_edit_custom.tpl	(revision 14408)
@@ -1,73 +1,73 @@
 <inp2:adm_SetPopupSize width="880" height="680"/>
 
 <inp2:m_include t="incs/header"/>
 <inp2:m_include t="categories/categories_tabs"/>
 
-<inp2:m_RenderElement name="combined_header" prefix="c" section="in-portal:browse" title_preset="categories_custom" grid="SeparateTab" tab_preset="Default"/>
+<inp2:m_RenderElement name="combined_header" prefix="c" section="in-portal:browse" title_preset="categories_custom" tab_preset="Default"/>
 
 <!-- ToolBar -->
 <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
 <tbody>
 	<tr>
   	<td>
   		<script type="text/javascript">
 				a_toolbar = new ToolBar();
 				a_toolbar.AddButton( new ToolBarButton('select', '<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>', function() {
 							submit_event('c','<inp2:c_SaveEvent/>');
 						}
 					) );
 				a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() {
 							submit_event('c','OnCancelEdit');
 						}
 				 ) );
 
 				a_toolbar.AddButton( new ToolBarSeparator('sep1') );
 
 				a_toolbar.AddButton( new ToolBarButton('prev', '<inp2:m_phrase label="la_ToolTip_Prev" escape="1"/>', function() {
 							go_to_id('c', '<inp2:c_PrevId/>');
 						}
 				 ) );
 				a_toolbar.AddButton( new ToolBarButton('next', '<inp2:m_phrase label="la_ToolTip_Next" escape="1"/>', function() {
 							go_to_id('c', '<inp2:c_NextId/>');
 						}
 				 ) );
 
 				function edit(){ }
 
 				a_toolbar.Render();
 
 				<inp2:m_if check="c_IsSingle">
 					a_toolbar.HideButton('prev');
 					a_toolbar.HideButton('next');
 					a_toolbar.HideButton('sep1');
 				<inp2:m_else/>
 					<inp2:m_if check="c_IsLast">
 						a_toolbar.DisableButton('next');
 					</inp2:m_if>
 					<inp2:m_if check="c_IsFirst">
 						a_toolbar.DisableButton('prev');
 					</inp2:m_if>
 				</inp2:m_if>
 			</script>
 		</td>
 
-		<inp2:m_RenderElement name="search_main_toolbar" prefix="cf" grid="SeparateTab"/>
+		<inp2:m_RenderElement name="ml_selector" prefix="c"/>
 	</tr>
 </tbody>
 </table>
 
+<inp2:c_SaveWarning name="grid_save_warning"/>
+<inp2:c_ErrorWarning name="form_error_warning"/>
+
 <inp2:m_include t="incs/custom_blocks"/>
-<inp2:m_RenderElement
-	name="grid"
-	PrefixSpecial="cf"
-	SourcePrefix="c"
-	value_field="Value"
-	IdField="CustomFieldId"
-	per_page="-1"
-	grid="SeparateTab"
-	header_block="grid_column_title_no_sorting"
-	no_init="no_init"
-	/>
+
+<div id="scroll_container">
+	<table class="edit-form">
+		<inp2:cf.all_PrintList render_as="cv_row_block" SourcePrefix="c" value_field="Value" per_page="-1" grid="Default" original_title="la_section_OriginalValues"/>
+
+		<inp2:m_RenderElement name="inp_edit_filler"/>
+	</table>
+</div>
 
 <input type="hidden" name="cf_type" value="<inp2:c_UnitOption name='ItemType'/>"/>
 <inp2:m_include t="incs/footer"/>
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/users/users_edit_custom.tpl
===================================================================
--- branches/5.1.x/core/admin_templates/users/users_edit_custom.tpl	(revision 14407)
+++ branches/5.1.x/core/admin_templates/users/users_edit_custom.tpl	(revision 14408)
@@ -1,71 +1,72 @@
 <inp2:adm_SetPopupSize width="720" height="500"/>
 
 <inp2:m_include t="incs/header"/>
 <inp2:m_RenderElement name="combined_header" section="in-portal:user_list" prefix="u" title_preset="user_edit_custom" tab_preset="Default"/>
 
 <!-- ToolBar -->
 <table class="toolbar" height="30" cellspacing="0" cellpadding="0" width="100%" border="0">
 <tbody>
 	<tr>
   	<td>
   		<script type="text/javascript">
 				a_toolbar = new ToolBar();
 				a_toolbar.AddButton( new ToolBarButton('select', '<inp2:m_phrase label="la_ToolTip_Save" escape="1"/>', function() {
 							submit_event('u','<inp2:u_SaveEvent/>');
 						}
 					) );
 				a_toolbar.AddButton( new ToolBarButton('cancel', '<inp2:m_phrase label="la_ToolTip_Cancel" escape="1"/>', function() {
 							submit_event('u','OnCancelEdit');
 						}
 				 ) );
 
 				a_toolbar.AddButton( new ToolBarSeparator('sep1') );
 
 				a_toolbar.AddButton( new ToolBarButton('prev', '<inp2:m_phrase label="la_ToolTip_Prev" escape="1"/>', function() {
 							go_to_id('u', '<inp2:u_PrevId/>');
 						}
 				 ) );
 				a_toolbar.AddButton( new ToolBarButton('next', '<inp2:m_phrase label="la_ToolTip_Next" escape="1"/>', function() {
 							go_to_id('u', '<inp2:u_NextId/>');
 						}
 				 ) );
 
 				function edit(){ }
 
 				a_toolbar.Render();
 
 				<inp2:m_if check="u_IsSingle">
 					a_toolbar.HideButton('prev');
 					a_toolbar.HideButton('next');
 					a_toolbar.HideButton('sep1');
 				<inp2:m_else/>
 					<inp2:m_if check="u_IsLast" >
 						a_toolbar.DisableButton('next');
 					</inp2:m_if>
 					<inp2:m_if check="u_IsFirst" >
 						a_toolbar.DisableButton('prev');
 					</inp2:m_if>
 				</inp2:m_if>
 			</script>
 		</td>
 
-		<inp2:m_if check="u_DisplayOriginal" display_original="1">
-			<inp2:m_RenderElement name="search_main_toolbar" prefix="cf" grid="SeparateTabOriginal"/>
-		<inp2:m_else/>
-			<inp2:m_RenderElement name="search_main_toolbar" prefix="cf" grid="SeparateTab"/>
-		</inp2:m_if>
+		<inp2:m_RenderElement name="ml_selector" prefix="u"/>
 	</tr>
 </tbody>
 </table>
 
+<inp2:u_SaveWarning name="grid_save_warning"/>
+<inp2:u_ErrorWarning name="form_error_warning"/>
+
 <inp2:m_include t="incs/custom_blocks"/>
 
-<inp2:m_if check="u_DisplayOriginal" display_original="1">
-	<inp2:m_RenderElement name="grid" PrefixSpecial="cf" IdField="CustomFieldId" SourcePrefix="u" value_field="Value" per_page="-1" grid="SeparateTabOriginal" header_block="grid_column_title_no_sorting" no_init="no_init" original_title="la_section_OriginalValues" display_original="1"/>
-<inp2:m_else/>
-	<inp2:m_RenderElement name="grid" PrefixSpecial="cf" IdField="CustomFieldId" SourcePrefix="u" value_field="Value" per_page="-1" grid="SeparateTab" header_block="grid_column_title_no_sorting" no_init="no_init"/>
-</inp2:m_if>
+<div id="scroll_container">
+	<table class="edit-form">
+		<inp2:cf.all_PrintList render_as="cv_row_block" SourcePrefix="u" value_field="Value" per_page="-1" grid="Default" original_title="la_section_OriginalValues"/>
+
+		<inp2:m_RenderElement name="inp_edit_filler"/>
+	</table>
+</div>
 
 <input type="hidden" name="cf_type" value="<inp2:u_UnitOption name='ItemType'/>"/>
 
 <inp2:m_include t="incs/footer"/>
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/incs/grid_blocks.tpl
===================================================================
--- branches/5.1.x/core/admin_templates/incs/grid_blocks.tpl	(revision 14407)
+++ branches/5.1.x/core/admin_templates/incs/grid_blocks.tpl	(revision 14408)
@@ -1,894 +1,875 @@
 <inp2:m_DefineElement name="current_page">
  <span class="current_page"><inp2:m_param name="page"/></span>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="page">
 	<a href="javascript:go_to_page('<inp2:m_param name="PrefixSpecial"/>', <inp2:m_param name="page"/>, <inp2:m_param name="ajax"/>)" class="nav_url"><inp2:m_param name="page"/></a>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="next_page">
 	<a href="javascript:go_to_page('<inp2:m_param name="PrefixSpecial"/>', <inp2:m_param name="page"/>, <inp2:m_param name="ajax"/>)" class="nav_url">&gt;</a>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="prev_page">
 	<a href="javascript:go_to_page('<inp2:m_param name="PrefixSpecial"/>', <inp2:m_param name="page"/>, <inp2:m_param name="ajax"/>)" class="nav_url">&lt;</a>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="next_page_split">
 	<a href="javascript:go_to_page('<inp2:m_param name="PrefixSpecial"/>', <inp2:m_param name="page"/>, <inp2:m_param name="ajax"/>)" class="nav_url">&gt;&gt;</a>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="prev_page_split">
 	<a href="javascript:go_to_page('<inp2:m_param name="PrefixSpecial"/>', <inp2:m_param name="page"/>, <inp2:m_param name="ajax"/>)" class="nav_url">&lt;&lt;</a>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_pagination_elem" main_special="" ajax="0">
 	<inp2:m_if check="GridInfo" type="needs_pagination" pass_params="1">
 		&nbsp;<inp2:m_phrase name="la_Page"/>:
 		<inp2:PrintPages active_block="current_page" split="10" inactive_block="page" prev_page_block="prev_page" next_page_block="next_page" prev_page_split_block="prev_page_split" next_page_split_block="next_page_split" main_special="$main_special" ajax="$ajax" grid="$grid"/>
 	</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_pagination" SearchPrefixSpecial="" ajax="0">
 <!--## Maybe not in use ##-->
 <table cellspacing="0" cellpadding="2" width="100%" border="0" class="pagination_bar">
 	<tbody>
 		<tr>
 	  	<td width="100%">
 		  	 <inp2:m_RenderElement name="grid_pagination_elem" pass_params="1"/>
 			</td>
 			<td>
 				<inp2:m_if check="m_ParamEquals" param="search" value="on">
 					<inp2:m_if check="m_ParamEquals" name="SearchPrefixSpecial" value="">
 						<inp2:m_RenderElement name="grid_search" grid="$grid" PrefixSpecial="$PrefixSpecial" ajax="$ajax"/>
 					<inp2:m_else />
 						<inp2:m_RenderElement name="grid_search" grid="$grid" PrefixSpecial="$SearchPrefixSpecial" ajax="$ajax"/>
 					</inp2:m_if>
 				</inp2:m_if>
 			</td>
 		</tr>
 	</tbody>
 </table>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="search_main_toolbar">
 	<td style="white-space: nowrap; text-align: right; width: 310px;" align="right">
 		<div style="float: right">
 			<table cellpadding="0" cellspacing="0">
 				<tr>
 					<td>
 						<input 	type="text"
 							id="<inp2:m_param name='prefix'/>_search_keyword"
 							class="filter <inp2:m_ifnot check='m_Recall' var='{$prefix}_search_keyword' equals_to=''>filter-active</inp2:m_ifnot>"
 							name="<inp2:m_param name='prefix'/>_search_keyword"
 							value="<inp2:m_recall var='{$prefix}_search_keyword' no_null='no_null' special='1'/>"
 							PrefixSpecial="<inp2:m_param name='prefix'/>"
 							Grid="<inp2:m_param name='grid'/>"
 							ajax="0" style="width:150px"/>
 					</td>
 					<td style="white-space: nowrap;">
 						<script type="text/javascript">
 							b_toolbar = new ToolBar();
 
 							b_toolbar.AddButton( new ToolBarButton('search', '<inp2:m_phrase label="la_ToolTip_Search" escape="1"/>',
 									function() {
 										search('<inp2:m_Param name="prefix"/>', '<inp2:m_Param name="grid"/>', 0);
 									} ) );
 
 							b_toolbar.AddButton( new ToolBarButton('search_reset_alt', '<inp2:m_phrase label="la_ToolTip_SearchReset" escape="1"/>',
 									function() {
 										search_reset('<inp2:m_Param name="prefix"/>', '<inp2:m_Param name="grid"/>', 0);
 									} ) );
 
 							b_toolbar.Render();
 						</script>
 					</td>
 				</tr>
 			</table>
 		</div>
 	</td>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_search" ajax="0">
 				<td align="right" class="search-cell">
 					<img src="<inp2:m_TemplatesBase/>/img/spacer.gif" width="250" height="1" alt=""/><br />
 					<table cellspacing="0" cellpadding="0">
 						<tr>
 							<td><inp2:m_phrase name="la_Search"/>:&nbsp;</td>
 							<td>
 								<input 	type="text"
 										id="<inp2:m_param name='PrefixSpecial'/>_search_keyword"
 										class="filter <inp2:m_ifnot check='m_Recall' var='{$PrefixSpecial}_search_keyword' equals_to=''>filter-active</inp2:m_ifnot>"
 										name="<inp2:m_param name='PrefixSpecial'/>_search_keyword"
 										value="<inp2:m_recall var='{$PrefixSpecial}_search_keyword' no_null='no_null' special='1'/>"
 										PrefixSpecial="<inp2:m_param name='PrefixSpecial'/>"
 										Grid="<inp2:m_param name='grid'/>"
 										ajax="<inp2:m_param name='ajax'/>"/>
 								<input type="text" style="display: none;"/>
 							</td>
 							<td style="white-space: nowrap;" id="search_buttons[<inp2:m_param name="PrefixSpecial"/>]">
 							</td>
 						</tr>
 					</table>
 
 					<inp2:m_if check="m_Param" name="ajax" equals_to="0">
 						<script type="text/javascript">
 							addLoadEvent(
 								function () {
 									<inp2:m_RenderElement name="grid_search_buttons" pass_params="true"/>
 								}
 							)
 						</script>
 					</inp2:m_if>
 				</td>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_search_buttons" PrefixSpecial="" grid="" ajax="1">
 	var $search_box = document.getElementById('<inp2:m_param name="PrefixSpecial"/>_search_keyword');
 	if ($search_box) {
 		//$search_box.onkeydown = search_keydown;
 		$( jq('#<inp2:m_param name="PrefixSpecial"/>_search_keyword') ).keydown(search_keydown);
 	}
 
 	var $search_buttons = document.getElementById('search_buttons[<inp2:m_param name="PrefixSpecial"/>]');
 	if ($search_buttons) {
 		Toolbars['<inp2:m_param name="PrefixSpecial"/>_search'] = new ToolBar('icon16_');
 		Toolbars['<inp2:m_param name="PrefixSpecial"/>_search'].IconSize = {w:22,h:22};
 		Toolbars['<inp2:m_param name="PrefixSpecial"/>_search'].UseLabels = false;
 		Toolbars['<inp2:m_param name="PrefixSpecial"/>_search'].AddButton(
 			new ToolBarButton(
 				'search',
 				'<inp2:m_phrase name="la_ToolTip_Search" escape="1"/>',
 				function() {
 					search('<inp2:m_param name="PrefixSpecial"/>','<inp2:m_param name="grid"/>', <inp2:m_param name="ajax"/>)
 				},
 				null,
 				'<inp2:m_param name="PrefixSpecial"/>'
 			)
 		);
 
 		Toolbars['<inp2:m_param name="PrefixSpecial"/>_search'].AddButton(
 			new ToolBarButton(
 				'search_reset',
 				'<inp2:m_phrase name="la_ToolTip_SearchReset" escape="1"/>',
 				function() {
 					search_reset('<inp2:m_param name="PrefixSpecial"/>','<inp2:m_param name="grid"/>', <inp2:m_param name="ajax"/>)
 				},
 				null,
 				'<inp2:m_param name="PrefixSpecial"/>'
 			)
 		);
 
 		Toolbars['<inp2:m_param name="PrefixSpecial"/>_search'].Render($search_buttons);
 	}
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_checkbox_td" format="">
 	<inp2:m_RenderElement name="grid_data_td" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_checkbox_td_no_icon" format="">
 	<inp2:m_RenderElement name="grid_data_td" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="label_grid_checkbox_td" format="">
 	<inp2:m_RenderElement name="grid_data_label_td" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_icon_td" format="">
 	<inp2:m_RenderElement name="grid_data_td" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_radio_td" format="">
 	<inp2:m_RenderElement name="grid_data_td" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_data_td" format="" no_special="1" nl2br="" first_chars="" td_style="">
 	<inp2:Field field="$field" first_chars="$first_chars" nl2br="$nl2br" grid="$grid" no_special="$no_special" format="$format"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_total_td">
 	<inp2:m_if check="FieldTotal" field="$field" function_only="1">
 		<inp2:FieldTotal field="$field"/>
 	<inp2:m_else/>
 		&nbsp;
 	</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_priority_td" format="" no_special="" nl2br="" first_chars="" td_style="" currency="">
 	<inp2:Field field="$field" first_chars="$first_chars" currency="$currency" nl2br="$nl2br" grid="$grid" no_special="$no_special" format="$format"/>
 	<inp2:m_ifnot check="Field" field="Priority" equals_to="0" db="db"><span class="priority"><sup><inp2:Field field="Priority"/></sup></span></inp2:m_ifnot>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_edit_td" format="" style="">
 	<input type="text" id="<inp2:{$PrefixSpecial}_InputName field="$field"/>" name="<inp2:{$PrefixSpecial}_InputName field="$field"/>" value="<inp2:{$PrefixSpecial}_field field="$field" grid="$grid" format="$format"/>" style="<inp2:m_Param name='style'/>"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_picker_td" nl2br="0" no_special="1" separator="&nbsp;">
 	<inp2:Field name="$field" format="$separator" nl2br="$nl2br" no_special="$no_special"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_options_td" format="">
 		<select name="<inp2:InputName field="$field"/>" id="<inp2:InputName field="$field"/>">
 			<inp2:m_if check="FieldOption" field="$field" option="use_phrases">
 				<inp2:PredefinedOptions field="$field" block="inp_option_phrase" selected="selected" has_empty="1" empty_value="0"/>
 			<inp2:m_else/>
 				<inp2:PredefinedOptions field="$field" block="inp_option_item" selected="selected" has_empty="1" empty_value="0"/>
 			</inp2:m_if>
 		</select>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_date_td" format="">
 		<input type="text" name="<inp2:InputName field="{$field}_date"/>" id="<inp2:InputName field="{$field}_date"/>" value="<inp2:Field field="{$field}_date" format="_regional_InputDateFormat"/>" size="<inp2:Format field="{$field}_date" input_format="1" edit_size="edit_size"/>" datepickerIcon="<inp2:m_ProjectBase/>core/admin_templates/img/calendar_icon.gif">&nbsp;
 		<img src="<inp2:m_TemplatesBase/>/img/calendar_icon.gif" id="cal_img_<inp2:InputName field="{$field}"/>" width="13" height="12"
 				     style="cursor: pointer; margin-right: 5px"
 				     title="Date selector"
 				/>
 		<span class="small">(<inp2:Format field="{$field}_date" input_format="1" human="true"/>)</span>
 		<script type="text/javascript">
 			Calendar.setup({
 		        inputField		:	"<inp2:InputName field="{$field}_date"/>",
 		        ifFormat		:	Calendar.phpDateFormat("<inp2:Format field="{$field}_date" input_format="1"/>"),
 		        button			:	"cal_img_<inp2:InputName field="{$field}"/>",
 		        align			:	"br",
 		        singleClick		:	true,
 		        showsTime		:	true,
 		        weekNumbers		:	false,
 		        firstDay		:	<inp2:m_GetConfig var="FirstDayOfWeek"/>,
 		        onUpdate	:	function(cal) {
 		        	runOnChange('<inp2:InputName field="{$field}_date"/>');
 		       	}
 			});
 		</script>
 		<input type="hidden" name="<inp2:InputName field="{$field}_time"/>" id="<inp2:InputName field="{$field}_time" input_format="1"/>" value="">
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_data_label_td">
 	<inp2:Field field="$field" grid="$grid" plus_or_as_label="1" no_special="no_special" format="$format"/>
 </inp2:m_DefineElement>
 
-<inp2:m_DefineElement name="grid_data_label_ml_td" format="">
-	<span class="<inp2:m_if check="{$SourcePrefix}_HasError" field="$virtual_field">error-cell</inp2:m_if>">
-		<inp2:{$PrefixSpecial}_Field field="$field" grid="$grid" as_label="1" no_special="no_special" format="$format"/>
-	</span><inp2:m_if check="{$SourcePrefix}_IsRequired" field="$virtual_field"><span class="field-required"> *</span></inp2:m_if>:<br />
-
-	<inp2:m_if check="FieldEquals" field="$ElementTypeField" value="textarea">
-		<inp2:m_if check="Field" name="MultiLingual" equals_to="1" db="db">
-			<a href="javascript:PreSaveAndOpenTranslatorCV('<inp2:m_param name="SourcePrefix"/>,<inp2:m_param name="SourcePrefix"/>-cdata', '<inp2:m_param name="SourcePrefix"/>-cdata:cust_<inp2:Field name="CustomFieldId"/>', 'popups/translator', <inp2:$SourcePrefix_Field field="ResourceId"/>, 1);" title="<inp2:m_Phrase label="la_Translate" escape="1"/>"><img src="img/icons/icon24_translate.png" style="cursor:hand;" width="24" height="24" border="0"></a>
-		<inp2:m_else/>
-			<inp2:Field name="FieldName" result_to_var="custom_field"/>
-			<a href="javascript:OpenEditor('&section=in-link:editlink_general', 'kernel_form', '<inp2:{$SourcePrefix}_InputName field="cust_{$custom_field}"/>');"><img src="img/icons/icon24_link_editor.gif" style="cursor: hand;" width="24" height="24" border="0"></a>
-		</inp2:m_if>
-	<inp2:m_else/>
-		<inp2:m_if check="Field" name="MultiLingual" equals_to="1" db="db">
-			<a href="javascript:PreSaveAndOpenTranslatorCV('<inp2:m_param name="SourcePrefix"/>,<inp2:m_param name="SourcePrefix"/>-cdata', '<inp2:m_param name="SourcePrefix"/>-cdata:cust_<inp2:Field name="CustomFieldId"/>', 'popups/translator', <inp2:$SourcePrefix_Field field="ResourceId"/>);" title="<inp2:m_Phrase label="la_Translate" escape="1"/>"><img src="img/icons/icon24_translate.png" style="cursor:hand;" width="24" height="24" border="0"></a>
-		</inp2:m_if>
-	</inp2:m_if>
-</inp2:m_DefineElement>
-
 <inp2:m_DefineElement name="grid_empty_filter">
 
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_column_filter">
 	<!--## this cheat makes sure, that columns without a filter are using like filter ##-->
 	<inp2:m_RenderElement name="grid_like_filter" pass_params="1"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_options_filter" use_phrases="0" filter_width="90%">
 		<select
 			class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='options' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 			name="<inp2:SearchInputName field="$filter_field" filter_type="options" grid="$grid"/>"
 			style="width: <inp2:m_Param name="filter_width"/>">
 
 			<inp2:m_if check="m_ParamEquals" name="use_phrases" value="1">
 				<inp2:PredefinedSearchOptions field="$filter_field" block="inp_option_phrase" selected="selected" has_empty="1" empty_value="" filter_type="options" grid="$grid"/>
 			<inp2:m_else/>
 				<inp2:PredefinedSearchOptions field="$filter_field" block="inp_option_item" selected="selected" has_empty="1" empty_value="" filter_type="options" grid="$grid"/>
 			</inp2:m_if>
 		</select>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_like_filter" filter_width="95%">
 		<input type="text"
 			class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='like' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 		  style="width: <inp2:m_Param name="filter_width"/>"
 			name="<inp2:SearchInputName field="$filter_field" filter_type="like" grid="$grid"/>"
 			value="<inp2:SearchField field="$filter_field" filter_type="like" grid="$grid"/>"
 			onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_user_like_filter" selector_template="user_selector" filter_width="95%">
 	<table class="range-filter">
 		<tr>
 			<td style="width: 100%">
 				<input type="text"
 					class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='like' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 	 				 style="width: <inp2:m_Param name="filter_width"/>"
 		name="<inp2:SearchInputName field="$filter_field" filter_type="like" grid="$grid"/>"
 		id="<inp2:SearchInputName field="$filter_field" filter_type="like" grid="$grid"/>"
 		value="<inp2:SearchField field="$filter_field" filter_type="like" grid="$grid"/>"
 		onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 			</td>
 			<td valign="middle">
 				<a href="javascript:openSelector('<inp2:m_param name="PrefixSpecial"/>', '<inp2:m_t t="$selector_template" pass="all,$PrefixSpecial" escape="1"/>', '<inp2:m_param name="filter_field"/>');">
 					<img src="img/icons/icon24_link_user.gif" style="cursor:hand;" width="24" height="24" border="0">
 				</a>
 			</td>
 		</tr>
 	</table>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_picker_filter" use_phrases="0" filter_width="90%">
 		<select
 			class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='picker' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 			name="<inp2:SearchInputName field="$filter_field" filter_type="picker" grid="$grid"/>"
 			style="width: <inp2:m_Param name="filter_width"/>">
 
 			<inp2:m_if check="m_ParamEquals" name="use_phrases" value="1">
 				<inp2:PredefinedSearchOptions field="$filter_field" block="inp_option_phrase" selected="selected" has_empty="1" empty_value="" filter_type="picker" grid="$grid"/>
 			<inp2:m_else/>
 				<inp2:PredefinedSearchOptions field="$filter_field" block="inp_option_item" selected="selected" has_empty="1" empty_value="" filter_type="picker" grid="$grid"/>
 			</inp2:m_if>
 		</select>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_like_combo_filter" filter_width="95%">
 		<input type="text"
 			autocomplete="off"
 			class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='like' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 		  style="width: <inp2:m_Param name="filter_width"/>"
 			name="<inp2:SearchInputName field="$filter_field" filter_type="like" grid="$grid"/>"
 			id="<inp2:SearchInputName field="$filter_field" filter_type="like" grid="$grid"/>"
 			value="<inp2:SearchField field="$filter_field" filter_type="like" grid="$grid"/>"
 			onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 		<script type="text/javascript">
 			new AJAXDropDown('<inp2:SearchInputName field="$filter_field" filter_type="like" grid="$grid"/>',
 				function(cur_value) {
 					return '<inp2:m_t no_amp="1" pass="m,{$PrefixSpecial}" field="$filter_field" {$PrefixSpecial}_event="OnSuggestValues" cur_value="#VALUE#"/>'.replace('#VALUE#', cur_value);
 				}
 			);
 		</script>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_equals_filter" filter_width="95%">
 		<input type="text"
 			 class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='equals' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 			 style="width: <inp2:m_Param name="filter_width"/>"
 			 name="<inp2:SearchInputName field="$filter_field" filter_type="equals" grid="$grid"/>"
 			 value="<inp2:SearchField field="$filter_field" filter_type="equals" grid="$grid"/>"
 			 onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_range_filter" filter_width="90%">
 		<table class="range-filter">
 			<tr>
 				<td style="width: 100%">
 					<input type="text"
 						class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='range' type='from' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 						name="<inp2:SearchInputName field="$filter_field" filter_type="range" type="from" grid="$grid"/>"
 						value="<inp2:SearchField field="$filter_field" filter_type="range" type="from" grid="$grid"/>"
 						style="width: <inp2:m_Param name="filter_width"/>;"
 						onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 				</td>
 				<td rowspan="2" valign="middle">
 					<img src="<inp2:m_TemplatesBase/>/img/expand_filter.gif" width="7" height="9" alt="" onclick="filter_toggle('<inp2:SearchInputName field='$filter_field' filter_type='range' type='to' grid='$grid'/>_row', '<inp2:m_Param name='PrefixSpecial'/>');"/>
 				</td>
 			</tr>
 			<tr class="to-range-filter<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> hidden-filter</inp2:m_ifnot>" id="<inp2:SearchInputName field='$filter_field' filter_type='range' type='to' grid='$grid'/>_row">
 				<td style="width: 100%;<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> display: none;</inp2:m_ifnot>">
 					<input type="text"
 						class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='range' type='to' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 						name="<inp2:SearchInputName field="$filter_field" filter_type="range" type="to" grid="$grid"/>"
 						value="<inp2:SearchField field="$filter_field" filter_type="range" type="to" grid="$grid"/>"
 						style="width: <inp2:m_Param name="filter_width"/>;"
 						onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 				</td>
 			</tr>
 		</table>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_float_range_filter" filter_width="90%">
 		<table class="range-filter">
 			<tr>
 				<td style="width: 100%">
 					<input type="text"
 						class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='float_range' type='from' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 						name="<inp2:SearchInputName field="$filter_field" filter_type="float_range" type="from" grid="$grid"/>"
 						value="<inp2:SearchField field="$filter_field" filter_type="float_range" type="from" grid="$grid"/>"
 						style="width: <inp2:m_Param name="filter_width"/>"
 						onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 				</td>
 				<td rowspan="2" valign="middle">
 					<img src="<inp2:m_TemplatesBase/>/img/expand_filter.gif" width="7" height="9" alt="" onclick="filter_toggle('<inp2:SearchInputName field='$filter_field' filter_type='range' type='to' grid='$grid'/>_row', '<inp2:m_Param name='PrefixSpecial'/>');"/>
 				</td>
 			</tr>
 			<tr class="to-range-filter<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> hidden-filter</inp2:m_ifnot>" id="<inp2:SearchInputName field='$filter_field' filter_type='float_range' type='to' grid='$grid'/>_row">
 				<td style="width: 100%;<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> display: none;</inp2:m_ifnot>">
 					<input type="text"
 						class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='float_range' type='to' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 						name="<inp2:SearchInputName field="$filter_field" filter_type="float_range" type="to" grid="$grid"/>"
 						value="<inp2:SearchField field="$filter_field" filter_type="float_range" type="to" grid="$grid"/>"
 						style="width: <inp2:m_Param name="filter_width"/>"
 						onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 				</td>
 			</tr>
 		</table>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_date_range_filter" calendar_format="" filter_width="80%">
 		<table class="range-filter">
 			<tr>
 				<td style="width: 100%">
 					<input type="text"
 						class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='date_range' type='from' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 						style="width: <inp2:m_Param name="filter_width"/>"
 						name="<inp2:SearchInputName field="$filter_field" filter_type="date_range" type="from" grid="$grid"/>"
 						id="<inp2:SearchInputName field="$filter_field" filter_type="date_range" type="from" grid="$grid"/>"
 						value="<inp2:SearchField field="$filter_field" filter_type="date_range" type="from" grid="$grid"/>"
 						onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 				</td>
 				<td>
 					<img src="<inp2:m_TemplatesBase/>/img/calendar_icon.gif" width="13" height="12" id="cal_img_<inp2:SearchInputName field="$filter_field" filter_type="date_range" type="from" grid="$grid"/>"
 					     style="cursor: pointer; margin-right: 5px"
 					     title="Date selector"
 					 />
 				</td>
 				<td rowspan="2" valign="middle">
 					<img src="<inp2:m_TemplatesBase/>/img/expand_filter.gif" width="7" height="9" alt="" onclick="filter_toggle('<inp2:SearchInputName field='$filter_field' filter_type='date_range' type='to' grid='$grid'/>_row', '<inp2:m_Param name='PrefixSpecial'/>');"/>
 				</td>
 			</tr>
 			<tr class="to-range-filter<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> hidden-filter</inp2:m_ifnot>" id="<inp2:SearchInputName field='$filter_field' filter_type='date_range' type='to' grid='$grid'/>_row">
 				<td style="width: 100%;<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> display: none;</inp2:m_ifnot>">
 					<input type="text"
 						class="filter <inp2:m_ifnot check='SearchField' field='$filter_field' filter_type='date_range' type='to' grid='$grid' equals_to=''>filter-active</inp2:m_ifnot>"
 						style="width: <inp2:m_Param name="filter_width"/>"
 						name="<inp2:SearchInputName field="$filter_field" filter_type="date_range" type="to" grid="$grid"/>"
 						id="<inp2:SearchInputName field="$filter_field" filter_type="date_range" type="to" grid="$grid"/>"
 						value="<inp2:SearchField field="$filter_field" filter_type="date_range" type="to" grid="$grid"/>"
 						onkeypress="search_keydown(event, '<inp2:m_Param name="PrefixSpecial"/>', '<inp2:m_Param name="grid"/>', '<inp2:m_Param name="ajax"/>')"/>
 				</td>
 				<td<inp2:m_ifnot check='RangeFiltersUsed' grid='$grid'> style="display: none;"</inp2:m_ifnot>>
 					<img src="<inp2:m_TemplatesBase/>/img/calendar_icon.gif" width="13" height="12" id="cal_img_<inp2:SearchInputName field="$filter_field" filter_type="date_range" type="to" grid="$grid"/>"
 					     style="cursor: pointer; margin-right: 5px"
 					     title="Date selector"
 					/>
 				</td>
 			</tr>
 		</table>
 		<script type="text/javascript">
 			var $format = "<inp2:m_if check='m_Param' name='calendar_format'><inp2:m_Param name='calendar_format'/><inp2:m_else/><inp2:Format field='{$sort_field}' input_format='1'/></inp2:m_if>";
 
 			Calendar.setup({
 		        inputField  : "<inp2:SearchInputName field='$filter_field' filter_type='date_range' type='from' grid='$grid'/>",
 		        ifFormat    : Calendar.phpDateFormat($format),
 		        button      : "cal_img_<inp2:SearchInputName field='$filter_field' filter_type='date_range' type='from' grid='$grid'/>",
 		        align       : 'br',
 		        singleClick : true,
 		        showsTime   : true,
 		        weekNumbers : false,
 		        firstDay    : <inp2:m_GetConfig var="FirstDayOfWeek"/>
 			});
 
 			Calendar.setup({
 		        inputField  : "<inp2:SearchInputName field='$filter_field' filter_type='date_range' type='to' grid='$grid'/>",
 		        ifFormat    : Calendar.phpDateFormat($format),
 		        button      : "cal_img_<inp2:SearchInputName field='$filter_field' filter_type='date_range' type='to' grid='$grid'/>",
 		        align       : 'br',
 		        singleClick : true,
 		        showsTime   : true,
 		        weekNumbers : false,
 		        firstDay    : <inp2:m_GetConfig var="FirstDayOfWeek"/>
 			});
 		</script>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="viewmenu_sort_block">
 	$Menus['<inp2:m_param name="PrefixSpecial"/>'+'_sorting_menu'].addMenuItem('<inp2:m_phrase name="$title" js_escape="1"/>','direct_sort_grid("<inp2:m_param name="PrefixSpecial"/>","<inp2:m_param name="sort_field"/>","<inp2:{$PrefixSpecial}_OrderInfo type="direction" pos="1"/>", null, <inp2:m_param name="ajax"/>);','<inp2:m_if check="{$PrefixSpecial}_IsOrder" field="$sort_field" pos="1" >2</inp2:m_if>');
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="viewmenu_filter_block">
 	$Menus['<inp2:m_param name="PrefixSpecial"/>'+'_filter_menu'].addMenuItem('<inp2:m_param name="label" js_escape="1"/>','<inp2:m_param name="filter_action"/>','<inp2:m_param name="filter_status"/>');
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="viewmenu_filter_separator">
 	$Menus['<inp2:m_param name="PrefixSpecial"/>'+'_filter_menu'].addMenuSeparator();
 </inp2:m_DefineElement>
 
 <inp2:m_include template="incs/menu_blocks"/>
 
 <inp2:m_DefineElement name="grid_save_warning">
 	<inp2:m_RenderElement design="form_message" pass_params="1">
 		<inp2:m_phrase name="la_Warning_Save_Item"/>
     </inp2:m_RenderElement>
 
 	<script type="text/javascript">
 		$edit_mode = <inp2:m_if check="m_ParamEquals" name="edit_mode" value="1">true<inp2:m_else />false</inp2:m_if>;
 		if (Form) Form.Changed();
 //		window.parent.document.title += ' - MODE: ' + ($edit_mode ? 'EDIT' : 'LIVE');
 	</script>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_status" pagination="1">
 	<table class="grid-status-bar">
 		<tr>
 			<td nowrap="nowrap" style="vertical-align: middle;">
 				<inp2:m_Phrase label="la_Records"/>: <inp2:GridInfo type="filtered"/> (<inp2:GridInfo type="from"/> - <inp2:GridInfo type="to"/>) <inp2:m_Phrase label="la_OutOf"/> <inp2:GridInfo type="total"/>
 			</td>
 			<td align="right" class="tablenav" valign="middle">
 				<inp2:m_if check="m_Param" name="pagination">
 					<inp2:m_RenderElement name="grid_pagination_elem" pass_params="1"/>
 				</inp2:m_if>
 			</td>
 		</tr>
 	</table>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_column_title" use_phrases="1">
 	<table style="width: auto" class="layout-only-table"><tr>
 		<td style="vertical-align: middle; padding: 0px">
 			<a
 				href="javascript:resort_grid('<inp2:m_param name="PrefixSpecial"/>','<inp2:m_param name="sort_field"/>', <inp2:m_param name="ajax"/>);"
 				class="columntitle_small"
 				title="<inp2:m_Phrase name='la_col_SortBy' no_editing='1' html_escape='1'/> <inp2:m_if check='m_Param' name='use_phrases'><inp2:m_Phrase name='$title' no_editing='1' html_escape='1'/><inp2:m_else/><inp2:m_Param name='title'/></inp2:m_if>">
 					<img
 						alt="<inp2:m_Phrase name='la_col_SortBy' no_editing='1' html_escape='1'/> <inp2:m_if check='m_Param' name='use_phrases'><inp2:m_Phrase name='$title' no_editing='1' html_escape='1'/><inp2:m_else/><inp2:m_Param name='title'/></inp2:m_if>"
 						src="<inp2:m_TemplatesBase/>/img/list_arrow_<inp2:Order field='$sort_field'/>.gif" width="15" height="15" border="0" align="absmiddle"
 					/>
 			</a>
 		</td>
 		<td style="vertical-align: middle; text-align: left; padding: 1px; white-space: normal">
 			<a
 				href="javascript:resort_grid('<inp2:m_param name="PrefixSpecial"/>','<inp2:m_param name="sort_field"/>', <inp2:m_param name="ajax"/>);"
 				class="columntitle_small"
 				title="<inp2:m_Phrase name='la_col_SortBy' no_editing='1' html_escape='1'/> <inp2:m_if check='m_Param' name='use_phrases'><inp2:m_Phrase name='$title' no_editing='1' html_escape='1'/><inp2:m_else/><inp2:m_Param name='title'/></inp2:m_if>">
 				<inp2:m_if check="m_Param" name="use_phrases"><inp2:m_Phrase name="$title"/><inp2:m_else/><inp2:m_Param name="title"/></inp2:m_if>
 			</a>
 		</td>
 	</tr></table>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_selector_icon_html" selector="checkbox">
 	<div style="white-space: nowrap;">
 		<inp2:m_if check="m_Param" name="selector">
 			<input type="<inp2:m_Param name='selector'/>" name="<inp2:InputName field='$IdField' IdField='$IdField'/>" id="<inp2:InputName field='$IdField' IdField='$IdField'/>">
 		</inp2:m_if>
 		<inp2:ItemIcon name="module" grid="$grid" result_to_var="icon_module"/>
 		<img src="<inp2:ModulePath module='$icon_module'/>img/itemicons/<inp2:ItemIcon grid='$grid'/>" width="16" height="16" alt=""/>
 	</div>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_selector_html" selector="checkbox">
 	<inp2:m_if check="m_Param" name="selector">
 		<input type="<inp2:m_Param name='selector'/>" name="<inp2:InputName field='$IdField' IdField='$IdField'/>" id="<inp2:InputName field='$IdField' IdField='$IdField'/>">
 	</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_select_all_checkbox_html">
 	<input type="checkbox" onclick="Grids['<inp2:m_param name="PrefixSpecial"/>'].InvertSelection(); this.checked=false;" ondblclick="Grids['<inp2:m_param name="PrefixSpecial"/>'].ClearSelection(); this.checked=false;" />
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_column_title_no_sorting" use_phrases="1">
 	<inp2:m_if check="m_ParamEquals" name="use_phrases" value="1"><inp2:m_phrase name="$title"/><inp2:m_else/><inp2:m_param name="title"/></inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_js_block" format="" no_special="1" nl2br="" first_chars="" td_style="">
 	'<inp2:m_RenderElement name="$block_name" pass_params="1" js_escape="1"/>'<inp2:m_if check="m_Param" name="is_last" inverse="1">,</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_js_empty_filter_block" use_phrases="0">
 	'<inp2:m_RenderElement name="grid_empty_filter" pass_params="1" js_escape="1"/>'<inp2:m_if check="m_Param" name="is_last" inverse="1">,</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_js_filter_block" use_phrases="0">
 	'<inp2:m_RenderElement name="$filter_block" pass_params="1" js_escape="1"/>'<inp2:m_if check="m_Param" name="is_last" inverse="1">,</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_js_width_td" format="" width="" no_special="1" nl2br="" first_chars="" td_style="">
 	<inp2:m_Param name="width" js_escape="1"/><inp2:m_if check="m_Param" name="is_last" inverse="1">,</inp2:m_if>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid" main_prefix="" per_page="" main_special="" grid_filters="1"
 	 search="on"
 	 header_block="grid_column_title"
 	 filter_block="grid_column_filter"
 	 data_block="grid_data_td"
 	 total_block="grid_total_td"
 	 row_block="_row"
 	 ajax="0"
 	 totals="0"
 	 limited_heights="false"
 	 max_row_height="45"
 	 grid_height="auto"
 	 selector="checkbox"
 	 grid_status="1"
 	 totals_render_as=""
 	 >
 <!--##
 	grid_filters - show individual filters for each column
 	has_filters  - draw filter section in "View" menu in toolbar
 ##-->
 
 	<inp2:InitList pass_params="1"/> <!--## this is to avoid recalling prefix as an item in first iterate grid, by col-picker for instance ##-->
 
 	<inp2:{$PrefixSpecial}_SaveWarning name="grid_save_warning" pass_params="1"/>
 	<inp2:m_if check="{$PrefixSpecial}_SearchActive" grid="$grid">
 		<inp2:m_RenderElement design="form_message" pass_params="1">
 			<inp2:m_phrase name="la_Warning_Filter"/>
 		</inp2:m_RenderElement>
 	</inp2:m_if>
 
 	<div id="grid_<inp2:m_Param name='PrefixSpecial'/>_container"></div>
 
 	<inp2:m_if check="m_Param" name="grid_status">
 		<inp2:m_RenderElement name="grid_status" grid="$grid" PrefixSpecial="$PrefixSpecial" main_special="$main_special" search="$search" ajax="$ajax"/>
 	</inp2:m_if>
 
 	<inp2:m_if check="m_ParamEquals" name="ajax" value="0">
 		<inp2:m_if check="m_GetEquals" name="fw_menu_included" value="">
 			<link rel="stylesheet" rev="stylesheet" href="<inp2:m_Compress files='incs/nlsmenu.css'/>" type="text/css" />
 			<script type="text/javascript" src="<inp2:m_Compress files='js/nlsmenu.js|js/nlsmenueffect_1_2_1.js'/>"></script>
 
 			<script type="text/javascript">
 				var menuMgr = new NlsMenuManager("mgr");
 				menuMgr.timeout = 500;
 				menuMgr.flowOverFormElement = true;
 			</script>
 
 			<inp2:m_set fw_menu_included="1"/>
 		</inp2:m_if>
 
 		<script type="text/javascript">
 			<inp2:m_RenderElement name="grid_js" mouseover_class="grid-data-row-mouseover" selected_class="grid-data-row-selected:grid-data-row-even-selected" tag_name="tr" pass_params="true"/>
 		</script>
 	</inp2:m_if>
 
 	<input type="hidden" id="<inp2:m_param name="PrefixSpecial"/>_Sort1" name="<inp2:m_param name="PrefixSpecial"/>_Sort1" value="">
 	<input type="hidden" id="<inp2:m_param name="PrefixSpecial"/>_Sort1_Dir" name="<inp2:m_param name="PrefixSpecial"/>_Sort1_Dir" value="asc">
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="default_sorting_element" ajax="0">
 	<div style="text-align: center;">
 		<a href="#" onclick="reset_sorting('<inp2:m_Param name="prefix"/>', <inp2:m_param name="ajax"/>); return false;" title="<inp2:m_phrase name="la_col_ResetToDefaultSorting" html_escape="1"/>">
 			<img src="<inp2:m_TemplatesBase/>/img/list_arrow_<inp2:m_if check='{$prefix}_OrderChanged'>no<inp2:m_else/>desc</inp2:m_if>_big.gif" width="16" height="16" alt="<inp2:m_phrase name="la_col_ResetToDefaultSorting" html_escape="1"/>"/>
 		</a>
 	</div>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_total_row">
 	GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].SetFooter(
 		[
 			['&nbsp;', <inp2:IterateGridFields grid="$grid" mode="total" force_block="grid_js_block" ajax="$ajax" pass_params="1"/>]
 		]
 	);
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_js"
 	main_prefix="" per_page="" main_special="" grid_filters="1"
 	header_block="grid_column_title"
 	filter_block="grid_column_filter"
 	data_block="grid_data_td"
 	total_block="grid_total_td"
 	row_block="_row"
 	ajax="0"
 	totals="0"
 	limited_heights="false"
 	max_row_height="45"
 	grid_height="auto"
 	grid_status="1" ajax="1"
 	totals_render_as=""
 	selector="checkbox"
 	mouseover_class="grid-data-row-mouseover" selected_class="grid-data-row-selected:grid-data-row-even-selected" tag_name="tr"
 >
 		<inp2:GridSelector grid="$grid" default="$selector" result_to_var="selector"/>
 
 		// 1. create grid
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'] = new GridScroller('grid_<inp2:m_Param name="PrefixSpecial" />', 'auto', <inp2:m_if check="m_Param" name="grid_height" equals_to="auto">'<inp2:m_Param name="grid_height"/>'<inp2:m_else/><inp2:m_Param name="grid_height"/></inp2:m_if>);
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].Spacer = 'img/spacer.gif';
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].LeftCells = <inp2:FreezerPosition grid="$grid"/>;
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].BottomOffset = <inp2:m_if check="m_Param" name="grid_status">30<inp2:m_else/>0</inp2:m_if>;
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].MinWidths = [<inp2:GridSelectorColumnWidth selector="$selector" icon_width="20" selector_width="30" grid="$grid"/>, <inp2:IterateGridFields grid="$grid" mode="width" block="grid_js_width_td" ajax="$ajax"/>];
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].PickerCRC = '<inp2:PickerCRC grid="$grid"/>';
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].LimitedHeights = <inp2:m_param name="limited_heights"/>;
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].MaxRowHeight = <inp2:m_param name="max_row_height"/>;
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].SetHeader(
 			[
 				[' <inp2:m_RenderElement name="default_sorting_element" prefix="$PrefixSpecial" ajax="$ajax" js_escape="1" strip_nl="2"/>', <inp2:IterateGridFields grid="$grid" mode="header" force_block="grid_js_block" ajax="$ajax" pass_params="1"/>],
 				['<inp2:m_if check="m_Param" name="selector" equals_to="checkbox"><inp2:m_RenderElement name="grid_select_all_checkbox_html" pass_params="1" js_escape="1"/><inp2:m_else/>&nbsp;</inp2:m_if>',
 					<inp2:m_if check="m_Param" name="grid_filters">
 						<inp2:IterateGridFields grid="$grid" mode="filter" force_block="grid_js_filter_block" ajax="$ajax" pass_params="1"/>
 					<inp2:m_else/>
 						<inp2:IterateGridFields grid="$grid" mode="filter" force_block="grid_js_empty_filter_block" ajax="$ajax" pass_params="1"/>
 					</inp2:m_if>
 				]
 			]
 		)
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].FieldNames = ['_CheckboxColumn', <inp2:IterateGridFields grid="$grid" mode="fields"/>];
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].SetData(
 			[
 				<inp2:m_DefineElement name="js_row" td_style="" row_class_render_as="" selector_render_as="grid_selector_html" row_class="">
 					{ 'row_class': '<inp2:m_if check="m_Param" name="row_class_render_as"><inp2:m_RenderElement name="$row_class_render_as" PrefixSpecial="$PrefixSpecial" trim="1"/><inp2:m_else/><inp2:m_Param name="row_class"/></inp2:m_if>',
 						'data': ['<inp2:m_RenderElement name="$selector_render_as" pass_params="1" js_escape="1"/>',<inp2:IterateGridFields grid="$grid" mode="data" force_block="grid_js_block" pass_params="1"/>]
 					}<inp2:m_if check="m_Param" name="is_last" inverse="1">,</inp2:m_if>
 				</inp2:m_DefineElement>
 				<inp2:m_set {$PrefixSpecial}_sequence="1" odd_even="table-color1"/>
 
 				<inp2:m_if check="UseItemIcons" grid="$grid">
 					<inp2:PrintList block="js_row" selector_render_as="grid_selector_icon_html" per_page="$per_page" main_special="$main_special" selector="$selector" id_field="$IdField" grid="$grid"/>
 				<inp2:m_else/>
 					<inp2:PrintList block="js_row" selector_render_as="grid_selector_html" per_page="$per_page" main_special="$main_special" selector="$selector" id_field="$IdField" grid="$grid"/>
 				</inp2:m_if>
 			]
 		)
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].IDs = [
 			<inp2:m_DefineElement name="js_id">
 				'<inp2:m_param name="PrefixSpecial"/>_<inp2:Field field="$IdField"/>'<inp2:m_if check="m_Param" name="is_last" inverse="1">,</inp2:m_if>
 			</inp2:m_DefineElement>
 			<inp2:PrintList block="js_id" per_page="$per_page" id_field="$IdField" main_special="$main_special"/>
 		]
 
 		<inp2:m_if check="m_Param" name="totals_render_as">
 			<inp2:m_RenderElement name="$totals_render_as" pass_params="1"/>
 		</inp2:m_if>
 
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].Render('grid_<inp2:m_Param name="PrefixSpecial" />_container');
 
 		<inp2:m_ifnot check="m_Param" name="ajax">
 			<inp2:m_RenderElement name="grid_search_buttons" pass_params="1"/>
 		</inp2:m_ifnot>
 
 		GridScrollers['<inp2:m_param name="PrefixSpecial"/>'].SaveURL = '<inp2:m_t pass="m,$PrefixSpecial" {$PrefixSpecial}_event="OnSaveWidths" widths="#WIDTHS#" no_amp="1" grid_name="$grid"/>';
 
 		<inp2:m_if check="m_Param" name="selector">
 			// 2. scan grid (only when using selector)
 			Grids['<inp2:m_param name="PrefixSpecial"/>'] = new Grid('<inp2:m_param name="PrefixSpecial"/>', '<inp2:m_param name="selected_class"/>', ':original', ($allow_dbl_click === undefined || $allow_dbl_click ? edit : function() {}) , a_toolbar);
 
 			Grids['<inp2:m_param name="PrefixSpecial"/>'].MouseOverClass = '<inp2:m_param name="mouseover_class"/>';
 			Grids['<inp2:m_param name="PrefixSpecial"/>'].StickySelection = true;
 			Grids['<inp2:m_param name="PrefixSpecial"/>'].AddItemsByIdMask('<inp2:m_param name="tag_name"/>', /^<inp2:m_param name="PrefixSpecial"/>_([\d\w-=]+)/, '<inp2:m_param name="PrefixSpecial"/>[$$ID$$][<inp2:m_param name="IdField"/>]');
 	  		Grids['<inp2:m_param name="PrefixSpecial"/>'].InitItems();
 
 	  		<inp2:m_if check="m_Param" name="selector" equals_to="radio">
 		  		Grids['<inp2:m_param name="PrefixSpecial"/>'].EnableRadioMode();
 			</inp2:m_if>
 
 	  		<inp2:m_if check="{$PrefixSpecial}_UseAutoRefresh">
 	  			function refresh_grid() {
 	  				// window.location.reload();
 	  				var $window_url = window.location.href;
 	  				if ($window_url.indexOf('skip_session_refresh=1') == -1) {
 	  					$window_url += '&skip_session_refresh=1';
 	  				}
 
 	  				window.location.href = $window_url;
 	  			}
 
 	  			setTimeout('refresh_grid()', <inp2:{$PrefixSpecial}_AutoRefreshInterval/> * 60000);
 	  		</inp2:m_if>
   		</inp2:m_if>
 
   		<inp2:m_RenderElement name="nlsmenu_declaration" pass_params="true"/>
 
   		$ViewMenus = new Array('<inp2:m_param name="PrefixSpecial"/>');
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="old_grid" main_prefix="" per_page="" main_special="" grid_filters="" search="on" header_block="grid_column_title" filter_block="grid_column_filter" data_block="grid_data_td" total_block="grid_total_td" row_block="_row" ajax="0" totals="0" selector="checkbox">
 <!--##
 	DEPRICATED. LEFT FOR EDUCATION PURPOSES.
 
 	grid_filters - show individual filters for each column
 	has_filters  - draw filter section in "View" menu in toolbar
 ##-->
 
 	<inp2:InitList pass_params="1"/> <!--## this is to avoid recalling prefix as an item in first iterate grid, by col-picker for instance ##-->
 
 	<inp2:GridSelector grid="$grid" default="$selector" result_to_var="selector"/>
 
 	<inp2:{$PrefixSpecial}_SaveWarning name="grid_save_warning" main_prefix="$main_prefix"/>
 	<inp2:m_if check="{$PrefixSpecial}_SearchActive" grid="$grid">
 		<inp2:m_RenderElement design="form_message" pass_params="1">
 	    	<inp2:m_phrase name="la_Warning_Filter"/>
 		</inp2:m_RenderElement>
 	</inp2:m_if>
 
 	<inp2:m_if check="m_ParamEquals" name="per_page" value="-1" inverse="1">
 		<inp2:m_RenderElement name="grid_pagination" grid="$grid" PrefixSpecial="$PrefixSpecial" main_special="$main_special" search="$search" ajax="$ajax"/>
 	</inp2:m_if>
 	<table width="100%" cellspacing="0" cellpadding="4" class="bordered">
 
 		<inp2:m_if check="m_ParamEquals" name="grid_filters" value="1">
 			<tr class="pagination_bar">
 				<inp2:{$PrefixSpecial}_IterateGridFields grid="$grid" mode="filter" block="$filter_block" ajax="$ajax" pass_params="1"/>
 			</tr>
 		</inp2:m_if>
 
 		<tr class="grid-header-row grid-header-row-1">
 			<inp2:{$PrefixSpecial}_IterateGridFields grid="$grid" mode="header" block="$header_block" ajax="$ajax" pass_params="1"/>
 		</tr>
 
 		<inp2:m_DefineElement name="_row" td_style="">
 			<tr class="<inp2:m_odd_even odd="grid-data-row grid-data-row-even" even="grid-data-row"/>" id="<inp2:m_param name="PrefixSpecial"/>_<inp2:Field field="$IdField"/>" sequence="<inp2:m_get param="{$PrefixSpecial}_sequence"/>"><inp2:m_inc param="{$PrefixSpecial}_sequence" by="1"/>
 				<inp2:IterateGridFields grid="$grid" mode="data" block="$data_block" pass_params="1"/>
 			</tr>
 		</inp2:m_DefineElement>
 		<inp2:m_set {$PrefixSpecial}_sequence="1" odd_even="table-color1"/>
 		<inp2:{$PrefixSpecial}_PrintList block="$row_block" per_page="$per_page" main_special="$main_special" />
 
 		<inp2:m_DefineElement name="grid_total_td">
 			<inp2:m_if check="m_Param" name="total">
 				<td style="<inp2:m_param name="td_style"/>">
 					<inp2:FieldTotal name="$field" function="$total"/>
 				</td>
 			<inp2:m_else/>
 				<td style="<inp2:m_param name="td_style"/>">&nbsp;</td>
 			</inp2:m_if>
 		</inp2:m_DefineElement>
 
 		<inp2:m_if check="m_ParamEquals" name="totals" value="1">
 			<tr class="totals-row"/>
 				<inp2:IterateGridFields grid="$grid" mode="data" block="$total_block" pass_params="1"/>
 			</tr>
 		</inp2:m_if>
 	</table>
 
 	<inp2:m_if check="m_ParamEquals" name="ajax" value="0">
 		<inp2:m_if check="m_GetEquals" name="fw_menu_included" value="">
 			<link rel="stylesheet" rev="stylesheet" href="<inp2:m_Compress files='incs/nlsmenu.css'/>" type="text/css" />
 			<script type="text/javascript" src="<inp2:m_Compress files='js/nlsmenu.js|js/nlsmenueffect_1_2_1.js'/>"></script>
 
 			<script type="text/javascript">
 				var menuMgr = new NlsMenuManager("mgr");
 				menuMgr.timeout = 500;
 				menuMgr.flowOverFormElement = true;
 			</script>
 
 			<inp2:m_set fw_menu_included="1"/>
 		</inp2:m_if>
 
 		<script type="text/javascript">
 			<inp2:m_RenderElement name="old_grid_js" mouseover_class="grid-data-row-mouseover" selected_class="grid-data-row-selected:grid-data-row-even-selected" tag_name="tr" pass_params="true"/>
 		</script>
 	</inp2:m_if>
 
 	<input type="hidden" id="<inp2:m_param name="PrefixSpecial"/>_Sort1" name="<inp2:m_param name="PrefixSpecial"/>_Sort1" value="">
 	<input type="hidden" id="<inp2:m_param name="PrefixSpecial"/>_Sort1_Dir" name="<inp2:m_param name="PrefixSpecial"/>_Sort1_Dir" value="asc">
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="old_grid_js" selector="checkbox" ajax="1">
 	<!--## DEPRICATED. LEFT FOR EDUCATION PURPOSES. ##-->
 	<inp2:GridSelector grid="$grid" default="$selector" result_to_var="selector"/>
 
 	<inp2:m_if check="m_Param" name="selector">
 		Grids['<inp2:m_param name="PrefixSpecial"/>'] = new Grid('<inp2:m_param name="PrefixSpecial"/>', 'grid-data-row-selected:grid-data-row-even-selected', ':original', edit, a_toolbar);
 
 		Grids['<inp2:m_param name="PrefixSpecial"/>'].MouseOverClass = 'grid-data-row-mouseover';
 		Grids['<inp2:m_param name="PrefixSpecial"/>'].StickySelection = true;
 		Grids['<inp2:m_param name="PrefixSpecial"/>'].AddItemsByIdMask('<inp2:m_param name="tag_name"/>', /^<inp2:m_param name="PrefixSpecial"/>_([\d\w-]+)/, '<inp2:m_param name="PrefixSpecial"/>[$$ID$$][<inp2:m_param name="IdField"/>]');
   		Grids['<inp2:m_param name="PrefixSpecial"/>'].InitItems();
 
   		<inp2:m_if check="m_Param" name="selector" equals_to="radio">
 	  		Grids['<inp2:m_param name="PrefixSpecial"/>'].EnableRadioMode();
 		</inp2:m_if>
 	</inp2:m_if>
 
 	<inp2:m_RenderElement name="nlsmenu_declaration" pass_params="true"/>
 
 	$ViewMenus = new Array('<inp2:m_param name="PrefixSpecial"/>');
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_ml_selector">
 	<inp2:m_if check="lang_IsMultiLanguage">
 		<inp2:m_phrase name="la_fld_Language"/>:
 		<select name="language" onchange="submit_event('<inp2:m_param name='prefix'/>', 'OnPreSaveAndChangeLanguage');">
 			<inp2:m_DefineElement name="lang_elem">
 				<option value="<inp2:Field name='LanguageId'/>" <inp2:m_if check="SelectedLanguage" type="data">selected="selected"</inp2:m_if> ><inp2:Field name="LocalName" no_special='no_special' /></option>
 			</inp2:m_DefineElement>
 			<inp2:lang_PrintList render_as="lang_elem"/>
 		</select>
 	<inp2:m_else/>
 		<inp2:m_if check="m_Param" name="pagination">
 			<inp2:$prefix_SelectParam possible_names="pagination_prefix,prefix" result_to_var="pagination_prefix"/>
 			<inp2:m_RenderElement name="grid_pagination_elem" PrefixSpecial="$pagination_prefix" pass_params="1"/>
 		</inp2:m_if>
 	</inp2:m_if>
 </inp2:m_DefineElement>
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/incs/custom_blocks.tpl
===================================================================
--- branches/5.1.x/core/admin_templates/incs/custom_blocks.tpl	(revision 14407)
+++ branches/5.1.x/core/admin_templates/incs/custom_blocks.tpl	(revision 14408)
@@ -1,152 +1,160 @@
 <inp2:m_DefineElement name="config_edit_text">
 	<input type="text" name="<inp2:CustomInputName/>" id="<inp2:CustomInputName/>" value="<inp2:Field field="$field"/>"<inp2:m_if check="m_Param" name="field_params"> <inp2:m_Param name="field_params"/><inp2:m_else/> style="width:100%"</inp2:m_if>/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_password">
 	<input type="password" primarytype="password" name="<inp2:CustomInputName/>" id="<inp2:CustomInputName/>" value="" />
 	<input type="password" name="verify_<inp2:CustomInputName/>" id="verify_<inp2:CustomInputName/>" value="" />
 	&nbsp;<span class="error" id="error_<inp2:CustomInputName/>"></span>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_option">
 		<option value="<inp2:m_param name="key"/>"<inp2:m_param name="selected"/>><inp2:m_param name="option"/></option>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_select">
 	<select name="<inp2:CustomInputName/>">
 		<inp2:PredefinedOptions field="$field" block="config_edit_option" selected="selected"/>
 	</select>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_multiselect">
 	<select id="<inp2:CustomInputName/>_select" onchange="update_multiple_options('<inp2:CustomInputName/>');" multiple>
 		<inp2:PredefinedOptions field="$field" block="config_edit_option" selected="selected"/>
 	</select>
 	<input type="hidden" id="<inp2:CustomInputName/>" name="<inp2:CustomInputName/>" value="<inp2:Field field="$field"/>"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_checkbox">
 	<input type="hidden" id="<inp2:CustomInputName/>" name="<inp2:CustomInputName/>" value="<inp2:Field field="$field" db="db"/>">
 	<input tabindex="<inp2:m_get param="tab_index"/>" type="checkbox" id="_cb_<inp2:m_param name="field"/>" name="_cb_<inp2:m_param name="field"/>" <inp2:Field field="$field" checked="checked" db="db"/> onclick="update_checkbox(this, document.getElementById('<inp2:CustomInputName/>'))">
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_textarea">
 	<textarea name="<inp2:CustomInputName/>" id="<inp2:CustomInputName/>" <inp2:m_param name="field_params" />><inp2:Field field="$field" /></textarea>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_radio_item">
 	<input type="radio" <inp2:m_param name="checked"/> name="<inp2:CustomInputName/>" id="<inp2:CustomInputName/>_<inp2:m_param name="key"/>" value="<inp2:m_param name="key"/>"><label for="<inp2:CustomInputName/>_<inp2:m_param name="key"/>"><inp2:m_param name="option"/></label>&nbsp;
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_radio">
 			<inp2:PredefinedOptions field="$field" block="config_radio_item" selected="checked"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_date">
 	<input type="text" name="<inp2:CustomInputName append="_date"/>" id="<inp2:CustomInputName append="_date"/>" value="<inp2:CustomField append="_date" format="_regional_InputDateFormat"/>" size="<inp2:CustomFormat append="_date" input_format="1" edit_size="edit_size"/>" datepickerIcon="<inp2:m_ProjectBase/>admin/images/ddarrow.gif">&nbsp;
 	<img src="img/calendar_icon.gif" id="cal_img_<inp2:CustomInputName/>"
 					     style="cursor: pointer; margin-right: 5px"
 					     title="Date selector"
 					/>
 	<span class="small">(<inp2:CustomFormat append="_date" input_format="1" human="true"/>)</span>
 	<script type="text/javascript">
 		Calendar.setup({
 	        inputField		:	"<inp2:CustomInputName append="_date"/>",
 	        ifFormat		:	Calendar.phpDateFormat("<inp2:CustomFormat append="_date" input_format="1"/>"),
 	        button			:	"cal_img_<inp2:CustomInputName/>",
 	        align			:	"br",
 	        singleClick		:	true,
 	        showsTime		:	true,
 	        weekNumbers		:	false,
 	        firstDay		:	<inp2:m_GetConfig var="FirstDayOfWeek"/>,
 	        onUpdate	:	function(cal) {
 	        	runOnChange('<inp2:CustomInputName append="_date"/>');
 	       	}
 		});
 	</script>
 
 	<input type="hidden" name="<inp2:CustomInputName append="_time"/>" value="">
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="config_edit_datetime">
 	<input type="text" name="<inp2:CustomInputName append="_date"/>" id="<inp2:CustomInputName append="_date"/>" value="<inp2:CustomField append="_date" format="_regional_InputDateFormat"/>" size="<inp2:CustomFormat append="_date" input_format="1" edit_size="edit_size"/>" datepickerIcon="<inp2:m_ProjectBase/>admin/images/ddarrow.gif">&nbsp;
 	<img src="img/calendar_icon.gif" id="cal_img_<inp2:CustomInputName/>"
 					     style="cursor: pointer; margin-right: 5px"
 					     title="Date selector"
 					/>
 	<span class="small">(<inp2:CustomFormat append="_date" input_format="1" human="true"/>)</span>
 	<input type="hidden" id="full_date_<inp2:CustomInputName/>" value="<inp2:CustomField format=""/>" />
 	<script type="text/javascript">
 		Calendar.setup({
 	        inputField	:	"full_date_<inp2:CustomInputName/>",
 	        ifFormat	:	Calendar.phpDateFormat("<inp2:CustomFormat input_format="1"/>"),
 	        button		:	"cal_img_<inp2:CustomInputName/>",
 	        align		:	"br",
 	        singleClick	:	true,
 	        showsTime	:	true,
 	        weekNumbers	:	false,
 	        firstDay	:	<inp2:m_GetConfig var="FirstDayOfWeek"/>,
 	        onUpdate	:	function(cal) {
 	        	document.getElementById('<inp2:CustomInputName append="_date"/>').value = cal.date.print( Calendar.phpDateFormat("<inp2:CustomFormat append="_date" input_format="1"/>") );
 	        	document.getElementById('<inp2:CustomInputName append="_time"/>').value = cal.date.print( Calendar.phpDateFormat("<inp2:CustomFormat append="_time" input_format="1"/>") );
 	       	}
 		});
 	</script>
 	&nbsp;<input type="text" name="<inp2:CustomInputName append="_time"/>" id="<inp2:CustomInputName append="_time"/>" value="<inp2:CustomField append="_time" format="_regional_InputTimeFormat"/>" size="<inp2:CustomFormat append="_time" input_format="1" edit_size="edit_size"/>"><span class="small"> (<inp2:CustomFormat append="_time" input_format="1" human="true"/>)</span>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="cv_row_block">
 	<inp2:m_if check="m_ParamEquals" name="show_heading" value="1">
 		<tr class="subsectiontitle">
 			<td colspan="3">
 				<inp2:Field name="Heading" as_label="1"/>
 			</td>
 			<inp2:m_if check="{$SourcePrefix}_DisplayOriginal" pass_params="1">
 				<td><inp2:m_phrase name="$original_title"/></td>
 			</inp2:m_if>
 		</tr>
 	</inp2:m_if>
 
 	<tr class="<inp2:m_odd_even odd='edit-form-odd' even='edit-form-even'/>">
 		<inp2:m_inc param="tab_index" by="1"/>
 		<td class="label-cell" onmouseover="show_form_error('<inp2:m_Param name="SourcePrefix" js_escape="1"/>', '<inp2:m_Param name="virtual_field" js_escape="1"/>')" onmouseout="hide_form_error('<inp2:m_Param name="SourcePrefix" js_escape="1"/>')">
-			<inp2:m_RenderElement name="grid_data_label_ml_td" grid="$grid" SourcePrefix="$SourcePrefix" virtual_field="$virtual_field" value_field="$value_field" ElementTypeField="ElementType" field="Prompt" PrefixSpecial="$PrefixSpecial"/>
+			<span class="<inp2:m_if check='{$SourcePrefix}_HasError' field='$virtual_field'>error-cell</inp2:m_if>"><inp2:Field field="Prompt" as_label="1"/></span><inp2:m_if check="{$SourcePrefix}_IsRequired" field="$virtual_field"><span class="field-required">&nbsp;*</span></inp2:m_if>:
+
+			<inp2:m_if check="FieldEquals" field="ElementType" value="textarea">
+				<br/>
+				<inp2:{$SourcePrefix}_InputName field="$virtual_field" result_to_var="input_name"/>
+				<a href="<inp2:m_Link template='popups/editor' TargetField='$input_name' pass_through='TargetField' pass='m,$SourcePrefix'/>" onclick="openSelector('<inp2:m_Param name='SourcePrefix' js_escape='1'/>', this.href, '', '800x575'); return false;">
+					<img src="img/icons/icon24_link_editor.gif" border="0">
+				</a>
+			</inp2:m_if>
 		</td>
 		<td class="control-mid">&nbsp;</td>
 		<script type="text/javascript">
 			if (typeof(fields['<inp2:m_Param name="SourcePrefix" js_escape="1"/>']) == 'undefined') {
 				fields['<inp2:m_Param name="SourcePrefix" js_escape="1"/>'] = new Object();
 			}
 
 			fields['<inp2:m_Param name="SourcePrefix" js_escape="1"/>']['<inp2:m_Param name="virtual_field" js_escape="1"/>'] = '<inp2:{$PrefixSpecial}_Field field="Prompt" grid="$grid" as_label="1" no_special="no_special" js_escape="1"/>'
 		</script>
 
 		<td class="control-cell" valign="top">
 			<inp2:ConfigFormElement field="Value" blocks_prefix="config_edit_" element_type_field="ElementType" value_list_field="ValueList" />
 		</td>
 		<inp2:m_RenderElement name="inp_edit_error" prefix="$SourcePrefix" field="$virtual_field"/>
 		<inp2:m_if check="{$SourcePrefix}_DisplayOriginal" pass_params="1">
 			<inp2:m_RenderElement prefix="$SourcePrefix" field="$field" name="inp_original_label"/>
 		</inp2:m_if>
 	</tr>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="edit_custom_td">
 	<inp2:ConfigFormElement field="Value" blocks_prefix="config_edit_" element_type_field="ElementType" value_list_field="ValueList" />
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="custom_error_td">
 	<inp2:$SourcePrefix_Error field="$virtual_field"/>
 </inp2:m_DefineElement>
 
 <inp2:m_DefineElement name="grid_original_td" >
 	<inp2:Field field="$field" grid="$grid"/>
 </inp2:m_DefineElement>
 
 <!--<inp2:m_DefineElement name="edit_custom_td">
 	<td valign="top" class="text">
 		<input type="hidden" name="<inp2:InputName field="ResourceId"/>" id="<inp2:InputName field="ResourceId"/>" value="<inp2:Field field="ResourceId" grid="$grid"/>">
 		<input type="hidden" name="<inp2:InputName field="CustomDataId"/>" id="<inp2:InputName field="CustomDataId"/>" value="<inp2:Field field="CustomDataId" grid="$grid"/>">
 		<inp2:ConfigFormElement field="Value" blocks_prefix="config_edit_" element_type_field="ElementType" value_list_field="ValueList" />
 	</td>
 </inp2:m_DefineElement>-->
\ No newline at end of file