Famous / engine

MIT License
1.75k stars 250 forks source link

Size.RENDER && Content Div #416

Open jd-carroll opened 9 years ago

jd-carroll commented 9 years ago

When you set the size mode Size.RENDER and place textual content into the Node using Node.setContent, the size of the nested content div is not updated with the render size.

Will try to work up an example tomorrow. I was doing something dumb when I encoutered this (trying to set a max height on a Size.RENDER so that text-overflow works, should just set an absolute height), so I don't know how critical this is or if folks will run into this for real...

thejsn commented 9 years ago

I'm running in to this issue right now, or at least something similar. This seem to happen if the element is hidden when content is added with Node.setContent.

Here is an example where Node.getSize return the height 0 even after it's been made visible:

var famous = require('famous');

// Famous dependencies
var DOMElement = famous.domRenderables.DOMElement;
var FamousEngine = famous.core.FamousEngine;
FamousEngine.init();

var scene = FamousEngine.createScene();

var node = scene.addChild();
var element = new DOMElement(node, { tagName: 'div' });

element.setProperty('display', 'none');

node
  .setSizeMode('relative', 'render', 'absolute')
  .setProportionalSize(1.0, 1.0, 1.0)
  .setAbsoluteSize(1, 100, 1);

setTimeout(function() {
  console.log('Set text content');
  element.setContent(
    '<p>hello</p><p>hello</p><p>hello</p><p>hello</p>'+
    '<p>hello</p><p>hello</p><p>hello</p><p>hello</p>'+
    '<p>hello</p><p>hello</p><p>hello</p><p>hello</p>'
  );
}, 100);

setTimeout(function() {
  console.log('Set display: block');
  element.setProperty('display', 'block');
}, 1000);

setTimeout(function() {
  console.log(node.getSize())
}, 1500);

A possible work around in this example is setting the display property to block just before setContent(), and then back to none after:

  element.setProperty('display', 'block');
  element.setContent(
    ...
  );
  element.setProperty('display', 'none');

But that only works if all parent nodes are visible too, so that is not always a realistic solution.

jd-carroll commented 9 years ago

@thejsn I'm not sure that's the same issue... Unfortunately I'm not going to get a chance to debug this until next week, but will also take a look at your issue at the same time and let you know.

JeremySaks commented 9 years ago

I'm encountering this problem as well. And it is causing a secondary problem: because node.getSize() is returning [0, 0, 0] where sizeMode is set to RENDER, node.setMountPoint() fails to properly translate the node's position (or, I assume, translates its position by 0).

var child = parent.addChild();
child.el = new famous.domRenderables.DOMElement(child, {
  content: 'test'
});
child.setSizeMode(2);
console.log(child.getSize()); // [0, 0, 0]

child.setAlign(1).setMountPoint(1); // content appears outside of parent node
michaelobriena commented 9 years ago

@JeremySaks I would expect this to happen. You are getting the size before we have written it to the DOM, as such, we have no idea what the render size is. Also, not sure if this is intended, but you are only setting the align and mount point of the X part of the node.

JeremySaks commented 9 years ago

@michaelobriena that makes sense, and teaches me something basic about node positioning.

I don't mean to hijack this thread, but is there a way to effectively work with size mode render in conjunction with components like MountPoint and Origin when the node size is not known at the time of construction? Or are they really not intended to be used together?

(Note: I only included the x-axis param in my example in order to simplify it.)

michaelobriena commented 9 years ago

Origin and mount point do work with render size. RenderSize is just a way of informing the node of how big it is. Beyond that it should work the same in the layout system.

pilwon commented 9 years ago

@michaelobriena I'm still wondering how to dynamically render a DOM element with arbitrary content at the center of parent node. Is there a known solution for that?

michaelobriena commented 9 years ago

// Famous dependencies
var DOMElement = require('famous/dom-renderables/DOMElement');
var FamousEngine = require('famous/core/FamousEngine');
FamousEngine.init();

var scene = FamousEngine.createScene();
var root = scene.addChild();
root
  .setSizeMode(1, 1, 1)
  .setAlign(.5, .5, .5)
  .setMountPoint(.5, .5, .5)
  .setAbsoluteSize(400, 400);

new DOMElement(root, {
  properties: {
    backgroundColor: 'red'
  }
})

var node = root.addChild();
var element = new DOMElement(node, {
  content: 'Hello',
  properties: {
    background: 'yellow'
  }
});

node
  .setSizeMode(2, 2)
  .setMountPoint(.5, .5)
  .setAlign(.5, .5)

There is an issue we are working through in regards to words auto moing down a line but this is the idea.

pilwon commented 9 years ago

@michaelobriena Thanks, I didn't know positioning issue for render size was fixed in v0.7. I'm glad it's almost working now except this word splitting bug. Is there an issue we can track for this bug?

michaelobriena commented 9 years ago

There was at one point but I was actually looking for it earlier today and could not find it. I will start one.

pilwon commented 9 years ago

@michaelobriena Thanks for opening issue #467

elinfante commented 9 years ago

@JeremySaks If you want to get the size of a Render Node you need to add a component onSizeChange:

Following an example that works for me:

(this = node)
function _addSizeComponent() {

    this.BZNO_FA_COMPONENT_SIZECHANGE.onSizeChange = function() {
        this.width = this.dom.getRenderSize()[0];
        this.height = this.dom.getRenderSize()[1];
        _setInitialPosition.call(this);
    }.bind(this);

    this.addComponent(this. BZNO_FA_COMPONENT_SIZECHANGE);

}