mirror of
https://github.com/flarum/core.git
synced 2025-08-11 19:04:29 +02:00
Rejigging templates for redesign.
- Componentize more stuff, heading in the direction of Ember 2.0 - Start CSS from scratch - Everything is broken atm!
This commit is contained in:
132
ember/app/components/discussion-item.js
Normal file
132
ember/app/components/discussion-item.js
Normal file
@@ -0,0 +1,132 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
// A discussion 'item' represents one item in the post stream. In other words, a
|
||||
// single item may represent a single post, or it may represent a gap of many
|
||||
// posts which have not been loaded.
|
||||
|
||||
export default Ember.View.extend({
|
||||
classNames: ['item'],
|
||||
classNameBindings: ['item.gap:gap', 'loading', 'direction'],
|
||||
attributeBindings: [
|
||||
'start:data-start',
|
||||
'end:data-end',
|
||||
'time:data-time',
|
||||
'number:data-number'
|
||||
],
|
||||
|
||||
start: function() {
|
||||
return this.get('item.indexStart');
|
||||
}.property('item.indexStart'),
|
||||
|
||||
end: function() {
|
||||
return this.get('item.indexEnd');
|
||||
}.property('item.indexEnd'),
|
||||
|
||||
count: function() {
|
||||
return this.get('end') - this.get('start') + 1;
|
||||
}.property('start', 'end'),
|
||||
|
||||
time: function() {
|
||||
return this.get('item.post.time');
|
||||
}.property('item.post.time'),
|
||||
|
||||
number: function() {
|
||||
return this.get('item.post.number');
|
||||
}.property('item.post.number'),
|
||||
|
||||
loading: function() {
|
||||
return this.get('item.loading');
|
||||
}.property('item.loading'),
|
||||
|
||||
direction: function() {
|
||||
return this.get('item.direction');
|
||||
}.property(),
|
||||
|
||||
loadingChanged: function() {
|
||||
this.rerender();
|
||||
}.observes('loading'),
|
||||
|
||||
render: function(buffer) {
|
||||
if (! this.get('item.gap')) {
|
||||
return this._super(buffer);
|
||||
}
|
||||
|
||||
buffer.push('<span>');
|
||||
if (this.get('loading')) {
|
||||
buffer.push(' ');
|
||||
} else {
|
||||
buffer.push(this.get('count')+' more post'+(this.get('count') != 1 ? 's' : ''));
|
||||
}
|
||||
buffer.push('</span>');
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
if (! this.get('item.gap')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.get('loading')) {
|
||||
var view = this;
|
||||
Ember.run.scheduleOnce('afterRender', function() {
|
||||
view.$().spin('small');
|
||||
});
|
||||
} else {
|
||||
var self = this;
|
||||
this.$().hover(function(e) {
|
||||
var up = e.clientY > $(this).offset().top - $(document).scrollTop() + $(this).outerHeight(true) / 2;
|
||||
self.set('direction', up ? 'up' : 'down');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
load: function(relativeIndex) {
|
||||
// If this item is not a gap, or if we're already loading its posts,
|
||||
// then we don't need to do anything.
|
||||
if (! this.get('item.gap') || this.get('loading')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If new posts are being loaded in an upwards direction, then when they
|
||||
// are rendered, the rest of the posts will be pushed down the page.
|
||||
// However, we want to maintain the current scroll position relative to
|
||||
// the content after the gap. To do this, we need to find item directly
|
||||
// after the gap and use it as an anchor.
|
||||
if (this.get('direction') === 'up') {
|
||||
var anchor = this.$().nextAll('.item:first');
|
||||
|
||||
// Immediately after the posts have been loaded (but before they
|
||||
// have been rendered,) we want to grab the distance from the top of
|
||||
// the viewport to the top of the anchor element.
|
||||
this.get('controller.postStream').one('postsLoaded', function() {
|
||||
if (anchor.length) {
|
||||
var scrollOffset = anchor.offset().top - $(document).scrollTop();
|
||||
}
|
||||
|
||||
// After they have been rendered, we scroll back to a position
|
||||
// so that the distance from the top of the viewport to the top
|
||||
// of the anchor element is the same as before. If there is no
|
||||
// anchor (i.e. this gap is terminal,) then we'll scroll to the
|
||||
// bottom of the document.
|
||||
Ember.run.scheduleOnce('afterRender', function() {
|
||||
$('body').scrollTop(anchor.length
|
||||
? anchor.offset().top - scrollOffset
|
||||
: $('body').height());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Tell the controller that we want to load the range of posts that this
|
||||
// gap represents. We also specify which direction we want to load the
|
||||
// posts from.
|
||||
this.get('controller').send(
|
||||
'loadRange',
|
||||
this.get('start') + (relativeIndex || 0),
|
||||
this.get('end'),
|
||||
this.get('direction') === 'up'
|
||||
);
|
||||
},
|
||||
|
||||
click: function() {
|
||||
this.load();
|
||||
}
|
||||
});
|
55
ember/app/components/discussion-post.js
Normal file
55
ember/app/components/discussion-post.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import Menu from '../utils/menu';
|
||||
import MenuItem from '../components/menu-item';
|
||||
|
||||
export default Ember.View.extend({
|
||||
tagName: 'article',
|
||||
templateName: 'discussion-post',
|
||||
|
||||
controls: null,
|
||||
|
||||
contentComponent: function() {
|
||||
return 'post-type-'+this.get('post.type');
|
||||
}.property('post.type'),
|
||||
|
||||
classNames: ['post'],
|
||||
classNameBindings: ['post.deleted', 'post.edited'],
|
||||
|
||||
construct: function() {
|
||||
this.set('controls', Menu.create());
|
||||
|
||||
var post = this.get('post');
|
||||
|
||||
if (post.get('deleted')) {
|
||||
this.addControl('restore', 'Restore', 'reply', 'canEdit');
|
||||
this.addControl('delete', 'Delete', 'times', 'canDelete');
|
||||
} else {
|
||||
if (post.get('type') == 'comment') {
|
||||
this.addControl('edit', 'Edit', 'pencil', 'canEdit');
|
||||
this.addControl('hide', 'Delete', 'times', 'canEdit');
|
||||
} else {
|
||||
this.addControl('delete', 'Delete', 'times', 'canDelete');
|
||||
}
|
||||
}
|
||||
}.on('init'),
|
||||
|
||||
didInsertElement: function() {
|
||||
this.$().hide().fadeIn('slow');
|
||||
},
|
||||
|
||||
addControl: function(tag, title, icon, permissionAttribute) {
|
||||
if (permissionAttribute && ! this.get('post').get(permissionAttribute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var action = function(post) {
|
||||
self.get('controller').send(actionName, post);
|
||||
};
|
||||
|
||||
var item = MenuItem.extend({title: title, icon: icon, action: action});
|
||||
this.get('controls').addItem(tag, item);
|
||||
}
|
||||
|
||||
});
|
280
ember/app/components/discussion-scrollbar.js
Normal file
280
ember/app/components/discussion-scrollbar.js
Normal file
@@ -0,0 +1,280 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import MenuItem from '../components/menu-item';
|
||||
import Scrollbar from '../utils/scrollbar';
|
||||
import PostStreamMixin from '../mixins/post-stream';
|
||||
|
||||
export default Ember.View.extend(PostStreamMixin, {
|
||||
|
||||
/**
|
||||
@property templateName
|
||||
@type String
|
||||
*/
|
||||
templateName: 'discussion-scrollbar',
|
||||
classNames: ['scrubber', 'discussion-scrubber'],
|
||||
|
||||
// An object which represents/ecapsulates the scrollbar.
|
||||
scrollbar: null,
|
||||
|
||||
// Right after the controller finished loading a discussion, we want to
|
||||
// trigger a scroll event on the window so the interface is kept up-to-date.
|
||||
loadedChanged: function() {
|
||||
this.scrollbar.setDisabled(! this.get('controller.loaded'));
|
||||
}.observes('controller.loaded'),
|
||||
|
||||
countChanged: function() {
|
||||
this.scrollbar.setCount(this.get('controller.postStream.count'));
|
||||
}.observes('controller.postStream.count'),
|
||||
|
||||
windowWasResized: function(event) {
|
||||
var view = event.data.view;
|
||||
view.scrollbar.$.height($('#sidebar-content').height() + $('#sidebar-content').offset().top - view.scrollbar.$.offset().top - 80);
|
||||
view.scrollbar.update();
|
||||
},
|
||||
|
||||
windowWasScrolled: function(event) {
|
||||
var view = event.data.view,
|
||||
$window = $(window);
|
||||
|
||||
if (! view.get('controller.loaded') || $window.data('disableScrollHandler')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var scrollTop = $window.scrollTop(),
|
||||
windowHeight = $window.height();
|
||||
|
||||
// Before looping through all of the posts, we reset the scrollbar
|
||||
// properties to a 'default' state. These values reflect what would be
|
||||
// seen if the browser were scrolled right up to the top of the page,
|
||||
// and the viewport had a height of 0.
|
||||
var index = $('.posts .item:first').data('end');
|
||||
var visiblePosts = 0;
|
||||
var period = '';
|
||||
|
||||
var first = $('.posts .item[data-start=0]');
|
||||
var offsetTop = first.length ? first.offset().top : 0;
|
||||
|
||||
// Now loop through each of the items in the discussion. An 'item' is
|
||||
// either a single post or a 'gap' of one or more posts that haven't
|
||||
// been loaded yet.
|
||||
// @todo cache item top positions to speed this up?
|
||||
$('.posts .item').each(function(k) {
|
||||
var $this = $(this),
|
||||
top = $this.offset().top - offsetTop,
|
||||
height = $this.outerHeight();
|
||||
|
||||
// If this item is above the top of the viewport, skip to the next
|
||||
// post. If it's below the bottom of the viewport, break out of the
|
||||
// loop.
|
||||
if (top + height < scrollTop) {
|
||||
return;
|
||||
}
|
||||
if (top > scrollTop + windowHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the bottom half of this item is visible at the top of the
|
||||
// viewport, then add the visible proportion to the visiblePosts
|
||||
// counter, and set the scrollbar index to whatever the visible
|
||||
// proportion represents. For example, if a gap represents indexes
|
||||
// 0-9, and the bottom 50% of the gap is visible in the viewport,
|
||||
// then the scrollbar index will be 5.
|
||||
if (top <= scrollTop && top + height > scrollTop) {
|
||||
visiblePosts = (top + height - scrollTop) / height;
|
||||
index = parseFloat($this.data('end')) + 1 - visiblePosts;
|
||||
}
|
||||
|
||||
// If the top half of this item is visible at the bottom of the
|
||||
// viewport, then add the visible proportion to the visiblePosts
|
||||
// counter.
|
||||
else if (top + height >= scrollTop + windowHeight) {
|
||||
visiblePosts += (scrollTop + windowHeight - top) / height;
|
||||
}
|
||||
|
||||
// If the whole item is visible in the viewport, then increment the
|
||||
// visiblePosts counter.
|
||||
else {
|
||||
visiblePosts++;
|
||||
}
|
||||
|
||||
// If this item has a time associated with it, then set the
|
||||
// scrollbar's current period to a formatted version of this time.
|
||||
if ($this.data('time')) {
|
||||
period = $this.data('time');
|
||||
}
|
||||
});
|
||||
|
||||
// Now that we've looped through all of the items and have worked out
|
||||
// the scrollbar's current index and the number of posts visible in the
|
||||
// viewport, we can update the scrollbar.
|
||||
view.scrollbar.setIndex(index);
|
||||
view.scrollbar.setVisible(visiblePosts);
|
||||
view.scrollbar.update();
|
||||
|
||||
view.scrollbar.$.find('.index').text(Math.ceil(index + visiblePosts));
|
||||
view.scrollbar.$.find('.description').text(moment(period).format('MMMM YYYY'));
|
||||
},
|
||||
|
||||
mouseWasMoved: function(event) {
|
||||
var view = event.data.view;
|
||||
|
||||
if ( ! event.data.handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
var offsetPixels = event.clientY - event.data.mouseStart;
|
||||
var offsetPercent = offsetPixels / view.scrollbar.$.outerHeight() * 100;
|
||||
|
||||
var offsetIndex = offsetPercent / view.scrollbar.percentPerPost().index;
|
||||
var newIndex = Math.max(0, Math.min(event.data.indexStart + offsetIndex, view.scrollbar.count - 1));
|
||||
|
||||
view.scrollToIndex(newIndex);
|
||||
},
|
||||
|
||||
mouseWasReleased: function(event) {
|
||||
var view = event.data.view;
|
||||
|
||||
if (! event.data.handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.data.mouseStart = 0;
|
||||
event.data.indexStart = 0;
|
||||
event.data.handle = null;
|
||||
|
||||
$(window).data('disableScrollHandler', false);
|
||||
|
||||
view.get('controller').send('jumpToIndex', Math.floor(view.scrollbar.index));
|
||||
|
||||
$(window).scroll();
|
||||
$('body').css('cursor', '');
|
||||
},
|
||||
|
||||
didInsertElement: function() {
|
||||
var view = this;
|
||||
|
||||
// Set up scrollbar object
|
||||
this.scrollbar = new Scrollbar($('.discussion-scrubber .scrollbar'));
|
||||
this.scrollbar.setDisabled(true);
|
||||
this.countChanged();
|
||||
this.loadedChanged();
|
||||
|
||||
// Whenever the window is resized, adjust the height of the scrollbar
|
||||
// so that it fills the height of the sidebar.
|
||||
$(window).on('resize', {view: this}, this.windowWasResized).resize();
|
||||
|
||||
// Define a handler to update the state of the scrollbar to reflect the
|
||||
// current scroll position of the page.
|
||||
$(window).on('scroll', {view: this}, this.windowWasScrolled);
|
||||
|
||||
this.get('controller').on('loadingIndex', this, this.loadingIndex);
|
||||
|
||||
// Now we want to make the scrollbar handle draggable. Let's start by
|
||||
// preventing default browser events from messing things up.
|
||||
this.scrollbar.$
|
||||
.css('user-select', 'none')
|
||||
.bind('dragstart mousedown', function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
// When the mouse is pressed on the scrollbar handle, we need to capture
|
||||
// some information about the current position.
|
||||
var scrollData = {
|
||||
view: this,
|
||||
mouseStart: 0,
|
||||
indexStart: 0,
|
||||
handle: null
|
||||
};
|
||||
|
||||
this.scrollbar.$.find('.scrollbar-slider').css('cursor', 'move').mousedown(function(e) {
|
||||
scrollData.mouseStart = e.clientY;
|
||||
scrollData.indexStart = view.scrollbar.index;
|
||||
scrollData.handle = $(this);
|
||||
$(window).data('disableScrollHandler', true);
|
||||
$('body').css('cursor', 'move');
|
||||
});
|
||||
|
||||
// When the mouse moves,
|
||||
$(document)
|
||||
.on('mousemove', scrollData, this.mouseWasMoved)
|
||||
.on('mouseup', scrollData, this.mouseWasReleased);
|
||||
|
||||
// When any part of the whole scrollbar is clicked, we want to jump to
|
||||
// that position.
|
||||
this.scrollbar.$.click(function(e) {
|
||||
|
||||
// Calculate the index which we want to jump to.
|
||||
// @todo document how this complexity works.
|
||||
var offsetPixels = e.clientY - view.scrollbar.$.offset().top + $('body').scrollTop();
|
||||
var offsetPercent = offsetPixels / view.scrollbar.$.outerHeight() * 100;
|
||||
|
||||
var handleHeight = parseFloat(view.scrollbar.$.find('.scrollbar-slider')[0].style.height);
|
||||
|
||||
var offsetIndex = (offsetPercent - handleHeight / 2) / view.scrollbar.percentPerPost().index;
|
||||
var newIndex = Math.max(0, Math.min(view.scrollbar.count - 1, offsetIndex));
|
||||
|
||||
view.get('controller').send('jumpToIndex', Math.floor(newIndex));
|
||||
})
|
||||
|
||||
// Exempt the scrollbar handle from this 'jump to' click event.
|
||||
this.scrollbar.$.find('.scrollbar-slider').click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
actions: {
|
||||
firstPost: function() {
|
||||
this.get('controller').send('jumpToIndex', 0);
|
||||
},
|
||||
|
||||
lastPost: function() {
|
||||
this.get('controller').send('jumpToIndex', this.scrollbar.count - 1);
|
||||
}
|
||||
},
|
||||
|
||||
loadingIndex: function(index) {
|
||||
this.scrollToIndex(index, true);
|
||||
},
|
||||
|
||||
// Instantly scroll to a certain index in the discussion. The index doesn't
|
||||
// have to be an integer; any fraction of a post will be scrolled to.
|
||||
scrollToIndex: function(index, animate) {
|
||||
index = Math.max(0, Math.min(index, this.scrollbar.count - 1));
|
||||
var indexFloor = Math.floor(index);
|
||||
|
||||
// Find
|
||||
var nearestItem = this.findNearestToIndex(indexFloor);
|
||||
var first = $('.posts .item[data-start=0]');
|
||||
var offsetTop = first.length ? first.offset().top : 0;
|
||||
|
||||
var pos = nearestItem.offset().top - offsetTop;
|
||||
if (! nearestItem.is('.gap')) {
|
||||
pos += nearestItem.outerHeight() * (index - indexFloor);
|
||||
} else {
|
||||
nearestItem.addClass('active');
|
||||
}
|
||||
|
||||
$('.posts .item.gap').not(nearestItem).removeClass('active');
|
||||
|
||||
if (animate) {
|
||||
// $('html, body').animate({scrollTop: pos});
|
||||
} else {
|
||||
$('html, body').scrollTop(pos);
|
||||
}
|
||||
this.scrollbar.setIndex(index);
|
||||
this.scrollbar.update(animate);
|
||||
},
|
||||
|
||||
willDestroyElement: function() {
|
||||
$(window)
|
||||
.off('resize', this.windowWasResized)
|
||||
.off('scroll', this.windowWasScrolled);
|
||||
|
||||
$(document)
|
||||
.off('mousemove', this.mouseWasMoved)
|
||||
.off('mouseup', this.mouseWasReleased);
|
||||
|
||||
this.get('controller').off('loadingIndex', this, this.loadingIndex);
|
||||
}
|
||||
});
|
154
ember/app/components/discussions-list-item.js
Executable file
154
ember/app/components/discussions-list-item.js
Executable file
@@ -0,0 +1,154 @@
|
||||
|
||||
import Ember from 'ember';
|
||||
import Menu from '../utils/menu';
|
||||
import MenuItem from '../components/menu-item';
|
||||
|
||||
export default Ember.View.extend({
|
||||
|
||||
_init: function() {
|
||||
this.set('controls', Menu.create());
|
||||
}.on('init'),
|
||||
|
||||
tagName: 'li',
|
||||
attributeBindings: ['discussionId:data-id'],
|
||||
classNameBindings: [
|
||||
'discussion.unread:unread',
|
||||
'discussion.sticky:sticky',
|
||||
'discussion.locked:locked',
|
||||
'discussion.following:following',
|
||||
'active'
|
||||
],
|
||||
templateName: 'discussions-result',
|
||||
|
||||
active: function() {
|
||||
return this.get('childViews').anyBy('active');
|
||||
}.property('childViews.@each.active'),
|
||||
|
||||
discussionId: function() {
|
||||
return this.get('discussion.id');
|
||||
}.property('discussion.id'),
|
||||
|
||||
relevantPosts: function() {
|
||||
if (this.get('controller.show') != 'posts') return [];
|
||||
|
||||
if (this.get('controller.searchQuery')) {
|
||||
return this.get('discussion.relevantPosts');
|
||||
} else if (this.get('controller.sort') == 'newest' || this.get('controller.sort') == 'oldest') {
|
||||
return [this.get('discussion.startPost')];
|
||||
} else {
|
||||
return [this.get('discussion.lastPost')];
|
||||
}
|
||||
}.property('discussion.relevantPosts', 'discussion.startPost', 'discussion.lastPost'),
|
||||
|
||||
icon: function() {
|
||||
if (this.get('discussion.unread')) return 'circle';
|
||||
}.property('discussion.unread'),
|
||||
|
||||
iconAction: function() {
|
||||
if (this.get('discussion.unread')) return function() {
|
||||
|
||||
};
|
||||
}.property('discussion.unread'),
|
||||
|
||||
categoryClass: function() {
|
||||
return 'category-'+this.get('discussion.category').toLowerCase();
|
||||
}.property('discussion.category'),
|
||||
|
||||
didInsertElement: function() {
|
||||
this.$().hide().fadeIn('slow');
|
||||
|
||||
this.$().find('.terminal-post a').tooltip();
|
||||
|
||||
var view = this;
|
||||
this.$().find('a.info, .terminal-post a').click(function() {
|
||||
view.set('controller.paneShowing', false);
|
||||
});
|
||||
|
||||
// https://github.com/nolimits4web/Framework7/blob/master/src/js/swipeout.js
|
||||
this.$().find('.discussion').on('touchstart mousedown', function(e) {
|
||||
var isMoved = false;
|
||||
var isTouched = true;
|
||||
var isScrolling = undefined;
|
||||
var touchesStart = {
|
||||
x: e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageX : e.pageX,
|
||||
y: e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageY : e.pageY,
|
||||
};
|
||||
var touchStartTime = (new Date()).getTime();
|
||||
|
||||
$(this).on('touchmove mousemove', function(e) {
|
||||
if (! isTouched) return;
|
||||
$(this).find('a.info').removeClass('pressed');
|
||||
var touchesNow = {
|
||||
x: e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageX : e.pageX,
|
||||
y: e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageY : e.pageY,
|
||||
};
|
||||
if (typeof isScrolling === 'undefined') {
|
||||
isScrolling = !!(isScrolling || Math.abs(touchesNow.y - touchesStart.y) > Math.abs(touchesNow.x - touchesStart.x));
|
||||
}
|
||||
if (isScrolling) {
|
||||
isTouched = false;
|
||||
return;
|
||||
}
|
||||
|
||||
isMoved = true;
|
||||
e.preventDefault();
|
||||
|
||||
var diffX = touchesNow.x - touchesStart.x;
|
||||
var translate = diffX;
|
||||
var actionsRightWidth = 150;
|
||||
|
||||
if (translate < -actionsRightWidth) {
|
||||
translate = -actionsRightWidth - Math.pow(-translate - actionsRightWidth, 0.8);
|
||||
}
|
||||
|
||||
$(this).css('left', translate);
|
||||
});
|
||||
|
||||
$(this).on('touchend mouseup', function(e) {
|
||||
$(this).off('touchmove mousemove touchend mouseup');
|
||||
$(this).find('a.info').removeClass('pressed');
|
||||
if (!isTouched || !isMoved) {
|
||||
isTouched = false;
|
||||
isMoved = false;
|
||||
return;
|
||||
}
|
||||
isTouched = false;
|
||||
// isMoved = false;
|
||||
|
||||
if (isMoved) {
|
||||
e.preventDefault();
|
||||
$(this).animate({left: -150});
|
||||
}
|
||||
});
|
||||
$(this).find('a.info').addClass('pressed').on('click', function(e) {
|
||||
if (isMoved) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
$(this).off('click');
|
||||
});
|
||||
});
|
||||
|
||||
var discussion = this.get('discussion');
|
||||
|
||||
var controls = this.get('controls');
|
||||
|
||||
controls.addItem('sticky', MenuItem.extend({title: 'Sticky', icon: 'thumb-tack', action: 'sticky'}));
|
||||
controls.addItem('lock', MenuItem.extend({title: 'Lock', icon: 'lock', action: 'lock'}));
|
||||
|
||||
controls.addSeparator();
|
||||
|
||||
controls.addItem('delete', MenuItem.extend({title: 'Delete', icon: 'times', className: 'delete', action: function() {
|
||||
// this.get('controller').send('delete', discussion);
|
||||
var discussion = view.$().slideUp().find('.discussion');
|
||||
discussion.css('position', 'relative').animate({left: -discussion.width()});
|
||||
}}));
|
||||
},
|
||||
|
||||
actions: {
|
||||
icon: function() {
|
||||
this.get('iconAction')();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
Reference in New Issue
Block a user