mirror of
https://github.com/colymba/GridFieldBulkEditingTools.git
synced 2024-10-22 11:05:57 +02:00
NEW Rewrite of bulk editing save FIX #76
Bulk editing now use the normal Form submission system and handles all field type, including ajax dependent
This commit is contained in:
parent
4a349987a4
commit
1ceee59360
@ -14,8 +14,6 @@ The component's options can be configurated individually or in bulk through the
|
||||
### $config overview
|
||||
The available configuration options are:
|
||||
* 'editableFields' : array of string referencing specific CMS fields available for editing
|
||||
* 'fieldsNameBlacklist' : array of string referencing the names of fields that wont be available for editing
|
||||
* 'readOnlyFieldClasses' : array of string referencing types (ClassName) of fields that will be transformed to read only (always includes `GridField` and `UploadField`)
|
||||
|
||||
## Custom actions
|
||||
You can remove or add individual action or replace them all via `addBulkAction()` and `removeBulkAction()`
|
||||
|
@ -12,7 +12,11 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
* RequestHandler allowed actions
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_actions = array('edit', 'update');
|
||||
private static $allowed_actions = array(
|
||||
'index',
|
||||
'bulkEditForm',
|
||||
'recordEditForm'
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
@ -20,18 +24,30 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
* @var array
|
||||
*/
|
||||
private static $url_handlers = array(
|
||||
'bulkEdit/update' => 'update',
|
||||
'bulkEdit' => 'edit'
|
||||
'bulkEdit/bulkEditForm' => 'bulkEditForm',
|
||||
'bulkEdit/recordEditForm' => 'recordEditForm',
|
||||
'bulkEdit' => 'index'
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Return URL to this RequestHandler
|
||||
* @param string $action Action to append to URL
|
||||
* @return string URL
|
||||
*/
|
||||
public function Link($action = null)
|
||||
{
|
||||
return Controller::join_links(parent::Link(), 'bulkEdit', $action);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a form for all the selected DataObjects
|
||||
* with their respective editable fields.
|
||||
*
|
||||
* @return Form Selected DataObjects editable fields
|
||||
*/
|
||||
public function editForm()
|
||||
public function bulkEditForm()
|
||||
{
|
||||
$crumbs = $this->Breadcrumbs();
|
||||
if($crumbs && $crumbs->count()>=2)
|
||||
@ -42,13 +58,11 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
$actions = new FieldList();
|
||||
|
||||
$actions->push(
|
||||
FormAction::create('SaveAll', _t('GRIDFIELD_BULKMANAGER_EDIT_HANDLER.SAVE_BTN_LABEL', 'Save all'))
|
||||
->setAttribute('id', 'bulkEditingUpdateBtn')
|
||||
->addExtraClass('ss-ui-action-constructive cms-panel-link')
|
||||
FormAction::create('doSave', _t('GRIDFIELD_BULKMANAGER_EDIT_HANDLER.SAVE_BTN_LABEL', 'Save all'))
|
||||
->setAttribute('id', 'bulkEditingSaveBtn')
|
||||
->addExtraClass('ss-ui-action-constructive')
|
||||
->setAttribute('data-icon', 'accept')
|
||||
->setAttribute('data-url', $this->gridField->Link('bulkaction/bulkEdit/update'))
|
||||
->setUseButtonTag(true)
|
||||
->setAttribute('src', '')//changes type to image so isn't hooked by default actions handlers
|
||||
);
|
||||
|
||||
$actions->push(
|
||||
@ -70,6 +84,7 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
$singleton = singleton($modelClass);
|
||||
$titleModelClass = (($editingCount > 1) ? $singleton->i18n_plural_name() : $singleton->i18n_singular_name());
|
||||
|
||||
//some cosmetics
|
||||
$headerText = _t('GRIDFIELD_BULKMANAGER_EDIT_HANDLER.HEADER_TEXT',
|
||||
'Editing {count} {class}',
|
||||
array(
|
||||
@ -85,10 +100,12 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
|
||||
$toggle = LiteralField::create('bulkEditToggle', '<span id="bulkEditToggle">' . _t('GRIDFIELD_BULKMANAGER_EDIT_HANDLER.TOGGLE_ALL_LINK', 'Show/Hide all') . '</span>');
|
||||
$recordsFieldList->push($toggle);
|
||||
|
||||
|
||||
|
||||
//fetch fields for each record and push to fieldList
|
||||
foreach ( $recordList as $id )
|
||||
{
|
||||
$record = DataObject::get_by_id($modelClass, $id);
|
||||
{
|
||||
$record = DataObject::get_by_id($modelClass, $id);
|
||||
$recordEditingFields = $this->getRecordEditingFields($record);
|
||||
|
||||
$toggleField = ToggleCompositeField::create(
|
||||
@ -103,18 +120,72 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
$recordsFieldList->push($toggleField);
|
||||
}
|
||||
|
||||
$form = new Form(
|
||||
$bulkEditForm = Form::create(
|
||||
$this,
|
||||
'BulkEditingForm',
|
||||
'recordEditForm', //recordEditForm name is here to trick SS to pass all subform request to recordEditForm()
|
||||
$recordsFieldList,
|
||||
$actions
|
||||
);
|
||||
);
|
||||
|
||||
if($crumbs && $crumbs->count()>=2){
|
||||
$form->Backlink = $one_level_up->Link;
|
||||
$bulkEditForm->Backlink = $one_level_up->Link;
|
||||
}
|
||||
|
||||
return $form;
|
||||
//override form action URL back to bulkEditForm
|
||||
//and add record ids GET var
|
||||
$bulkEditForm->setAttribute(
|
||||
'action',
|
||||
$this->Link('bulkEditForm?records[]='.implode('&', $recordList))
|
||||
);
|
||||
|
||||
return $bulkEditForm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return's a form with only one record's fields
|
||||
* Used for bulkEditForm subForm requests via ajax
|
||||
*
|
||||
* @return Form Currently being edited form
|
||||
*/
|
||||
public function recordEditForm()
|
||||
{
|
||||
//clone current request : used to figure out what record we are asking
|
||||
$request = clone $this->request;
|
||||
$recordInfo = $request->shift();
|
||||
|
||||
//shift request till we find the requested field
|
||||
while ($recordInfo)
|
||||
{
|
||||
if ( $unescapedRecordInfo = $this->unEscapeFieldName($recordInfo) )
|
||||
{
|
||||
$id = $unescapedRecordInfo['id'];
|
||||
$fieldName = $unescapedRecordInfo['name'];
|
||||
|
||||
$action = $request->shift();
|
||||
break;
|
||||
}
|
||||
else{
|
||||
$recordInfo = $request->shift();
|
||||
}
|
||||
}
|
||||
|
||||
//generate a form with only that requested record's fields
|
||||
if ( $id )
|
||||
{
|
||||
$modelClass = $this->gridField->getModelClass();
|
||||
$record = DataObject::get_by_id($modelClass, $id);
|
||||
|
||||
$cmsFields = $record->getCMSFields();
|
||||
$recordEditingFields = $this->getRecordEditingFields($record);
|
||||
|
||||
return Form::create(
|
||||
$this->gridField,
|
||||
'recordEditForm',
|
||||
FieldList::create($recordEditingFields),
|
||||
FieldList::create()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -159,8 +230,6 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
{
|
||||
$config = $this->component->getConfig();
|
||||
$editableFields = $config['editableFields'];
|
||||
$fieldsNameBlacklist = $config['fieldsNameBlacklist'];
|
||||
$readOnlyClasses = $config['readOnlyFieldClasses'];
|
||||
|
||||
// get all dataFields or just the ones allowed in config
|
||||
if ( $editableFields )
|
||||
@ -179,39 +248,62 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
$dataFields = $fields->dataFields();
|
||||
}
|
||||
|
||||
// remove and/or set readonly fields in blacklists
|
||||
foreach ($dataFields as $name => $field)
|
||||
{
|
||||
if ( in_array($name, $fieldsNameBlacklist) )
|
||||
{
|
||||
unset( $dataFields[$name] );
|
||||
}
|
||||
else if ( in_array(get_class($field), $readOnlyClasses) )
|
||||
{
|
||||
$newField = $field->performReadonlyTransformation();
|
||||
$dataFields[$name] = $newField;
|
||||
}
|
||||
}
|
||||
|
||||
// escape field names with unique prefix
|
||||
foreach ( $dataFields as $name => $field )
|
||||
{
|
||||
$field->Name = 'record_' . $id . '_' . $name;
|
||||
$field->Name = $this->escapeFieldName($id, $name);
|
||||
$dataFields[$name] = $field;
|
||||
}
|
||||
|
||||
return $dataFields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Escape a fieldName with a unique prefix
|
||||
*
|
||||
* @param integer $recordID Record id from who the field belongs
|
||||
* @param string $name Field name
|
||||
* @return string Escaped field name
|
||||
*/
|
||||
protected function escapeFieldName($recordID, $name)
|
||||
{
|
||||
return 'record_' . $recordID . '_' . $name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Un-escape a previously escaped field name
|
||||
*
|
||||
* @param string $fieldName Escaped field name
|
||||
* @return array|false Fasle if the fieldName was not escaped. Or Array map with record 'id' and field 'name'
|
||||
*/
|
||||
protected function unEscapeFieldName($fieldName)
|
||||
{
|
||||
$parts = array();
|
||||
$match = preg_match('/record_(\d+)_(\w+)/i', $fieldName, $parts);
|
||||
|
||||
if ( !$match )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
return array(
|
||||
'id' => $parts[1],
|
||||
'name' => $parts[2],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates and return the editing interface
|
||||
* Creates and return the bulk editing interface
|
||||
*
|
||||
* @return string Form's HTML
|
||||
*/
|
||||
public function edit()
|
||||
public function index()
|
||||
{
|
||||
$form = $this->editForm();
|
||||
$form = $this->bulkEditForm();
|
||||
$form->setTemplate('LeftAndMain_EditForm');
|
||||
$form->addExtraClass('center cms-content');
|
||||
$form->setAttribute('data-pjax-fragment', 'CurrentForm Content');
|
||||
@ -236,49 +328,72 @@ class GridFieldBulkActionEditHandler extends GridFieldBulkActionHandler
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Saves the changes made in the bulk edit into the dataObject
|
||||
* Handles bulkEditForm submission
|
||||
* and parses and saves each records data
|
||||
*
|
||||
* @return JSON
|
||||
* @param array $data Sumitted form data
|
||||
* @param Form $form Form
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$data = $this->request->requestVars();
|
||||
$return = array();
|
||||
$className = $this->gridField->list->dataClass;
|
||||
public function doSave($data, $form)
|
||||
{
|
||||
$className = $this->gridField->list->dataClass;
|
||||
$singleton = singleton($className);
|
||||
|
||||
if ( isset($data['url']) ) unset($data['url']);
|
||||
if ( isset($data['cacheBuster']) ) unset($data['cacheBuster']);
|
||||
if ( isset($data['locale']) ) unset($data['locale']);
|
||||
$formsData = array();
|
||||
$ids = array();
|
||||
$done = 0;
|
||||
|
||||
foreach ($data as $recordID => $recordDataSet)
|
||||
//unescape and sort form data per record ID
|
||||
foreach ($data as $fieldName => $value)
|
||||
{
|
||||
$record = DataObject::get_by_id($className, $recordID);
|
||||
foreach($recordDataSet as $recordData)
|
||||
if ( $fieldInfo = $this->unEscapeFieldName($fieldName) )
|
||||
{
|
||||
$field = preg_replace('/record_(\d+)_(\w+)/i', '$2', $recordData['name']);
|
||||
$value = $recordData['value'];
|
||||
if ( !isset($formsData[$fieldInfo['id']]) )
|
||||
{
|
||||
$formsData[$fieldInfo['id']] = array();
|
||||
}
|
||||
|
||||
if ( $record->hasMethod($field) )
|
||||
{
|
||||
$list = $record->$field();
|
||||
$list->setByIDList($value);
|
||||
}
|
||||
else{
|
||||
$record->setCastedField($field, $value);
|
||||
}
|
||||
$formsData[$fieldInfo['id']][$fieldInfo['name']] = $value;
|
||||
}
|
||||
$done = $record->write();
|
||||
array_push($return, array(
|
||||
'id' => $done,
|
||||
'title' => $record->getTitle()
|
||||
));
|
||||
}
|
||||
|
||||
return json_encode(array(
|
||||
'done' => 1,
|
||||
'records' => $return
|
||||
), JSON_NUMERIC_CHECK);
|
||||
//process each record's form data and save
|
||||
foreach ($formsData as $recordID => $recordData)
|
||||
{
|
||||
$record = DataObject::get_by_id($className, $recordID);
|
||||
$recordForm = Form::create(
|
||||
$this, "RecordForm",
|
||||
$record->getCMSFields(),
|
||||
FieldList::create()
|
||||
);
|
||||
|
||||
$recordForm->loadDataFrom($recordData);
|
||||
$recordForm->saveInto($record);
|
||||
$id = $record->write();
|
||||
|
||||
array_push($ids, $record->ID);
|
||||
|
||||
if ( $id )
|
||||
{
|
||||
$done++;
|
||||
}
|
||||
}
|
||||
|
||||
//compose form message
|
||||
$messageModelClass = (($editingCount > 1) ? $singleton->i18n_plural_name() : $singleton->i18n_singular_name());
|
||||
$message = _t('GRIDFIELD_BULKMANAGER_EDIT_HANDLER.SAVE_RESULT_TEXT',
|
||||
'{count} {class} saved successfully.',
|
||||
array(
|
||||
'count' => $done,
|
||||
'class' => $messageModelClass
|
||||
)
|
||||
);
|
||||
$form->sessionMessage($message, 'good');
|
||||
|
||||
//return back to form
|
||||
return Controller::curr()->redirect($this->Link('?records[]='.implode('&records[]=', $ids)));
|
||||
//return Controller::curr()->redirect($form->Backlink); //returns to gridField
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class GridFieldBulkActionHandler extends RequestHandler
|
||||
*/
|
||||
public function Link($action = null)
|
||||
{
|
||||
return Controller::join_links($this->gridField->Link(), 'bulkediting', $action);
|
||||
return Controller::join_links($this->gridField->Link(), 'bulkAction', $action);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,27 +12,16 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
* component configuration
|
||||
*
|
||||
* 'editableFields' => fields editable on the Model
|
||||
* 'readOnlyFieldClasses' => field types that will be converted to readonly
|
||||
* 'fieldsNameBlacklist' => fields that will be removed from the automatic form generation
|
||||
* 'actions' => maps of action name and configuration
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config = array(
|
||||
'editableFields' => null,
|
||||
'fieldsNameBlacklist' => array(),
|
||||
'readOnlyFieldClasses' => array(),
|
||||
'actions' => array()
|
||||
'editableFields' => null,
|
||||
'actions' => array()
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Holds any class that should not be used as they break the component
|
||||
* These cannot be removed from the blacklist
|
||||
*/
|
||||
protected $readOnlyFieldClasses = array('GridField', 'UploadField');
|
||||
|
||||
|
||||
/**
|
||||
* GridFieldBulkManager component constructor
|
||||
*
|
||||
@ -42,7 +31,6 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
public function __construct($editableFields = null, $defaultActions = true)
|
||||
{
|
||||
if ( $editableFields != null ) $this->setConfig ( 'editableFields', $editableFields );
|
||||
$this->config['readOnlyFieldClasses'] = $this->readOnlyFieldClasses;
|
||||
|
||||
if ( $defaultActions )
|
||||
{
|
||||
@ -102,17 +90,11 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
user_error("Bulk actions must be edited via addBulkAction() and removeBulkAction()", E_USER_ERROR);
|
||||
}
|
||||
|
||||
if ( ($reference == 'readOnlyFieldClasses' || $reference == 'fieldsNameBlacklist' || $reference == 'editableFields') && !is_array($value) )
|
||||
if ( ($reference == 'editableFields') && !is_array($value) )
|
||||
{
|
||||
$value = array($value);
|
||||
}
|
||||
|
||||
//makes sure $readOnlyFieldClasses are in no matter what
|
||||
if ( $reference == 'readOnlyFieldClasses' )
|
||||
{
|
||||
$value = array_unique( array_merge($value, $this->readOnlyFieldClasses) );
|
||||
}
|
||||
|
||||
$this->config[$reference] = $value;
|
||||
|
||||
return $this;
|
||||
@ -130,62 +112,6 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
if ( $reference ) return $this->config[$reference];
|
||||
else return $this->config;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a field to the editable fields blacklist
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return boolean
|
||||
*/
|
||||
function addFieldNameToBlacklist ( $fieldName )
|
||||
{
|
||||
return array_push( $this->config['fieldsNameBlacklist'], $fieldName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a class to the readonly list
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
function addClassToReadOnlyList ( $className )
|
||||
{
|
||||
return array_push( $this->config['readOnlyFieldClasses'], $className);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a field to the editable fields blacklist
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return boolean
|
||||
*/
|
||||
function removeFieldNameFromBlacklist ( $fieldName )
|
||||
{
|
||||
if (key_exists($fieldName, $this->config['fieldsNameBlacklist'])) {
|
||||
return delete( $this->config['fieldsNameBlacklist'][$fieldName] );
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a class to the readonly list
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
function removeClassFromReadOnlyList ( $className )
|
||||
{
|
||||
if (key_exists($className, $this->config['readOnlyFieldClasses']) && !in_array($className, $this->forbiddenFieldsClasses)) {
|
||||
return delete( $this->config['readOnlyFieldClasses'][$className] );
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -379,7 +305,7 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
'Menu' => $dropDownActionsList->FieldHolder(),
|
||||
'Button' => array(
|
||||
'Label' => _t('GRIDFIELD_BULK_MANAGER.ACTION_BTN_LABEL', 'Go'),
|
||||
'DataURL' => $gridField->Link('bulkaction'),
|
||||
'DataURL' => $gridField->Link('bulkAction'),
|
||||
'Icon' => $this->config['actions'][$firstAction]['config']['icon'],
|
||||
'DataConfig' => htmlspecialchars(json_encode($actionsConfig), ENT_QUOTES, 'UTF-8')
|
||||
),
|
||||
@ -410,7 +336,7 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
*/
|
||||
public function getURLHandlers($gridField) {
|
||||
return array(
|
||||
'bulkaction' => 'handlebulkaction'
|
||||
'bulkAction' => 'handleBulkAction'
|
||||
);
|
||||
}
|
||||
|
||||
@ -427,7 +353,7 @@ class GridFieldBulkManager implements GridField_HTMLProvider, GridField_ColumnPr
|
||||
* @param SS_HTTPRequest $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function handlebulkaction($gridField, $request)
|
||||
public function handleBulkAction($gridField, $request)
|
||||
{
|
||||
$controller = $gridField->getForm()->Controller();
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
onunmatch: function(){},
|
||||
onclick: function(e)
|
||||
{
|
||||
var toggleFields = this.parents('#Form_BulkEditingForm').find('.ss-toggle .ui-accordion-header'),
|
||||
var toggleFields = this.parents('form').find('.ss-toggle .ui-accordion-header'),
|
||||
state = this.data('state')
|
||||
;
|
||||
|
||||
@ -58,71 +58,5 @@
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Save all button
|
||||
* process all field holders with updates
|
||||
*/
|
||||
$('#bulkEditingUpdateBtn').entwine({
|
||||
onmatch: function(){},
|
||||
onunmatch: function(){},
|
||||
onclick: function(e){
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
var $fieldHolders = $('div.bulkEditingFieldHolder.hasUpdate'),
|
||||
url = this.data('url'),
|
||||
data = {},
|
||||
cacheBuster = new Date().getTime() + '_' + this.attr('name')
|
||||
;
|
||||
|
||||
if ( $fieldHolders.length > 0 )
|
||||
{
|
||||
this.addClass('loading');
|
||||
}
|
||||
else{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( url.indexOf('?') !== -1 )
|
||||
{
|
||||
cacheBuster = '&cacheBuster=' + cacheBuster;
|
||||
}
|
||||
else{
|
||||
cacheBuster = '?cacheBuster=' + cacheBuster;
|
||||
}
|
||||
|
||||
$fieldHolders.each(function(){
|
||||
var $this = $(this);
|
||||
data[$this.data('id')] = $this.find(':input').serializeArray();
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: url + cacheBuster,
|
||||
data: data,
|
||||
type: "POST",
|
||||
context: this
|
||||
}).success(function(data, textStatus, jqXHR){
|
||||
try{
|
||||
data = $.parseJSON(data);
|
||||
}catch(er){}
|
||||
|
||||
$.each(data.records, function(index, record){
|
||||
var $fieldHolder = $('#Form_BulkEditingForm_RecordFields_'+record.id),
|
||||
$header = $fieldHolder.find('.ui-accordion-header')
|
||||
;
|
||||
|
||||
$fieldHolder.removeClass('hasUpdate').addClass('updated');
|
||||
$header.find('a').html(record.title);
|
||||
if ( $header.hasClass('ui-state-active') )
|
||||
{
|
||||
$header.click();
|
||||
}
|
||||
});
|
||||
|
||||
this.removeClass('loading');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}(jQuery));
|
@ -19,4 +19,5 @@ en:
|
||||
HEADER_TEXT: Editing {count} {class}
|
||||
TOGGLE_ALL_LINK: Show/Hide all
|
||||
SAVE_BTN_LABEL: Save all
|
||||
CANCEL_BTN_LABEL: Cancel
|
||||
CANCEL_BTN_LABEL: Cancel
|
||||
SAVE_RESULT_TEXT: {count} {class} saved successfully.
|
Loading…
Reference in New Issue
Block a user