Created
November 8, 2010 15:43
-
-
Save jaredhoyt/667826 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class FileTreeHelper extends AppHelper { | |
var $elements = array( | |
'tree' => '<ul class="tree">%s</ul>', | |
'folder' => '<li id="tree-folder_%d" class="folder open"> | |
<div class="folder-name-wrap"><span class="icon">Sort</span><span class="folder-name">%s</span></div> | |
<div class="folder-contents"><ul class="folders">%s</ul><ul class="files">%s</ul></div></li>', | |
'file' => '<li id="tree-file_%d" class="file"><span class="icon">Sort</span><span class="file-name">%s</span></li>' | |
); | |
var $settings = array(); | |
public function generate($folders, $settings = array()) { | |
if (!is_array($folders)) { | |
return false; | |
} | |
$this->settings = array_merge( | |
array( | |
'folders' => 'Folder', | |
'files' => 'File' | |
), $settings | |
); | |
$out = ''; | |
foreach ($folders as $folder) { | |
$out .= $this->parseFolder($folder); | |
} | |
return sprintf($this->elements['tree'], $out); | |
} | |
private function parseFolder($folder) { | |
$folders = ''; | |
if (!empty($folder['children'])) { | |
foreach ($folder['children'] as $subfolder) { | |
$folders .= $this->parseFolder($subfolder); | |
} | |
} | |
$files = ''; | |
if (!empty($folder[$this->settings['files']])) { | |
foreach ($folder[$this->settings['files']] as $file) { | |
$files .= sprintf($this->elements['file'], $file['id'], $file['name']); | |
} | |
} | |
return sprintf($this->elements['folder'], $folder[$this->settings['folders']]['id'], $folder[$this->settings['folders']]['name'], $folders, $files); | |
} | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var productTree = { | |
// Check for modified items before proceeding | |
confirmChanges : function(){ | |
if ($('#active-item').find('input.modified, textarea.modified').length) { | |
return confirm('You have unsaved changes. Are you sure you want to continue?'); | |
} | |
return true; | |
}, | |
// Strip non-numeric characters from id | |
extractId : function(element){ | |
return $(element).attr('id').replace(/[^0-9]*/, ''); | |
}, | |
// Focus (and select) active item name input | |
focusActiveItem : function(select){ | |
$('#active-item input.name')[0].focus(); | |
if (select === true) { | |
$('#active-item input.name')[0].select(); | |
} | |
}, | |
// Load item for editing when selected | |
loadItem : function(url, data, callback){ | |
// Center ajax loader | |
$('#active-item div.content-wrap').addClass('loading'); | |
$('#active-item div.ajax-loader div.message').css({ | |
left : $('#active-item div.ajax-loader').width()/2 - 77, | |
top : $('#active-item div.ajax-loader').height()/2 - 29 | |
}); | |
if (typeof data == 'function') { | |
callback = data; | |
data = new Object(); | |
} | |
$('#active-item div.content').load(url, data, function(){ | |
$('#active-item div.content-wrap').removeClass('loading'); | |
callback(); | |
}); | |
}, | |
// Save folder order below node | |
saveFolderOrder : function(node){ | |
var folders = new Object(); | |
var instance = this; | |
$(node).children('div.folder-contents').children('ul.folders').children().each(function(index){ | |
folders[index] = { | |
ProductFolder: { | |
id: instance.extractId(this), | |
sort: index | |
} | |
} | |
}); | |
$.post('/admin/product_folders/reorder/' + productTree.extractId(node), { data : folders }); | |
}, | |
// Save folder order below node | |
saveFileOrder : function(node){ | |
var files = new Object(); | |
var instance = this; | |
$(node).children().each(function(index){ | |
files[index] = { | |
Product: { | |
id: instance.extractId(this), | |
sort: index | |
} | |
} | |
}); | |
$.post('/admin/products/reorder', { data : files }); | |
}, | |
// Load edit view into active item | |
selectItem : function(item, callback) { | |
if (!this.confirmChanges() || $(item).parent().hasClass('ui-prevent-select')) { | |
$(item).parent().removeClass('ui-prevent-select'); | |
return false; | |
} | |
$('ul.tree .selected').removeClass('selected'); | |
$('#product-tree a.create-product').addClass('disabled'); | |
if ($(item).length) { | |
$(item).addClass('selected'); | |
$('#product-tree a.create-product').removeClass('disabled'); | |
callback = callback || this.focusActiveItem; | |
if ($(item).hasClass('file')) { | |
this.loadItem('/admin/products/edit/' + this.extractId(item), callback); | |
$(item).parents('li.folder').addClass('open'); | |
} else { | |
this.loadItem('/admin/product_folders/edit/' + this.extractId($(item).parent()), callback); | |
} | |
} | |
} | |
}; | |
jQuery(function(){ | |
// Filter : type | |
$('#FilterType').change(function(){ | |
window.location = '/admin/products/tree/' + $(this).val(); | |
}); | |
// Filter : autocomplete | |
$('#FilterSearch').autocomplete({ | |
source: function(request, response) { | |
$.ajax({ | |
url : '/admin/products/search/' + productTree.extractId($('ul.tree li.folder:first')), | |
dataType : "json", | |
data : request, | |
success : function(data){ | |
if (data.length) { | |
response(data); | |
} else { | |
$('#FilterSearch').removeClass('searching'); | |
} | |
} | |
}); | |
}, | |
select: function(event, ui){ | |
productTree.selectItem($('#tree-file_' + ui.item.val)); | |
}, | |
search: function(){ | |
$('#FilterSearch').addClass('searching'); | |
}, | |
close: function(){ | |
$('#FilterSearch').removeClass('searching').val(''); | |
} | |
}); | |
// Sorting folders and files | |
$('ul.tree').delegate('div.folder-contents', 'mouseover', function(){ | |
$(this).children('ul.folders').sortable({ | |
axis: "y", | |
handle: "> div.folder-name-wrap span.icon", | |
items: "> li.folder", | |
start: function(event, ui){ | |
$(ui.item).addClass('ui-prevent-select'); | |
}, | |
update: function(event, ui){ | |
productTree.saveFolderOrder($(ui.item).parents('li.folder:first')); | |
} | |
}) | |
$(this).children('ul.files').sortable({ | |
axis: "y", | |
handle: "> span.icon", | |
items: "> li.file", | |
start: function(event, ui){ | |
$(ui.item).addClass('ui-prevent-select'); | |
}, | |
update: function(event, ui){ | |
productTree.saveFileOrder($(ui.item).parent()); | |
} | |
}); | |
}); | |
// Dragging folders and files | |
$('ul.tree ul.folders').delegate('li.folder', 'mouseover', function(event){ | |
$(this).draggable({ | |
handle: "> div.folder-name-wrap span.folder-name", | |
revert: true, | |
revertDuration: 150, | |
scope: "tree", | |
zIndex: 2 | |
}); | |
}); | |
// Dropping items onto folders | |
$('ul.tree').delegate('div.folder-contents', 'mouseover', function(){ | |
$('div.folder-name-wrap').droppable({ | |
greedy: true, | |
scope: "tree", | |
tolerance: "pointer", | |
drop: function(event, ui){ | |
var element = $(ui.helper); | |
var target = $(event.target); | |
if (target.hasClass('ui-folder-hover')) { | |
if (element.hasClass('folder')) { | |
element.appendTo(target.next('div.folder-contents').children('ul.folders')); | |
} else { | |
element.appendTo(target.next('div.folder-contents').children('ul.files')); | |
} | |
target.removeClass('ui-folder-hover').parent().addClass('open'); | |
var targetId = productTree.extractId(target.parent()); | |
if (element.hasClass('file')) { | |
$.post('/admin/products/edit/' + productTree.extractId(element), { data : { Product : { product_folder_id : targetId }}}); | |
} else { | |
$.post('/admin/product_folders/edit/' + productTree.extractId(element), { data : { ProductFolder : { parent_id : targetId }}}); | |
} | |
} | |
}, | |
over: function(event, ui){ | |
var element = $(ui.helper); | |
var target = $(event.target); | |
var targetDepth = target.parents('div.folder-contents').length; | |
var validTarget = false; | |
if (element.hasClass('file') && targetDepth > 0) { | |
validTarget = true; | |
} else if (element.hasClass('folder')) { | |
validTarget = (targetDepth == 0 || (targetDepth == 1 && element.find('div.folder-contents').length == 1)); | |
} | |
if (validTarget) { | |
target.addClass('ui-folder-hover'); | |
} | |
}, | |
out: function(event, ui){ | |
$(event.target).removeClass('ui-folder-hover'); | |
} | |
}); | |
}); | |
// Toggling folders | |
$('ul.tree').delegate('div.folder-name-wrap', 'dblclick', function(){ | |
if ($(this).parents('div.folder-contents').length) { | |
$(this).parent().toggleClass('open'); | |
} | |
}).disableSelection(); | |
// Selecting a tree item | |
$('div.folder-contents').delegate('div.folder-name-wrap, li.file', 'click', function(){ | |
productTree.selectItem(this); | |
return false; | |
}).disableSelection(); | |
// Editing items with save/cancel buttons | |
$('#active-item').delegate('div.submit a', 'click', function(event){ | |
if ($(this).hasClass('save')) { | |
var name = $(this).parents('form:first').find('input.name').val(); | |
var selector = $('ul.tree .selected').hasClass('file') ? 'file-name' : 'folder-name'; | |
if ($('#ProductFolderImage').val()) { | |
$('#ItemEditForm').attr('target', 'image-submit')[0].submit(); | |
} | |
productTree.loadItem($('#ItemEditForm').attr('action'), $('#ItemEditForm').serializeArray(), function(){ | |
if ($('#active-item div.content').find('p.success').length) { | |
$('ul.tree .selected span.' + selector + ':first').text(name); | |
productTree.selectItem(null); | |
} | |
}); | |
} else if ($(this).hasClass('cancel')) { | |
productTree.loadItem('/admin/products #active-item div.content > *', function(){ | |
productTree.selectItem(null); | |
}); | |
} else if ($(this).hasClass('delete')) { | |
if ($('ul.tree .selected').hasClass('file')) { | |
var message = 'Are you sure you want to delete this product?'; | |
var item = $('ul.tree .selected'); | |
} else { | |
var message = 'Are you sure you want to delete this folder and all of its contents?'; | |
var item = $('ul.tree .selected').parent(); | |
} | |
if (confirm(message)) { | |
productTree.loadItem(this.href, function(){ | |
item.fadeOut(function(){ | |
$(this).remove(); | |
productTree.selectItem(null); | |
}); | |
}); | |
} | |
} | |
event.preventDefault(); | |
}).delegate('input, textarea', 'change', function(){ | |
$(this).addClass('modified'); | |
}).delegate('form', 'submit', function(event){ | |
$(this).find('a.save').click(); | |
event.preventDefault(); | |
}).delegate('div.image-options a.view-image', 'click', function(event){ | |
magicbox.load(this.href, { title: 'Product Folder Image' }); | |
event.preventDefault(); | |
}).delegate('div.image-options a.delete-image', 'click', function(event){ | |
if (confirm('Are you sure you want to delete this image?')) { | |
productTree.loadItem(this.href); | |
} | |
event.preventDefault(); | |
}); | |
// Create new folder | |
$('a.create-folder').click(function(event){ | |
var parent = $('ul.tree li.folder:first'); | |
$.get('/admin/product_folders/create/' + productTree.extractId(parent), function(folder){ | |
productTree.selectItem(parent.children('div.folder-contents').children('ul.folders').prepend(folder).find('div.folder-name-wrap:first'), function(){ | |
productTree.saveFolderOrder(parent); | |
productTree.focusActiveItem(true); | |
}); | |
}); | |
event.preventDefault(); | |
}); | |
// Create new product | |
$('a.create-product').click(function(event){ | |
if (!$(this).hasClass('disabled')) { | |
var parent = $('ul.tree .selected').parents('li.folder:first'); | |
$.get('/admin/products/create/' + productTree.extractId(parent), function(product){ | |
productTree.selectItem(parent.children('div.folder-contents').children('ul.files').append(product).find('li.file:last'), function(){ | |
productTree.saveFileOrder(parent.children('div.folder-contents').children('ul.files')); | |
productTree.focusActiveItem(true); | |
}); | |
}); | |
} | |
event.preventDefault(); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php echo $this->FileTree->generate($folders, array('folders' => 'ProductFolder', 'files' => 'Product')); ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment