application/js/views/box_view.js
// console.log('Loading BoxView...')
Spontaneous.Views.BoxView = (function($, S) {
'use strict';
var dom = S.Dom;
var BoxView = new JS.Class(Spontaneous.Views.View, {
include: Spontaneous.Properties,
initialize: function(box, dom_container) {
this.callSuper(box);
this.box = box;
this.dom_container = dom_container;
this.box.bind('entry_added', this.insert_entry.bind(this));
this.box.bind('entry_removed', this.remove_entry.bind(this));
this._isAttached = false;
},
name: function() {
return this.box.name();
},
level: function() {
return this.box.level();
},
schema_id: function() {
return this.box.schema_id();
},
activate: function() {
$('> .slot-content', this.dom_container).hide();
this.panel().show();
this.attachView();
},
mouseover: function() {
if (this.fields_preview) {
this.fields_preview.addClass('hover');
}
},
mouseout: function() {
if (this.fields_preview) {
this.fields_preview.removeClass('hover');
}
},
panel: function() {
if (!this._panel) {
var box = this.box;
var panel = dom.div('.slot-content');
panel.addClass('empty');
if (box.hasComment()) {
var comment = dom.div('.box-comment');
comment.html(box.commentHTML());
panel.append(comment);
}
if (box.has_fields()) {
var w = dom.div('.box-fields');
var fields = new Spontaneous.FieldPreview(this, '');
this._subviews.push(fields);
var fields_preview = fields.panel();
fields_preview.prepend(dom.div('.overlay'));
var preview_area = this.create_edit_wrapper(fields_preview);
w.append(preview_area);
panel.append(w);
this.fields_preview = fields_preview;
}
var firstPosition = function() { return 0; };
panel.append(this.add_allowed_types_bar('top', firstPosition));
var entries = dom.div('.slot-entries');
panel.append(entries);
this.dom_container.append(panel);
var instructions = dom.div('.slot-instructions').text('Add items using the buttons above');
entries.append(instructions);
if (this._isAttached) {
this.appendEntries(entries);
}
entries.sortable({
items:'> .'+this.entry_class(),
// handle: '.title-bar',
axis:'y',
distance: 5,
tolerance: 'pointer',
helper: 'clone',
// tolerance: 'intersect',
scrollSpeed: 40,
containment: 'parent',
cursor: 'move',
stop: function(event, ui) {
this.re_sort(ui.item);
}.bind(this)
});
panel.hide();
this._panel = panel;
this._entry_container = entries;
// this._bottom_add_bar = _bottom_add_bar;
}
this.check_if_empty();
return this._panel;
},
// relies on this view being attached to the dom
// fills the box until all the entries have been added or the last entry
// is at the bottom of the screen, whichever comes first.
appendEntries: function(entries) {
// only use dynamic loading for page boxes
var entry_total = this.entries().length, attached = 0;
if (this.level() === 0) {
var availableHeight = S.ContentArea.height() - entries.position().top;
for (var i = 0, ee = this.entries(), ii = entry_total;i < ii; i++) {
var entry = ee[i];
entries.append(this.claim_entry(entry));
attached++;
var contentHeight = entries.height(), gap = availableHeight - contentHeight;
if (gap < 0) { // wait until there's an overlap so we see a scrollbar
break;
}
}
} else {
for (var i = 0, ee = this.entries(), ii = entry_total;i < ii; i++) {
entries.append(this.claim_entry(ee[i]));
attached++;
}
}
if (attached < entry_total) {
var scrollLoad = function(view, loadedCount, entries, container) {
var position = loadedCount, increment = 3, total = entries.length;
return function() {
if (position >= total) { return; }
var availableHeight = S.ContentArea.height() - container.position().top;
var added = 0;
for (var i = position, ii = total; i < ii; i++) {
container.append(view.claim_entry(entries[i]));
added++;
var contentHeight = container.height(), gap = availableHeight - contentHeight;
if (gap < 0) { // wait until there's an overlap so we see a scrollbar
break;
}
}
position += added;
if (position >= total) {
container.addClass('entries-loaded');
}
};
}(this, attached, this.entries(), entries);
this.watchOther(S.ContentArea, 'scroll_bottom', scrollLoad);
} else {
entries.addClass('entries-loaded');
}
},
attachView: function() {
if (this._isAttached) {
return;
}
this._isAttached = true;
var entries = this._entry_container;
if (!entries) { return; }
this.appendEntries(entries);
},
check_if_empty: function() {
var _view = this, _panel = this._panel;
if (_view.box.entries().length === 0) {
_panel.addClass('empty');
// _view._bottom_add_bar.velocity('fadeOut', $.fn.appear.height_change_duration/2, function() {
// })
} else {
_panel.removeClass('empty');
// _view._bottom_add_bar.velocity('fadeIn', function() {
// })
}
},
add_allowed_types_bar: function(position, insert_at) {
var allowed = this.box.allowed_types();
if (allowed.length === 0) { return ''; }
var _box = this
, allowed_bar = dom.div('.slot-addable')
, inner = dom.div('.addable-inner')
, dropper = allowed_bar
, drop = function(event) {
dropper.removeClass('drop-active').addClass('uploading');
// var progress_outer = $(dom.div, {'class':'drop-upload-outer'});
// var progress_inner = $(dom.div, {'class':'drop-upload-inner'}).css('width', 0);
// progress_outer.append(progress_inner);
// dropper.append(progress_outer);
// this.progress_bar = progress_inner;
event.stopPropagation();
event.preventDefault();
var files = event.dataTransfer.files;
if (files.length > 0) {
S.UploadManager.wrap(this, files, insert_at());
}
return false;
}.bind(this)
, drag_enter = function(event) {
// var files = event.originalEvent.dataTransfer.files;
$(this).addClass('drop-active');
event.stopPropagation();
event.preventDefault();
return false;
}.bind(dropper)
, drag_over = function(event) {
event.stopPropagation();
event.preventDefault();
return false;
}.bind(dropper)
, drag_leave = function(event) {
$(this).removeClass('drop-active');
event.stopPropagation();
event.preventDefault();
return false;
}.bind(dropper);
allowed_bar.addClass(position);
dropper.get(0).addEventListener('drop', drop, true);
dropper.bind('dragenter', drag_enter).bind('dragover', drag_over).bind('dragleave', drag_leave);
$.each(allowed, function(i, allow) {
var type = allow.type, as = allow.as || type.title;
var a = dom.a().append(dom.span().text(as)), add_allowed;
if (type.is_alias()) {
a.addClass('alias');
add_allowed = function(type) {
var d = new Spontaneous.AddAliasDialogue(_box, type, insert_at());
d.open();
}.bind(_box, type);
} else {
add_allowed = function(type) {
this.add_content(type, insert_at());
}.bind(_box, type);
}
a.click(add_allowed);
inner.append(a);
});
allowed_bar.data('allowed-count', allowed.length);
allowed_bar.append(inner, dom.span('.down'));
return allowed_bar;
},
re_sort: function(item) {
var entries = this.entries(), order = this._entry_container.sortable('toArray'), css_id = item.attr('id'), new_position = 0;
for (var i = 0, ii = order.length; i < ii; i++) {
if (order[i] === css_id) { new_position = i; break; }
}
var id = css_id.split('-')[1], entry, old_position = 0;
for (i = 0, ii = entries.length; i < ii; i++) {
if (entries[i].id() == id) {
old_position = i;
entry = entries[i];
break;
}
}
// move entry inside the array so that we can reliably find its position
entries.splice(old_position, 1);
entries.splice(new_position, 0, entry);
entry.reposition(new_position, function(entry) {
this.sorted(entry);
}.bind(this));
},
sorted: function(entry) {
},
upload_complete: function(values) {
this.box.entry_added(values);
},
upload_progress: function(position, total) {
},
entries: function() {
var entries = [];
for (var i = 0, ee = this.box.entries(), ii = ee.length;i < ii; i++) {
var entry = ee[i];
entries.push(this.view_for_entry(entry));
}
return entries;
}.cache(),
view_for_entry: function(entry) {
var view_class = S.Views.PieceView, view, panel;
if (entry.is_page()) {
view_class = S.Views.PagePieceView;
}
view = new view_class(entry, this); // jshint ignore:line
return view;
},
claim_entry: function(entry) {
this._subviews.push(entry);
var div = entry.panel();
entry.bind('removed', this.entry_removed.bind(this));
return div.attr('id', this.entry_id(entry)).addClass(this.entry_class());
},
entry_id: function(entry) {
return 'entry-' + entry.content.id();
},
entry_class: function() {
return 'container-'+this.box.schema_id();
},
save_path: function() {
return ['/content', this.id()].join('/');
},
add_content: function(content_type, position) {
this.box.add_entry(content_type, position);
},
add_alias: function(target_ids, type, position) {
this.box.add_alias(target_ids, type, position);
},
insert_entry: function(entry, position) {
this.trigger('entry_added', entry, position);
var entries = this.entries()
, w = this.entry_wrappers()
, e = this.view_for_entry(entry)
, h = this.claim_entry(e)
, view = this;
if (position === -1) {
entries.push(e);
} else {
entries.splice(position, 0, e);
}
if (position === -1 || w.length === 0) {
this._entry_container.append(h);
} else if (position === 0) {
this._entry_container.prepend(h);
} else {
this.entry_wrappers().slice(position-1, position).after(h);
}
if (position === -1) {
S.ContentArea.scroll_to_bottom($.fn.appear.height_change_duration);
}
view.check_if_empty();
h.hide().appear(function() {
if (e.content.has_fields()) {
e.edit();
}
});
},
remove_entry: function(entry) {
},
entry_removed: function(entry) {
var entries = this.entries();
for (var i = 0, ii = entries.length; i < ii; i++) {
if (entries[i] === entry) {
entries.splice(i, 1);
}
}
this.check_if_empty();
},
entry_wrappers: function() {
return this._entry_container.find('> .'+this.entry_class());
},
currentEntryPosition: function(entry) {
for (var i = 0, entries = this.entries(), ii = entries.length; i < ii; i++) {
if (entries[i] === entry) {
return i;
}
}
return false;
},
show_add_after: function(entry, entry_spacer) {
var bar, entryPosition = this.currentEntryPosition.bind(this);
var position = function() {
return entryPosition(entry) + 1;
};
bar = this.add_allowed_types_bar('floating', position);
if (bar && bar.data('allowed-count') > 0) {
entry_spacer.addClass('add-entry').append(bar.show());
if (!entry_spacer.data('auto-height')) {
entry_spacer.data('auto-height', entry_spacer.height());
}
var newHeight = bar.find('.addable-inner').outerHeight() + 11, currentHeight = entry_spacer.outerHeight();
newHeight = Math.max(newHeight, currentHeight);
entry_spacer.velocity({height:newHeight}, 200);
}
},
hide_add_after: function(entry, entry_spacer) {
if (entry_spacer.data('auto-height')) {
entry_spacer.empty();
entry_spacer.removeClass('add-entry').velocity({height: entry_spacer.data('auto-height')}, 200);
}
}
});
return BoxView;
})(jQuery, Spontaneous);