Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a cacheInstanciatedViews property to SC.ContainerView #1439

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
86 changes: 44 additions & 42 deletions frameworks/foundation/tests/views/container/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,39 +51,24 @@

view3: SC.View.create(),
view4: SC.View.create()
})
}),

// prevent destroying containers on teardown
destroy: function() {},
});

pane.add("cleans-up-views", SC.ContainerView, {
nowShowing: 'uninstantiatedView',
cacheInstanciatedViews: false,
uninstantiatedView: SC.View
});

pane.add("cache-views", SC.ContainerView, {
nowShowing: 'uninstantiatedView',
cacheInstanciatedViews: true,
uninstantiatedView: SC.View
});

// .add("disabled - single selection", SC.ListView, {
// isEnabled: NO,
// content: content,
// contentValueKey: 'title',
// selection: singleSelection
// })
//
// .add("single selection", SC.ListView, {
// content: content,
// contentValueKey: 'title',
// selection: singleSelection
// })
//
// .add("multiple selection, contiguous", SC.ListView, {
// content: content,
// contentValueKey: 'title',
// selection: multiSelectionContiguous
// })
//
// .add("multiple selection, discontiguous", SC.ListView, {
// content: content,
// contentValueKey: 'title',
// selection: multiSelectionDiscontiguous
// })

// ..........................................................
// TEST VIEWS
Expand All @@ -95,10 +80,8 @@
ok(!view.$().hasClass('disabled'), 'should not have disabled class');
ok(!view.$().hasClass('sel'), 'should not have sel class');

var contentView = view.get('contentView') ;

// ok(contentView.kindOf(SC.ContainerView), 'default contentView is an SC.ContainerView');
// ok(contentView.get('contentView') === null, 'default contentView should have no contentView itself');
ok(view.kindOf(SC.ContainerView), 'default contentView is an SC.ContainerView');
ok(view.get('contentView') === null, 'default contentView should have no contentView itself');
});

test("disabled", function() {
Expand All @@ -107,18 +90,6 @@
ok(!view.$().hasClass('sel'), 'should not have sel class');
});

// test("disabled - single selection", function() {
// var view = pane.view('disabled - single selection');
// ok(view.$().hasClass('disabled'), 'should have disabled class');
// ok(view.itemViewAtContentIndex(0).$().hasClass('sel'), 'should have sel class');
// });
//
// test("single selection", function() {
// var view = pane.view('single selection');
// ok(view.itemViewAtContentIndex(0).$().hasClass('sc-collection-item'), 'should have sc-collection-item class');
// ok(view.itemViewAtContentIndex(0).$().hasClass('sel'), 'should have sel class');
// });

test("changing nowShowing", function() {
var view = pane.view('basic');
// Set nowShowing to an instantiated object.
Expand Down Expand Up @@ -192,6 +163,37 @@
contentView = view.get('contentView');
SC.run(function() { view.set('nowShowing', null); });
equals(contentView.isDestroyed, YES, "should have destroyed the previous view it instantiated (from class)");

SC.run(function() { view.set('nowShowing', SC.View.create()); });
contentView = view.get('contentView');
equals(contentView.isDestroyed, NO, "The content view should not be destroyed");

view.destroy();
equals(contentView.isDestroyed, YES, "should have destroyed the content view");

});

test("Cache instantiated views", function() {
var view = pane.view("cache-views");
view.awake();

var contentViewFromPath = view.get('contentView');
SC.run(function() { view.set('nowShowing', SC.View.create()); });
equals(contentViewFromPath.isDestroyed, NO, "should not have destroyed the previous view it instantiated (from path)");

var contentView = view.get('contentView');
SC.run(function() { view.set('nowShowing', SC.View.extend()); });
equals(contentView.isDestroyed, NO, "should not have destroyed the previous view because it was already instantiated");

var contentViewFromClass = view.get('contentView');
SC.run(function() { view.set('nowShowing', null); });
equals(contentViewFromClass.isDestroyed, NO, "should not have destroyed the previous view it instantiated (from class)");

view.destroy();
equals(view.isDestroyed, YES, "should have destroyed the container");
equals(contentViewFromPath.isDestroyed, YES, "should have destroyed the view it instantiated (from path)");
equals(contentView.isDestroyed, NO, "should not have destroyed the view that was already instantiated");
equals(contentViewFromClass.isDestroyed, YES, "should have destroyed the view it instantiated (from class)");
});

test("Nested container view", function() {
Expand Down Expand Up @@ -262,7 +264,7 @@
equals(container1.getPath('view1.frame.height'), 100, 'nowShowing#view1: view1 height should be');


container2.get('view4').adjust('top', 10);
container2.get('view4').adjust('top', 10);
view.set("nowShowing", 'container2');

equals(container1.get('isVisibleInWindow'), false, "nowShowing#view4: container1 visbility should be");
Expand Down
65 changes: 57 additions & 8 deletions frameworks/foundation/views/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@ SC.ContainerView = SC.View.extend(
*/
isTransitioning: NO,

/**
If the view to display is not instantiated, SC.ContainerView will instanciate
it for you when the view is entered.

if cacheInstanciatedViews is set to true, the instanciated views will be
cached for later reuse. Otherwise, the instanciated views will be destroyed
when the view is exited.

All the cached views will be destroy if the container itself is destroy.

@type Boolean
@default true
*/
cacheInstanciatedViews: true,

/**
Optional path name for the content view. Set this to a property path
pointing to the view you want to display. This will automatically change
Expand Down Expand Up @@ -256,12 +271,28 @@ SC.ContainerView = SC.View.extend(
this.removeObserver('contentView', this, this._sc_contentViewDidChange);

// Cancel any active transitions.
// Note: this will also destroy any content view that the container created.
this._sc_cancelTransitions();
var contentView = this.get('contentView');

// Remove our internal reference to the statecharts.
this._contentStatecharts = this._currentStatechart = null;

if (this._cachedViews) {
this._cachedViews.forEach(function(cachedView) {
cachedView.instance.parentView = this;
cachedView.instance.destroy();
cachedView.instance.parentView = null;
}, this);
this._cachedViews = null;
}

if (contentView) {
contentView.parentView = this;
contentView.destroy();
contentView.parentView = null;
this.contentView = null;
}

return sc_super();
},

Expand All @@ -272,7 +303,10 @@ SC.ContainerView = SC.View.extend(
*/
nowShowingDidChange: function () {
// This code turns this.nowShowing into a view object by any means necessary.
var content = this.get('nowShowing');
var content = this.get('nowShowing'),
nowShowing = content+'',
cacheInstanciatedViews = this.get('cacheInstanciatedViews'),
cachedViews = this._cachedViews;

// If it's a string, try to turn it into the object it references...
if (SC.typeOf(content) === SC.T_STRING && content.length > 0) {
Expand All @@ -292,11 +326,6 @@ SC.ContainerView = SC.View.extend(
}
}

// If it's an uninstantiated view, then attempt to instantiate it.
if (content && content.kindOf(SC.CoreView)) {
content = this.createChildView(content);
}

//@if(debug)
// Prevent developers from assigning non-view content to a container.
if (content && !SC.kindOf(content, SC.CoreView)) {
Expand All @@ -305,6 +334,26 @@ SC.ContainerView = SC.View.extend(
}
//@endif

if (content && content.kindOf(SC.CoreView)) {
// If it's an uninstantiated view, then attempt to instantiate it.
if (SC.typeOf(content) === SC.T_CLASS) {
if (cachedViews) {
var obj = cachedViews.findProperty('nowShowing', nowShowing);
if (obj) {
content = obj.instance;
}
}
}

if (SC.typeOf(content) === SC.T_CLASS) {
content = this.createChildView(content);
if (cacheInstanciatedViews) {
if (!cachedViews) cachedViews = this._cachedViews = [];
cachedViews.push({ nowShowing: nowShowing, instance: content });
}
}
}

// Sets the content.
this.set('contentView', content);
}.observes('nowShowing'),
Expand Down Expand Up @@ -625,7 +674,7 @@ SC.ContainerContentStatechart = SC.Object.extend({
transitionSwap.didBuildOutFromView(container, content, options);
}

if (content.createdByParent) {
if (content.createdByParent && !container.get('cacheInstanciatedViews')) {
container.removeChildAndDestroy(content);
} else {
container.removeChild(content);
Expand Down