mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
ENHANCEMENT Converted AssetAdmin and AssetTableField javascript to jquery-concrete
MINOR Moved AssetAdmin->movemarked() logic to AssetTableField git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@92829 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
1581d93df6
commit
c467c926fd
@ -38,15 +38,10 @@ class AssetAdmin extends LeftAndMain {
|
||||
static $allowed_actions = array(
|
||||
'doAdd',
|
||||
'AddForm',
|
||||
'deletemarked',
|
||||
'DeleteItemsForm',
|
||||
'deleteUnusedThumbnails',
|
||||
'doUpload',
|
||||
'getfile',
|
||||
'getsubtree',
|
||||
'movemarked',
|
||||
'save',
|
||||
'savefile',
|
||||
'uploadiframe',
|
||||
'UploadForm',
|
||||
'deleteUnusedThumbnails' => 'ADMIN',
|
||||
@ -325,73 +320,6 @@ HTML;
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the "move marked" action.
|
||||
* Called and returns in same way as 'save' function
|
||||
*/
|
||||
public function movemarked($urlParams, $form) {
|
||||
if($_REQUEST['DestFolderID'] && (is_numeric($_REQUEST['DestFolderID']) || ($_REQUEST['DestFolderID']) == 'root')) {
|
||||
$destFolderID = ($_REQUEST['DestFolderID'] == 'root') ? 0 : $_REQUEST['DestFolderID'];
|
||||
$fileList = "'" . ereg_replace(' *, *',"','",trim(addslashes($_REQUEST['FileIDs']))) . "'";
|
||||
$numFiles = 0;
|
||||
|
||||
if($fileList != "''") {
|
||||
$files = DataObject::get("File", "\"File\".\"ID\" IN ($fileList)");
|
||||
if($files) {
|
||||
foreach($files as $file) {
|
||||
if($file instanceof Image) {
|
||||
$file->deleteFormattedImages();
|
||||
}
|
||||
$file->ParentID = $destFolderID;
|
||||
$file->write();
|
||||
$numFiles++;
|
||||
}
|
||||
} else {
|
||||
user_error("No files in $fileList could be found!", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
$message = sprintf(_t('AssetAdmin.MOVEDX','Moved %s files'),$numFiles);
|
||||
|
||||
FormResponse::status_message($message, "good");
|
||||
FormResponse::add("$('Form_EditForm_Files').refresh();");
|
||||
|
||||
return FormResponse::respond();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content to be placed in Form_SubForm when editing a file.
|
||||
* Called using ajax.
|
||||
*/
|
||||
public function getfile() {
|
||||
SSViewer::setOption('rewriteHashlinks', false);
|
||||
|
||||
// bdc: only try to return something if user clicked on an object
|
||||
if (is_object($this->getSubForm($this->urlParams['ID']))) {
|
||||
return $this->getSubForm($this->urlParams['ID'])->formHtmlContent();
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action handler for the save button on the file subform.
|
||||
* Saves the file
|
||||
*/
|
||||
public function savefile($data, $form) {
|
||||
$record = DataObject::get_by_id("File", $data['ID']);
|
||||
$form->saveInto($record);
|
||||
$record->write();
|
||||
$title = Convert::raw2js($record->Title);
|
||||
$name = Convert::raw2js($record->Name);
|
||||
$saved = sprintf(_t('AssetAdmin.SAVEDFILE','Saved file %s'),"#$data[ID]");
|
||||
echo <<<JS
|
||||
statusMessage('$saved');
|
||||
$('record-$data[ID]').getElementsByTagName('td')[1].innerHTML = "$title";
|
||||
$('record-$data[ID]').getElementsByTagName('td')[2].innerHTML = "$name";
|
||||
JS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the entire site tree as a nested UL.
|
||||
* @return string HTML for site tree
|
||||
|
@ -225,21 +225,27 @@ class AssetTableField extends ComplexTableField {
|
||||
* @return string HTML for search form
|
||||
*/
|
||||
function SearchForm() {
|
||||
$searchFields = new FieldGroup(
|
||||
new TextField('FileSearch', _t('MemberTableField.SEARCH', 'Search'), $this->searchingFor),
|
||||
new HiddenField("ctf[ID]", '', $this->ID),
|
||||
new HiddenField('FileFieldName', '', $this->name)
|
||||
);
|
||||
|
||||
$actionFields = new LiteralField(
|
||||
'FileFilterButton',
|
||||
'<input type="submit" class="action" name="FileFilterButton" value="' . _t('MemberTableField.FILTER', 'Filter') . '" id="FileFilterButton"/>'
|
||||
);
|
||||
|
||||
$fieldContainer = new FieldGroup(
|
||||
$searchFields,
|
||||
$actionFields
|
||||
new FieldGroup(
|
||||
new TextField(
|
||||
'FileSearch',
|
||||
_t('MemberTableField.SEARCH', 'Search'),
|
||||
$this->searchingFor
|
||||
)
|
||||
),
|
||||
new FieldGroup(
|
||||
$btnFilter = new InlineFormAction(
|
||||
'FileFilterButton',
|
||||
_t('MemberTableField.FILTER', 'Filter')
|
||||
),
|
||||
$btnClear = new InlineFormAction(
|
||||
'FileFilterClearButton',
|
||||
_t('AssetTableField.CLEAR', 'Clear')
|
||||
)
|
||||
)
|
||||
);
|
||||
$btnFilter->includeDefaultJS(false);
|
||||
$btnClear->includeDefaultJS(false);
|
||||
|
||||
return $fieldContainer->FieldHolder();
|
||||
}
|
||||
@ -300,8 +306,39 @@ class AssetTableField extends ComplexTableField {
|
||||
$brokenPageList
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $response->output();
|
||||
public function movemarked($request) {
|
||||
$fileIDs = $request->requestVar($this->Name());
|
||||
$folderId = $request->requestVar('DestFolderID');
|
||||
$numFiles = 0;
|
||||
|
||||
if($folderId && (is_numeric($folderId) || ($folderId) == 'root')) {
|
||||
if($folderId == 'root') $folderId = 0;
|
||||
|
||||
if($fileIDs && count($fileIDs)) {
|
||||
$files = DataObject::get(
|
||||
"File",
|
||||
sprintf("\"File\".\"ID\" IN (%s)", Convert::raw2sql(implode(',', $fileIDs)))
|
||||
);
|
||||
if($files) {
|
||||
foreach($files as $file) {
|
||||
$file->ParentID = $folderId;
|
||||
$file->write();
|
||||
$numFiles++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response = $this->form->Controller()->getResponse();
|
||||
$response->addHeader(
|
||||
'X-Status',
|
||||
sprintf(
|
||||
sprintf(_t('AssetAdmin.MOVEDX','Moved %s files'),$numFiles),
|
||||
$numFiles
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,8 @@ ul.tree span.a {
|
||||
cursor: pointer;
|
||||
}
|
||||
.filefolderhover span.a,
|
||||
ul.tree span.a.over {
|
||||
ul.tree span.a.over,
|
||||
ul.tree .over > span.a {
|
||||
background-color: #FFFFBB !important;
|
||||
/* these push the highlight out to the left of the window */
|
||||
margin-left: -100px;
|
||||
|
@ -1,118 +1,76 @@
|
||||
// SubsDraggable adapted from http://dev.rubyonrails.org/ticket/5771
|
||||
(function($) {
|
||||
$.concrete('ss', function($){
|
||||
|
||||
// extentions for scriptaculous dragdrop.js
|
||||
Object.extend(Class, {
|
||||
superrise: function(obj, names){
|
||||
names.each( function(n){ obj['super_' + n] = obj[n] } )
|
||||
return obj;
|
||||
}
|
||||
})
|
||||
$('.AssetTableField.dragdrop').concrete({
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
$('#sitetree li').each(function() {
|
||||
$(this).droppable({
|
||||
greedy: true,
|
||||
hoverClass: 'over', // same hover effect as normal tree
|
||||
drop: function(e, ui) {self.drop(e, ui);}
|
||||
});
|
||||
});
|
||||
|
||||
// Draggable that allows substitution of draggable element
|
||||
var SubsDraggable = Class.create();
|
||||
|
||||
SubsDraggable.prototype = Object.extend({}, Draggable.prototype);
|
||||
Class.superrise(SubsDraggable.prototype, ['initialize', 'startDrag', 'finishDrag'])
|
||||
Object.extend( SubsDraggable.prototype , {
|
||||
initialize: function(event) {
|
||||
this.super_initialize.apply(this, arguments);
|
||||
if( typeof(this.options.dragelement) == 'undefined' ) this.options.dragelement = false;
|
||||
},
|
||||
startDrag: function(event) {
|
||||
if( this.options.dragelement ) {
|
||||
this._originalElement = this.element;
|
||||
// Get the id of the file being dragged
|
||||
var beingDraggedId = this.element.id.replace('drag-Files-','');
|
||||
this.element = this.options.dragelement(this.element);
|
||||
Position.absolutize(this.element);
|
||||
Position.clone(this._originalElement, this.element);
|
||||
// Add # files being moved message
|
||||
this.element.className = 'dragfile DraggedHandle';
|
||||
// We are at least moving the 1 file being dragged
|
||||
var numMoved = 1;
|
||||
var i, checkboxes = $('Form_EditForm').elements['Files[]'];
|
||||
if(!checkboxes) checkboxes = [];
|
||||
if(!checkboxes.length) checkboxes = [ checkboxes ];
|
||||
for(i=0;i<checkboxes.length;i++) {
|
||||
// Total up the other files that are checked
|
||||
if(checkboxes[i].checked && checkboxes[i].value != beingDraggedId) {
|
||||
numMoved++;
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* Take selected files and move them to a folder target in the tree.
|
||||
*/
|
||||
drop: function(e, ui) {
|
||||
var self = this;
|
||||
if(e.target.id.match(/-([^-]+)$/)) {
|
||||
var folderId = RegExp.$1;
|
||||
$.post(
|
||||
this.attr('href') + '/movemarked',
|
||||
this.parents('form').serialize() + '&DestFolderID=' + folderId,
|
||||
function(data, status) {
|
||||
self.refresh();
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
numFilesIndicator = document.createElement('span');
|
||||
numFilesIndicator.innerHTML = 'Moving ' + numMoved + ' files';
|
||||
numFilesIndicator.className = 'NumFilesIndicator';
|
||||
this.element.appendChild(numFilesIndicator);
|
||||
}
|
||||
this.super_startDrag(event);
|
||||
},
|
||||
finishDrag: function(event, success) {
|
||||
this.super_finishDrag(event, success);
|
||||
|
||||
if(this.options.dragelement){
|
||||
Element.remove(this.element);
|
||||
this.element = this._originalElement;
|
||||
this._originalElement = null;
|
||||
}
|
||||
}
|
||||
})
|
||||
// gets element that should be dragged instead of original element
|
||||
// returned element should be added to DOM tree, and will be deleted by dragdrop library
|
||||
function getDragElement(element){
|
||||
var el = element.cloneNode(true);
|
||||
el.id = '';
|
||||
document.body.appendChild(el);
|
||||
return el;
|
||||
}
|
||||
|
||||
// Set up DRAG handle
|
||||
DragFileItem = Class.create();
|
||||
DragFileItem.prototype = {
|
||||
initialize: function() {
|
||||
if (this.id)
|
||||
{
|
||||
this.draggable = new SubsDraggable(this.id, {revert:true,ghosting:false,dragelement:getDragElement});
|
||||
}
|
||||
},
|
||||
destroy: function() {
|
||||
this.draggable = null;
|
||||
}
|
||||
}
|
||||
DragFileItem.applyTo('#Form_EditForm_Files tr td.dragfile');
|
||||
|
||||
// Set up folder drop target
|
||||
DropFileItem = Class.create();
|
||||
DropFileItem.prototype = {
|
||||
initialize: function() {
|
||||
// Get this.recordID from the last "-" separated chunk of the id HTML attribute
|
||||
// eg: <li id="treenode-6"> would give a recordID of 6
|
||||
if(this.id && this.id.match(/-([^-]+)$/))
|
||||
this.recordID = RegExp.$1;
|
||||
this.droppable = Droppables.add(this.id, {accept:'dragfile', hoverclass:'filefolderhover',
|
||||
onDrop:function(droppedElement) {
|
||||
// Get this.recordID from the last "-" separated chunk of the id HTML attribute
|
||||
// eg: <li id="treenode-6"> would give a recordID of 6
|
||||
if(this.element.id && this.element.id.match(/-([^-]+)$/))
|
||||
this.recordID = RegExp.$1;
|
||||
$('Form_EditForm').elements['DestFolderID'].value = this.recordID;
|
||||
|
||||
// Add the dropped file to the list of files to move
|
||||
var list = droppedElement.getElementsByTagName('img')[0].id.replace('drag-img-Files-','');
|
||||
var i, checkboxes = $('Form_EditForm').elements['Files[]'];
|
||||
if(!checkboxes) checkboxes = [];
|
||||
if(!checkboxes.length) checkboxes = [ checkboxes ];
|
||||
// Add each checked file to the list of ones to move
|
||||
for(i=0;i<checkboxes.length;i++) {
|
||||
if(checkboxes[i].checked) list += (list?',':'') + checkboxes[i].value;
|
||||
}
|
||||
$('Form_EditForm_FileIDs').value = list;
|
||||
$('Form_EditForm').save(false, null, 'movemarked')
|
||||
},
|
||||
/**
|
||||
* Get the IDs of all selected files in the table.
|
||||
* Used for drag'n'drop.
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
getSelected: function() {
|
||||
return this.find(':input[name=Files\[\]]:checked').map(function() {
|
||||
return $(this).val();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
destroy: function() {
|
||||
this.droppable = null;
|
||||
this.recordID = null;
|
||||
}
|
||||
}
|
||||
DropFileItem.applyTo('#sitetree li');
|
||||
|
||||
$('.AssetTableField .dragfile').concrete({
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
var container = this.parents('.AssetTableField');
|
||||
|
||||
this.draggable({
|
||||
zIndex: 4000,
|
||||
//stack: {group: '.ui-layout-west'},
|
||||
appendTo: 'body',
|
||||
helper: function() {
|
||||
return $(
|
||||
'<div class="NumFilesIndicator">' +
|
||||
ss.i18n.sprintf(ss.i18n._t('AssetTableField.MOVING'),container.getSelected().length) +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* Automatically select the checkbox in the same table row
|
||||
* to signify that this element is moved, and hint that
|
||||
* all checkboxed elements will be moved along with it.
|
||||
*/
|
||||
onmousedown: function(e) {
|
||||
this.siblings('.markingcheckbox').find(':input').attr('checked', 'checked');
|
||||
}
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
@ -1,6 +1,51 @@
|
||||
(function($) {
|
||||
$.concrete('ss', function($){
|
||||
|
||||
$('.AssetTableField').concrete({
|
||||
onmatch: function() {
|
||||
var self = this;
|
||||
|
||||
// search button
|
||||
this.find('input#FileFilterButton').click(function(e) {
|
||||
var btn = $(this);
|
||||
$(this).addClass('loading');
|
||||
self.refresh(function() {btn.removeClass('loading');});
|
||||
return false;
|
||||
});
|
||||
|
||||
// clear button
|
||||
this.find('input#FileFilterClearButton').click(function(e) {
|
||||
self.find('input#FileSearch').val('');
|
||||
self.find('input#FileFilterButton').click();
|
||||
return false;
|
||||
});
|
||||
|
||||
// search field
|
||||
this.find('input#FileSearch').keypress(function(e) {
|
||||
if(e.keyCode == $.ui.keyCode.ENTER) {
|
||||
self.find('input#FileFilterButton').click();
|
||||
}
|
||||
});
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
refresh: function(callback) {
|
||||
var self = this;
|
||||
this.load(
|
||||
this.attr('href'),
|
||||
this.find(':input').serialize(),
|
||||
function(response, status, xmlhttp) {
|
||||
Behaviour.apply(self[0], true);
|
||||
if(callback) callback.apply(arguments);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Checkboxes used to batch delete files
|
||||
*/
|
||||
$('.AssetTableField :checkbox').concrete({
|
||||
onchange: function() {
|
||||
var container = this.parents('.AssetTableField');
|
||||
@ -33,7 +78,7 @@
|
||||
this.parents('form').serialize(),
|
||||
function(data, status) {
|
||||
self.removeClass('loading');
|
||||
container[0].refresh();
|
||||
container.refresh();
|
||||
}
|
||||
);
|
||||
return false;
|
||||
@ -41,102 +86,3 @@
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
||||
|
||||
AssetTableField = Class.create();
|
||||
AssetTableField.applyTo('#Form_EditForm_Files');
|
||||
AssetTableField.prototype = {
|
||||
|
||||
initialize: function() {
|
||||
Behaviour.register({
|
||||
'#Form_EditForm div.FileFilter input' : {
|
||||
onkeypress : this.prepareSearch.bind(this)
|
||||
},
|
||||
|
||||
'#Form_EditForm' : {
|
||||
changeDetection_fieldsToIgnore : {
|
||||
'ctf[start]' : true,
|
||||
'ctf[ID]' : true,
|
||||
'FileFilterButton' : true,
|
||||
'FileFieldName' : true,
|
||||
'FileSearch' : true,
|
||||
'Files[]' : true
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// prevent submission of wrong form-button (FileFilterButton)
|
||||
prepareSearch: function(e) {
|
||||
// IE6 doesnt send an event-object with onkeypress
|
||||
var event = (e) ? e : window.event;
|
||||
var keyCode = (event.keyCode) ? event.keyCode : event.which;
|
||||
|
||||
if(keyCode == Event.KEY_RETURN) {
|
||||
var el = Event.element(event);
|
||||
$('FileFilterButton').onclick(event);
|
||||
Event.stop(event);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileFilterButton = Class.create();
|
||||
FileFilterButton.applyTo('#FileFilterButton');
|
||||
FileFilterButton.prototype = {
|
||||
initialize: function() {
|
||||
this.inputFields = new Array();
|
||||
|
||||
var childNodes = this.parentNode.parentNode.getElementsByTagName('input');
|
||||
|
||||
for( var index = 0; index < childNodes.length; index++ ) {
|
||||
if( childNodes[index].tagName ) {
|
||||
childNodes[index].resetChanged = function() { return false; }
|
||||
childNodes[index].isChanged = function() { return false; }
|
||||
this.inputFields.push( childNodes[index] );
|
||||
}
|
||||
}
|
||||
|
||||
childNodes = this.parentNode.getElementsByTagName('select');
|
||||
|
||||
for( var index = 0; index < childNodes.length; index++ ) {
|
||||
if( childNodes[index].tagName ) {
|
||||
childNodes[index].resetChanged = function() { return false; }
|
||||
childNodes[index].field_changed = function() { return false; }
|
||||
this.inputFields.push( childNodes[index] );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isChanged: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
onclick: function(e) {
|
||||
if(!$('ctf-ID') || !$('FileFieldName')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var form = Event.findElement(e, 'form');
|
||||
var fieldName = $('FileFieldName').value;
|
||||
|
||||
// build url
|
||||
var updateURL = form.action + '/field/' + fieldName + '?';
|
||||
for(var index = 0; index < this.inputFields.length; index++) {
|
||||
if(this.inputFields[index].tagName) {
|
||||
updateURL += '&' + this.inputFields[index].name + '=' + encodeURIComponent(this.inputFields[index].value);
|
||||
}
|
||||
}
|
||||
updateURL += ($('SecurityID') ? '&SecurityID=' + $('SecurityID').value : '');
|
||||
|
||||
// update the field
|
||||
var field = form.getElementsByClassName('AssetTableField')[0];
|
||||
field.setAttribute('href', updateURL);
|
||||
field.refresh();
|
||||
} catch(er) {
|
||||
errorMessage('Error searching');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
|
||||
'CMSMAIN.ALERTCLASSNAME': 'The page type will be updated after the page is saved',
|
||||
'CMSMAIN.URLSEGMENTVALIDATION': 'URLs can only be made up of letters, digits and hyphens.',
|
||||
'AssetAdmin.BATCHACTIONSDELETECONFIRM': "Do you really want to delete %s folders?",
|
||||
'AssetTableField.REALLYDELETE': 'Do you really want to delete the marked files?'
|
||||
'AssetTableField.REALLYDELETE': 'Do you really want to delete the marked files?',
|
||||
'AssetTableField.MOVING': 'Moving %s file(s)'
|
||||
});
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<div id="$id" class="$CSSClasses $extraClass field" href="$CurrentLink">
|
||||
<div id="$id" class="$CSSClasses $extraClass field dragdrop" href="$CurrentLink">
|
||||
<div class="FileFilter filterBox">
|
||||
$SearchForm
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user