// ========================================================================== // Project: SproutCore - JavaScript Application Framework // Copyright: ©2006-2011 Strobe Inc. and contributors. // portions copyright @2011 Apple Inc. // License: Licensed under MIT license (see license.js) // ========================================================================== /*global module test htmlbody ok equals same stop start */ var pane, view , view2, view3, view4; var appleURL='http://photos4.meetupstatic.com/photos/event/4/6/9/9/600_4518073.jpeg'; module("SC.ScrollView",{ setup: function() { SC.RunLoop.begin(); pane = SC.MainPane.create({ childViews: [ SC.ScrollView.extend({ contentView: SC.ImageView.design({value: appleURL, layout: {height:4000, width:4000}}) }), SC.ScrollView.extend({ contentView: SC.ImageView.design({value: appleURL, layout: {height:2000, width:2000}}) }), SC.ScrollView.extend({ layout: { height: 400, width: 400 }, contentView: SC.View.design({ layout: { height: 500, width: 500 }, childViews: [ SC.ScrollView.design({ layout: { height: 200, width: 200, centerX: 0, centerY: 0 }, contentView: SC.ImageView.design({value: appleURL, layout: {height:300, width:300}}) }) ] }) }) ], expectedVertLine: function(line) { var ret = view.get('verticalLineScroll')*line; var alt = view.get('maximumVerticalScrollOffset'); ret = (ret > alt)? alt : ret; return ret; }, expectedHorzLine: function(line) { var ret = view.get('horizontalLineScroll')*line; var alt = view.get('maximumHorizontalScrollOffset'); ret = (ret > alt)? alt : ret; return ret; }, expectedVertPage: function(page) { var ret = view.get('verticalPageScroll')*page; var alt = view.get('maximumVerticalScrollOffset'); ret = (ret > alt)? alt : ret; return ret; }, expectedHorzPage: function(page) { var ret = view.get('horizontalPageScroll')*page; var alt = view.get('maximumHorizontalScrollOffset'); ret = (ret > alt)? alt : ret; return ret; } }); pane.append(); // make sure there is a layer... SC.RunLoop.end(); view = pane.childViews[0]; view.get('containerView').get('frame').height = 100; view.get('containerView').get('frame').width = 100; view2 = pane.childViews[1]; view2.get('containerView').get('frame').height = 100; view2.get('containerView').get('frame').width = 100; view3 = pane.childViews[2]; view4 = view3.get('contentView').get('childViews')[0]; }, teardown: function() { pane.remove(); pane = view = null ; } }); test("Scrolling to a certain co-ordinate of the container view", function() { equals(view.get('horizontalScrollOffset'), 0, "Initial horizontal offset must be zero"); equals(view.get('verticalScrollOffset'), 0, "Initial vertical offset must be zero"); SC.RunLoop.begin(); view.scrollTo(100, 100); SC.RunLoop.end(); equals(view.get('horizontalScrollOffset'), 100, "After scrolling to 100, horizontal offset must be"); equals(view.get('verticalScrollOffset'), 100, "After scrolling to 100, vertical offset must be"); view.scrollTo(5000, 5000); equals(view.get('horizontalScrollOffset'), view.get('maximumHorizontalScrollOffset'), "After scrolling to 400, horizontal offset must be maximum"); equals(view.get('verticalScrollOffset'), view.get('maximumVerticalScrollOffset'), "After scrolling to 400, vertical offset must be maximum"); }); test("Scrolling relative to the current possition of the container view", function() { equals(view.get('horizontalScrollOffset'), 0, "Initial horizontal offset must be zero"); equals(view.get('verticalScrollOffset'), 0, "Initial vertical offset must be zero"); view.scrollBy(100, 100); equals(view.get('horizontalScrollOffset'), 100, "After scrolling by 100, horizontal offset must be"); equals(view.get('verticalScrollOffset'), 100, "After scrolling by 100, vertical offset must be"); view.scrollBy(100, 100); equals(view.get('horizontalScrollOffset'), 200, "After scrolling by 100, horizontal offset must be"); equals(view.get('verticalScrollOffset'), 200, "After scrolling by 100, vertical offset must be"); view.scrollBy(5000, 5000); equals(view.get('horizontalScrollOffset'), view.get('maximumHorizontalScrollOffset'), "After scrolling by 400, horizontal offset must be maximum"); equals(view.get('verticalScrollOffset'), view.get('maximumVerticalScrollOffset'), "After scrolling by 400, vertical offset must be maximum"); }); test("Scrolling through line by line", function() { var line = 3; equals(view.get('horizontalScrollOffset'), 0, "Initial horizontal offset must be zero"); equals(view.get('verticalScrollOffset'), 0, "Initial vertical offset must be zero"); view.scrollDownLine(line); equals(view.get('horizontalScrollOffset'), 0, "After scrolling down by lines, horizontal offset is unchanged"); equals(view.get('verticalScrollOffset'), pane.expectedVertLine(line), "After scrolling down by lines, vertical offset must be"); view.scrollUpLine(line); }); test("maximumHorizontalScrollOffset() returns the maximum horizontal scroll dimension", function() { var old_horizontalScrollOffset=2; var old_verticalScrollOffset=2; view2.set('horizontalScrollOffset',old_horizontalScrollOffset); view2.set('verticalScrollOffset',old_verticalScrollOffset); view2.scrollBy(5000, 0); view2.get('horizontalScrollOffset'); equals(view2.get('horizontalScrollOffset'),1900, 'maximum y coordinate should be 1900'); view2.set('horizontalScrollOffset',old_horizontalScrollOffset); view2.set('verticalScrollOffset',old_verticalScrollOffset); view2.scrollBy(-5000,0); equals(view2.get('horizontalScrollOffset'),0, 'minimum y coordinate should be 0'); }); test("maximumVerticalScrollOffset() returns the maximum vertical scroll dimension", function() { var old_horizontalScrollOffset=2; var old_verticalScrollOffset=2; view2.set('horizontalScrollOffset',old_horizontalScrollOffset); view2.set('verticalScrollOffset',old_verticalScrollOffset); view2.scrollBy(0, 5000); view2.get('maximumVerticalScrollOffset'); equals(view2.get('verticalScrollOffset'),1900, 'maximum coordinate should be 1900'); view2.set('horizontalScrollOffset',old_horizontalScrollOffset); view2.set('verticalScrollOffset',old_verticalScrollOffset); view2.scrollBy(0,-5000); equals(view2.get('verticalScrollOffset'),0, 'The minimum y coordinate should be 0'); }); test("Mouse wheel events should only be captured if the scroll can scroll in the direction (both TOP-LEFT).", function() { // FIRST GROUP: everything scrolled all the way to the top left view3.scrollTo(0,0); view4.scrollTo(0,0); // Scrolling further left is not captured by either scroll view ok(!view3.mouseWheel({ wheelDeltaX: -10, wheelDeltaY: 0 }), 'The inner scroll view should not capture the mousewheel event since it cannot scroll further.'); ok(!view4.mouseWheel({ wheelDeltaX: -10, wheelDeltaY: 0 }), 'The outer scroll view should not capture the mousewheel event since it cannot scroll further.'); // Scrolling further up is not captured by either scroll view ok(!view3.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: -10 }), 'The inner scroll view should not capture the mousewheel event since it cannot scroll further.'); ok(!view4.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: -10 }), 'The outer scroll view should not capture the mousewheel event since it cannot scroll further.'); // Scrolling down is captured by the target scroll view ok(view3.mouseWheel({ wheelDeltaX: 10, wheelDeltaY: 0 }), 'The inner scroll view should capture the mousewheel event since it can scroll further.'); ok(view4.mouseWheel({ wheelDeltaX: 10, wheelDeltaY: 0 }), 'The outer scroll view should capture the mousewheel event since it can scroll further.'); // Scrolling right is captured by the target scroll view ok(view3.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: 10 }), 'The inner scroll view should capture the mousewheel event since it can scroll further.'); ok(view4.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: 10 }), 'The outer scroll view should capture the mousewheel event since it can scroll further.'); }); test("Mouse wheel events should only be captured if the scroll can scroll in the direction (both BOTTOM-RIGHT).", function() { view3.scrollTo(114,114); view4.scrollTo(114,114); // Scrolling further right is not captured by either scroll view ok(!view3.mouseWheel({ wheelDeltaX: 10, wheelDeltaY: 0 }), 'The inner scroll view should not capture the mousewheel event since it cannot scroll further.'); ok(!view4.mouseWheel({ wheelDeltaX: 10, wheelDeltaY: 0 }), 'The outer scroll view should not capture the mousewheel event since it cannot scroll further.'); // Scrolling further down is not captured by either scroll view ok(!view3.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: 10 }), 'The inner scroll view should not capture the mousewheel event since it cannot scroll further.'); ok(!view4.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: 10 }), 'The outer scroll view should not capture the mousewheel event since it cannot scroll further.'); // Scrolling up is captured by the target scroll view ok(view3.mouseWheel({ wheelDeltaX: -10, wheelDeltaY: 0 }), 'The inner scroll view should capture the mousewheel event since it can scroll further.'); ok(view4.mouseWheel({ wheelDeltaX: -10, wheelDeltaY: 0 }), 'The outer scroll view should capture the mousewheel event since it can scroll further.'); // Scrolling left is captured by the target scroll view ok(view3.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: -10 }), 'The inner scroll view should capture the mousewheel event since it can scroll further.'); ok(view4.mouseWheel({ wheelDeltaX: 0, wheelDeltaY: -10 }), 'The outer scroll view should capture the mousewheel event since it can scroll further.'); }); test("Mouse wheel events not capturable by the inner scroll should bubble to the outer scroll (scroll right).", function() { var elem = view4.get('layer'), event; view3.scrollTo(0,0); view4.scrollTo(114,114); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: 10, wheelDeltaY: 0 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('horizontalScrollOffset'), 114, 'The inner scroll view should still have horizontalScrollOffset'); equals(view3.get('horizontalScrollOffset'), 10, 'The outer scroll view should now have horizontalScrollOffset'); window.start(); }, interval: 200}); SC.RunLoop.end(); }); test("Mouse wheel events not capturable by the inner scroll should bubble to the outer scroll (scroll down).", function() { var elem = view4.get('layer'), event; view3.scrollTo(0,0); view4.scrollTo(114,114); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: 0, wheelDeltaY: 10 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('verticalScrollOffset'), 114, 'The inner scroll view should still have verticalScrollOffset'); equals(view3.get('verticalScrollOffset'), 10, 'The outer scroll view should now have verticalScrollOffset'); window.start(); }, interval: 200}); SC.RunLoop.end(); }); test("Mouse wheel events not capturable by the inner scroll should bubble to the outer scroll (scroll left).", function() { var elem = view4.get('layer'), event; view3.scrollTo(114,114); view4.scrollTo(0,0); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: -10, wheelDeltaY: 0 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('horizontalScrollOffset'), 0, 'The inner scroll view should still have horizontalScrollOffset'); equals(view3.get('horizontalScrollOffset'), 104, 'The outer scroll view should now have horizontalScrollOffset'); window.start(); }, interval: 200}); SC.RunLoop.end(); }); test("Mouse wheel events not capturable by the inner scroll should bubble to the outer scroll (scroll up).", function() { var elem = view4.get('layer'), event; view3.scrollTo(114,114); view4.scrollTo(0,0); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: 0, wheelDeltaY: -10 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('verticalScrollOffset'), 0, 'The inner scroll view should still have verticalScrollOffset'); equals(view3.get('verticalScrollOffset'), 104, 'The outer scroll view should now have verticalScrollOffset'); window.start(); }, interval: 200 }); SC.RunLoop.end(); }); test("Mouse wheel events capturable by the inner scroll should not bubble to the outer scroll (scroll right).", function() { var elem = view4.get('layer'), event; view3.scrollTo(0,0); view4.scrollTo(0,0); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: 10, wheelDeltaY: 0 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('horizontalScrollOffset'), 10, 'The inner scroll view should now have horizontalScrollOffset'); equals(view3.get('horizontalScrollOffset'), 0, 'The outer scroll view should still have horizontalScrollOffset'); window.start(); }, interval: 200 }); SC.RunLoop.end(); }); test("Mouse wheel events capturable by the inner scroll should not bubble to the outer scroll (scroll up).", function() { var elem = view4.get('layer'), event; view3.scrollTo(114,114); view4.scrollTo(114,114); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: 0, wheelDeltaY: -10 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('verticalScrollOffset'), 104, 'The inner scroll view should now have verticalScrollOffset'); equals(view3.get('verticalScrollOffset'), 114, 'The outer scroll view should still have verticalScrollOffset'); window.start(); }, interval: 200 }); SC.RunLoop.end(); }); test("Mouse wheel events capturable by the inner scroll should not bubble to the outer scroll (scroll left).", function() { var elem = view4.get('layer'), event; view3.scrollTo(114,114); view4.scrollTo(114,114); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: -10, wheelDeltaY: 0 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('horizontalScrollOffset'), 104, 'The inner scroll view should now have horizontalScrollOffset'); equals(view3.get('horizontalScrollOffset'), 114, 'The outer scroll view should still have horizontalScrollOffset'); window.start(); }, interval: 200 }); SC.RunLoop.end(); }); test("Mouse wheel events capturable by the inner scroll should not bubble to the outer scroll (scroll down).", function() { var elem = view4.get('layer'), event; view3.scrollTo(0,0); view4.scrollTo(0,0); window.stop(); event = SC.Event.simulateEvent(elem, 'mousewheel', { wheelDeltaX: 0, wheelDeltaY: 10 }); SC.Event.trigger(elem, 'mousewheel', event); SC.RunLoop.begin(); SC.Timer.schedule({ target: this, action: function() { equals(view4.get('verticalScrollOffset'), 10, 'The inner scroll view should now have verticalScrollOffset'); equals(view3.get('verticalScrollOffset'), 0, 'The outer scroll view should still have verticalScrollOffset'); window.start(); }, interval: 200 }); SC.RunLoop.end(); });