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 = '-∞'; if ( !isset($max_val) ) $max_val = '∞'; $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">></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"><</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">>></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"><<</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"> <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"/>: </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/> </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=" "> <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"> <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('§ion=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( [ [' ', <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/> </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"/>"> </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="" /> <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> </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"> <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"> <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> <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"> *</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"> </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