FIX: Incorrect post number following a link. Updated ember-cloaking.

This commit is contained in:
Robin Ward 2014-02-13 14:05:12 -05:00
parent 8711762143
commit a555dc9f5e
2 changed files with 79 additions and 14 deletions

View File

@ -67,7 +67,14 @@
{{/if}} {{/if}}
{{#unless postStream.loadingFilter}} {{#unless postStream.loadingFilter}}
{{cloaked-collection cloakView="post" idProperty="post_number" defaultHeight="200" content=postStream.posts slackRatio=slackRatio loadingHTML=controller.loadingHTML}} {{cloaked-collection cloakView="post"
idProperty="post_number"
defaultHeight="200"
content=postStream.posts
slackRatio=slackRatio
loadingHTML=controller.loadingHTML
preservesContext="true"
offsetFixed="header"}}
{{/unless}} {{/unless}}
{{#if postStream.loadingBelow}} {{#if postStream.loadingBelow}}

View File

@ -10,10 +10,11 @@
Ember.CloakedCollectionView = Ember.CollectionView.extend({ Ember.CloakedCollectionView = Ember.CollectionView.extend({
topVisible: null, topVisible: null,
bottomVisible: null, bottomVisible: null,
offsetFixedElement: null,
init: function() { init: function() {
var cloakView = this.get('cloakView'), var cloakView = this.get('cloakView'),
idProperty = this.get('idProperty') || 'id'; idProperty = this.get('idProperty');
// Set the slack ratio differently to allow for more or less slack in preloading // Set the slack ratio differently to allow for more or less slack in preloading
var slackRatio = parseFloat(this.get('slackRatio')); var slackRatio = parseFloat(this.get('slackRatio'));
@ -22,18 +23,24 @@
this.set('itemViewClass', Ember.CloakedView.extend({ this.set('itemViewClass', Ember.CloakedView.extend({
classNames: [cloakView + '-cloak'], classNames: [cloakView + '-cloak'],
cloaks: cloakView, cloaks: cloakView,
preservesContext: this.get('preservesContext') === "true",
cloaksController: this.get('itemController'),
defaultHeight: this.get('defaultHeight') || 100, defaultHeight: this.get('defaultHeight') || 100,
init: function() { init: function() {
this._super(); this._super();
if (idProperty) {
this.set('elementId', cloakView + '-cloak-' + this.get('content.' + idProperty)); this.set('elementId', cloakView + '-cloak-' + this.get('content.' + idProperty));
} }
}
})); }));
this._super(); this._super();
Ember.run.next(this, 'scrolled'); Ember.run.next(this, 'scrolled');
}, },
/** /**
If the topmost visible view changed, we will notify the controller if it has an appropriate hook. If the topmost visible view changed, we will notify the controller if it has an appropriate hook.
@ -70,8 +77,10 @@
if (max < min) { return min; } if (max < min) { return min; }
var mid = Math.floor((min + max) / 2), var mid = Math.floor((min + max) / 2),
// in case of not full-window scrolling
scrollOffset = this.get('wrapperTop') >> 0,
$view = childViews[mid].$(), $view = childViews[mid].$(),
viewBottom = $view.offset().top + $view.height(); viewBottom = $view.position().top + scrollOffset + $view.height();
if (viewBottom > viewportTop) { if (viewBottom > viewportTop) {
return this.findTopView(childViews, viewportTop, min, mid-1); return this.findTopView(childViews, viewportTop, min, mid-1);
@ -90,26 +99,33 @@
if ((!childViews) || (childViews.length === 0)) { return; } if ((!childViews) || (childViews.length === 0)) { return; }
var toUncloak = [], var toUncloak = [],
onscreen = [],
// calculating viewport edges
$w = $(window), $w = $(window),
windowHeight = window.innerHeight ? window.innerHeight : $w.height(), windowHeight = this.get('wrapperHeight') || ( window.innerHeight ? window.innerHeight : $w.height() ),
windowTop = $w.scrollTop(), windowTop = this.get('wrapperTop') || $w.scrollTop(),
slack = Math.round(windowHeight * this.get('slackRatio')), slack = Math.round(windowHeight * this.get('slackRatio')),
viewportTop = windowTop - slack, viewportTop = windowTop - slack,
windowBottom = windowTop + windowHeight, windowBottom = windowTop + windowHeight,
viewportBottom = windowBottom + slack, viewportBottom = windowBottom + slack,
topView = this.findTopView(childViews, viewportTop, 0, childViews.length-1), topView = this.findTopView(childViews, viewportTop, 0, childViews.length-1),
bodyHeight = $('body').height(), bodyHeight = this.get('wrapperHeight') ? this.$().height() : $('body').height(),
bottomView = topView, bottomView = topView,
onscreen = []; offsetFixedElement = this.get('offsetFixedElement');
if (windowBottom > bodyHeight) { windowBottom = bodyHeight; } if (windowBottom > bodyHeight) { windowBottom = bodyHeight; }
if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; } if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; }
if (offsetFixedElement) {
windowTop += (offsetFixedElement.outerHeight(true) || 0);
}
// Find the bottom view and what's onscreen // Find the bottom view and what's onscreen
while (bottomView < childViews.length) { while (bottomView < childViews.length) {
var view = childViews[bottomView], var view = childViews[bottomView],
$view = view.$(), $view = view.$(),
viewTop = $view.offset().top, // in case of not full-window scrolling
scrollOffset = this.get('wrapperTop') >> 0,
viewTop = $view.position().top + scrollOffset,
viewBottom = viewTop + $view.height(); viewBottom = viewTop + $view.height();
if (viewTop > viewportBottom) { break; } if (viewTop > viewportBottom) { break; }
@ -158,20 +174,27 @@
Em.run.scheduleOnce('afterRender', this, 'scrolled'); Em.run.scheduleOnce('afterRender', this, 'scrolled');
}, },
didInsertElement: function() { _startEvents: function() {
var self = this, var self = this,
offsetFixed = this.get('offsetFixed'),
onScrollMethod = function() { onScrollMethod = function() {
Ember.run.debounce(self, 'scrollTriggered', 10); Ember.run.debounce(self, 'scrollTriggered', 10);
}; };
if (offsetFixed) {
this.set('offsetFixedElement', $(offsetFixed));
}
$(document).bind('touchmove.ember-cloak', onScrollMethod); $(document).bind('touchmove.ember-cloak', onScrollMethod);
$(window).bind('scroll.ember-cloak', onScrollMethod); $(window).bind('scroll.ember-cloak', onScrollMethod);
}, this.addObserver('wrapperTop', self, onScrollMethod);
this.addObserver('wrapperHeight', self, onScrollMethod);
}.on('didInsertElement'),
willDestroyElement: function() { _endEvents: function() {
$(document).unbind('touchmove.ember-cloak'); $(document).unbind('touchmove.ember-cloak');
$(window).unbind('scroll.ember-cloak'); $(window).unbind('scroll.ember-cloak');
} }.on('willDestroyElement')
}); });
@ -198,11 +221,46 @@
uncloak: function() { uncloak: function() {
var containedView = this.get('containedView'); var containedView = this.get('containedView');
if (!containedView) { if (!containedView) {
var model = this.get('content'),
controller = null,
container = this.get('container');
// Wire up the itemController if necessary
var controllerName = this.get('cloaksController');
if (controllerName) {
var controllerFullName = 'controller:' + controllerName,
factory = container.lookupFactory(controllerFullName),
parentController = this.get('controller');
// let ember generate controller if needed
if (factory === undefined) {
factory = Ember.generateControllerFactory(container, controllerName, model);
// inform developer about typo
Ember.Logger.warn('ember-cloacking: can\'t lookup controller by name "' + controllerFullName + '".');
Ember.Logger.warn('ember-cloacking: using ' + factory.toString() + '.');
}
controller = factory.create({
model: model,
parentController: parentController,
target: parentController
});
}
var createArgs = {},
target = controller || model;
if (this.get('preservesContext')) {
createArgs.content = target;
} else {
createArgs.context = target;
}
if (controller) { createArgs.controller = controller; }
this.setProperties({ this.setProperties({
style: null, style: null,
loading: false, loading: false,
containedView: this.createChildView(this.get('cloaks'), {content: this.get('content') }) containedView: this.createChildView(this.get('cloaks'), createArgs)
}); });
this.rerender(); this.rerender();