Element.find doesn't work correctly when using the CSS property flow: horizontal

Sciter Forums Bug reports Element.find doesn't work correctly when using the CSS property flow: horizontal

This topic contains 10 replies, has 2 voices, and was last updated by  gaoqiangz 4 months, 2 weeks ago.

  • Author
    Posts
  • #48789

    gaoqiangz
    Participant
    #favorites {
    	margin: 10dip;
    	flow: horizontal-flow;
    }

    When I use $(#favorites).find(evtX,evtY) to find a child,it always return the child currently being captured by the mouse or the child on the right.
    horizontal or horizontal-flow have the same problem

  • #48793

    Andrew
    Keymaster

    Any sample I can try?

  • #48798

    gaoqiangz
    Participant

    test.htm:

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style>
    	body {
    		margin: 0;
    		padding: 0;
    		flow: horizontal;
    		overflow: hidden;
    	}
    	div.item {
    		behavior: clickable;
    	}
    	div.left {
    		position: relative;
    		size: *;
    		background-color: #CEDEED;
    		border-right: 1dip solid #A7B3C5;
    		flow: vertical;
    		overflow: scroll-indicator;
    	}
    	div.left > .title {
    		margin: 10dip;
    		border-bottom: 1dip dashed #A7B3C5;
    	}
    	div.left > .title > caption {
    		margin-bottom: 10dip;
    		padding-left: 10px;
    		foreground: url(img\12.gif) no-repeat 0 50%;
    	}
    	div.left > .favorites {
    		prototype: "Favorites" url(favorites.tis);
    		margin: 10dip;
    		flow: horizontal-flow;
    	}
    	div.left > .favorites > .item {
    		size: max-content;
    		margin: 0 40dip 40dip 0;
    		padding: 4dip;
    		color: #18698E;
    		text-align: center;
    		flow: vertical;
    	}
    	div.left > .favorites > .item:hover {
    		background-color: #DAF0FD;
    		outline: 1dip solid #A7B3C5;
    		border-radius: 4dip;
    		transition: background-color(linear,100ms)
    					outline(linear,100ms);
    	}
    	div.left > .favorites > .item:active {
    		background-color: rgb(186,202,217);
    		transition: none;
    	}
    	div.left > .favorites > .item[dragging]
    	{
    		opacity: 0.5;
    		background-color: transparent;
    		outline: none;
    	}
    	div.left > .favorites > .item > img {
    		margin: 0 * 4dip *;
    	}
    	div.left > .favorites > .item.add {
    		color: #424C54;
    	}
    </style>
    <script type="text/tiscript">
    	function self.ready(){
    		self.on("click","div.item",function(){
    			view.msgbox("",this.text);
    		});
    	}
    </script>
    </head>
    <body>
    	<div.left>
    		<div.title><caption>Favorites</caption></div>
    		<div.favorites>
    			<div.item tooltip="item1" cls="cls"><img src="img\41.gif"/><text>item1</text></div>
    			<div.item tooltip="item2" cls="cls"><img src="img\41.gif"/><text>item2</text></div>
    			<div.item tooltip="item3" cls="cls"><img src="img\41.gif"/><text>item3</text></div>
    			<div.item.add tooltip="Add more" #addMore><img src="img\41.gif"/><text>Add more..</text></div>
    		</div>
    	</div>
    </body>
    </html>

    favorites.tis:

    class Favorites : Behavior
    {
    	const DD_X_THRESHOLD			= 4;
    	const DD_Y_THRESHOLD			= 4;
    	const DD_FILL_COLOR			= rgba(62,151,246,0.3);
    	const DD_LINE_COLOR			= rgb(62,151,246);
    	const DD_LINE_SIZE			= 1;
    	const DD_AM_DURATION			= 200ms;
    	const DD_DROP_WHERE_BEFORE	= 1;
    	const DD_DROP_WHERE_AFTER	= 2;
    	this var m_dragging			= false;
    	this var m_animating			= false;
    	this var m_drag_source		= null;
    	this var m_drop_target		= null;
    	this var m_drop_where		= 0;
    	this var m_drop_marker_pos	= {x1:0,y1:0,x2:0,y2:0};
    	this var m_mouse_target		= 0;
    	this var m_mouse_where		= 0;
    	this var m_mouse_down_item	= null;
    	this var m_mouse_down_pos	= {x:0,y:0};
    	this var m_last_mouse_pos	= {x:0,y:0};
    	this var m_snap_image		= null;
    	this var m_snap_image_pos	= {x:0,y:0};
    	
    	function getLocalPos(vX,vY)
    	{
    		var (tx,ty) = this.box(#position, #content, #view);
    		return (vX - tx + this.scroll(#left),vY - ty + this.scroll(#top));
    	}
    
    	function getEventLocalPos(evt)
    	{
    		return this.getLocalPos(evt.xView,evt.yView);
    	}
    
    	function getElementLocalPos(el)
    	{
    		var (x,y) = el.box(#position, #border, #view);
    		return this.getLocalPos(x,y);
    	}
    
    	function getElementLocalRectW(el)
    	{
    		var (x,y,w,h) = el.box(#rectw, #border, #view);
    		(x,y) = this.getLocalPos(x,y);
    		return (x,y,w,h);
    	}
    	
    	function onMouse(evt)
    	{
    		if(!evt.target) return false;
    		if(this.m_animating) return false;
    
    		switch(evt.type)
    		{
    			case Event.MOUSE_DOWN | Event.SINKING:
    			{
    				if(evt.target === this) break;
    				var item = evt.target.$p(div.item);
    				if(!item) break;
    				if(item.attributes.hasClass("add"))break;
    				var (evtX,evtY) = this.getEventLocalPos(evt);
    				var (x,y,w,h) = this.getElementLocalRectW(item);
    				if(evtY < y || evtY > y + h) break;
    				this.m_mouse_down_item = item;
    				this.m_mouse_down_pos.x = evtX;
    				this.m_mouse_down_pos.y = evtY;
    				this.m_mouse_down_item.capture(#strict);
    				break;
    			}
    			case Event.MOUSE_UP:
    			{
    				if(this.m_mouse_down_item)
    				{
    					this.m_mouse_down_item.capture(false);
    					this.m_mouse_down_item = null;
    				}
    				if(this.m_dragging)
    				{
    					this.doDrop(evt);
    					return true;
    				}
    				break;
    			}
    			case Event.MOUSE_MOVE:
    			{
    				if(evt.mainButton)
    				{
    					if(!this.m_dragging)
    					{
    						if(!this.m_mouse_down_item) break;
    						if(evt.target === this) break;
    						var (evtX,evtY) = this.getEventLocalPos(evt);
    						if(Math.abs(evtX - this.m_mouse_down_pos.x) > DD_X_THRESHOLD ||
    							Math.abs(evtY - this.m_mouse_down_pos.y) > DD_Y_THRESHOLD)
    						{
    							this.doBeginDrag(evt);
    							return true;
    						}
    					}
    					else
    					{
    						this.doDragMove(evt);
    					}
    				}
    				break;
    			}
    			case Event.MOUSE_WHEEL:
    			{
    				if(this.m_dragging && this.m_mouse_where != 0)
    				{
    					this.m_drop_target = this.m_mouse_target = null;
    					this.m_drop_where = this.m_mouse_where = 0;
    					//this.refresh();
    				}
    				break;
    			}
    		}
    
    		return false;
    	}
    
    	function doBeginDrag(evt)
    	{
    		assert(!this.m_dragging && this.m_mouse_down_item);
    
    		var (evtX,evtY) = this.getEventLocalPos(evt);
    		this.m_drag_source = this.m_mouse_down_item;
    		
    		var (x,y,w,h) = this.getElementLocalRectW(this.m_drag_source);
    		this.m_snap_image = new Image(w, h, this.m_drag_source);
    		this.m_snap_image_pos.x = x + (evtX - this.m_mouse_down_pos.x);
    		this.m_snap_image_pos.y = y + (evtY - this.m_mouse_down_pos.y);
    		
    		this.paintForeground = this.onForegroundPainter;
    		
    		this.m_drag_source.@#dragging = true;
    		this.m_dragging = true;
    		this.refresh();
    		
    		this.m_last_mouse_pos.x = evtX;
    		this.m_last_mouse_pos.y = evtY;
    
    		return true;
    	}
    	
    	function doEndDrag()
    	{
    		assert(this.m_dragging && this.m_drag_source);
    		
    		this.paintForeground = null;
    		
    		if(this.m_snap_image) this.m_snap_image.destroy();
    		
    		this.m_drop_target = this.m_mouse_target = this.m_drag_source = this.m_snap_image = null;
    		this.m_drop_where = this.m_mouse_where = 0;
    		this.m_dragging = false;
    		
    		this.refresh();
    	}
    	
    	function doDragMove(evt)
    	{
    		assert(this.m_dragging && this.m_drag_source);
    		var (evtX,evtY) = this.getEventLocalPos(evt);
    		var cx = evtX - this.m_last_mouse_pos.x;
    		var cy = evtY - this.m_last_mouse_pos.y;
    		if(cx == 0 && cy == 0) return;
    		
    		this.m_last_mouse_pos.x = evtX;
    		this.m_last_mouse_pos.y = evtY;
    		this.m_snap_image_pos.x += cx;
    		this.m_snap_image_pos.y += cy;
    		
    		var elFound = this.find(evtX,evtY);
    		if(elFound === this) elFound = null;
    		if(elFound && !elFound.$is(div.item)) elFound = elFound.$p(div.item);
    		if(elFound) stdout.println(elFound.html);
    		if(elFound && (elFound === this.m_drag_source || elFound.state.disabled)) elFound = null;
    		if(this.m_mouse_target !== elFound)
    		{
    			this.m_mouse_target = elFound;
    			if(this.m_drop_target)
    			{
    				this.m_drop_target.@#dragenter = null;
    				this.m_drop_target = null;
    			}
    			this.m_drop_where = this.m_mouse_where = 0;
    		}
    		if(this.m_mouse_target)
    		{
    			var nWhere = 0;
    			var (x,y,w,h) = this.getElementLocalRectW(this.m_mouse_target);
    			if(evtX < x + (w / 2))
    			{
    				nWhere = DD_DROP_WHERE_BEFORE;
    			}
    			else
    			{
    				nWhere = DD_DROP_WHERE_AFTER;
    			}
    			if(nWhere != this.m_mouse_where)
    			{
    				this.m_mouse_where = nWhere;
    				switch(nWhere)
    				{
    					case DD_DROP_WHERE_BEFORE:
    					{
    						if(this.m_drag_source === this.m_mouse_target.prior)
    							nWhere = 0;
    						break;
    					}
    					case DD_DROP_WHERE_AFTER:
    					{
    						if(this.m_drag_source === this.m_mouse_target.next)
    							nWhere = 0;
    						if(this.m_mouse_target.attributes.hasClass("add"))
    							nWhere = 0;
    						break;
    					}
    				}
    				this.m_drop_where = nWhere;
    				if(this.m_drop_where != 0)
    				{
    					(x,y,w,h) = this.getElementLocalRectW(this.m_mouse_target);
    					if(this.m_drop_where == DD_DROP_WHERE_AFTER)
    					{
    						x += w;
    					}
    					this.m_drop_marker_pos.x1 = x;
    					this.m_drop_marker_pos.y1 = y;
    					this.m_drop_marker_pos.x2 = x;
    					this.m_drop_marker_pos.y2 = y + h;
    					if(!this.m_drop_target)
    					{
    						this.m_drop_target = this.m_mouse_target;
    						this.m_drop_target.@#dragenter = true;
    					}
    				}
    				else if(this.m_drop_target)
    				{
    					this.m_drop_target.@#dragenter = null;
    					this.m_drop_target = null;
    				}
    			}
    		}
    
    		this.refresh();
    	};
    	
    	function doDrop(evt)
    	{
    		assert(this.m_dragging && this.m_drag_source);
    		
    		this.m_drag_source.@#dragging = null;
    		if(this.m_drop_target) this.m_drop_target.@#dragenter = null;
    		
    		if(this.m_drop_target && !evt.propButton)
    		{
    			switch(this.m_drop_where)
    			{
    				case DD_DROP_WHERE_BEFORE:
    				{
    					this.m_drop_target.insertNodeBefore(this.m_drag_source);
    					break;
    				}
    				case DD_DROP_WHERE_AFTER:
    				{
    					this.m_drop_target.insertNodeAfter(this.m_drag_source);
    					break;
    				}
    			}
    			this.m_drag_source.scrollToView();
    			this.m_drop_target.clearState(Element.STATE_HOVER);
    		}
    
    		this.doDropAnimate();
    	}
    	
    	function doDropAnimate()
    	{
    		assert(!this.m_animating && this.m_dragging && this.m_drag_source);
    		var easef = function( t, b, c, d) { return -c *(t/=d)*(t-2) + b; }
    		var (fromx,fromy) = (this.m_snap_image_pos.x,this.m_snap_image_pos.y);
    		var (tox,toy) = this.getElementLocalPos(this.m_drag_source);
    		function amf(progress)
    		{
    			if(progress >= 1.0)
    			{
    				if(this.m_animating)
    				{
    					this.m_animating = false;
    					this.doEndDrag();
    				}
    				return false; 
    			}
    			this.m_snap_image_pos.x = easef(progress, fromx, tox - fromx, 1.0).toInteger();
    			this.m_snap_image_pos.y = easef(progress, fromy, toy - fromy, 1.0).toInteger();
    			this.refresh();
    			return true;
    		}
    		this.m_animating = true;
    		this.animate(amf, DD_AM_DURATION);
    	}
    	
    	function onForegroundPainter(gfx)
    	{
    		gfx.save();
    		gfx.blendImage( this.m_snap_image, this.m_snap_image_pos.x,this.m_snap_image_pos.y, 0.5 );
    		if(this.m_drop_target && this.m_drop_target.@#dragenter)
    		{
    			gfx.strokeColor(DD_LINE_COLOR);
    			gfx.strokeWidth(DD_LINE_SIZE);
    			gfx.strokeDash(#solid);
    			gfx.line(this.m_drop_marker_pos.x1,this.m_drop_marker_pos.y1,this.m_drop_marker_pos.x2,this.m_drop_marker_pos.y2);
    		}
    		gfx.restore();
    	}
    }

    There is a problem with the code in function doDragMove(evt)::var elFound = this.find(evtX,evtY);
    Please drag the “item”.
    And I found a new problem when after scrolling the outline will repeat:
    normal
    normal
    after scrolling
    after scrolling

    • This reply was modified 4 months, 2 weeks ago by  gaoqiangz.
  • #48803

    Andrew
    Keymaster

    I haven’t tested this but try to put view.update() when you need to find elements.

    Problem is that at the moment of element.find() its layout can be not known due to changes made before.

    • #48804

      gaoqiangz
      Participant

      Still not resolved..

    • #48818

      Andrew
      Keymaster

      I do not see any problems to be honest.

      This looks and behaves OK.

      dragging

  • #48843

    gaoqiangz
    Participant

    See this gif,I can’t drag the item to left because “When I use $(#favorites).find(evtX,evtY) to find a child,it always return the child currently being captured by the mouse or the child on the right.”
    Please look at the output of the console,it shows the currently found item.

    And this is the outline CSS property problem:

    Thanks!

  • #48847

    Andrew
    Keymaster

    I do not see problems with this:

    <html>
        <head>
            <title>Test</title>
            <style>
    
    	section {
    	   flow: horizontal-flow;
    	   border-spacing:4dip;
    	}
    
    	section > div { 
    	   size:64dip;
               background:gold; 
    	}
    
    	section > div:current {
    	   background:red; 	
    	}
    
            </style>
            <script type="text/tiscript">
               $(section).on("mousemove",function(evt){
                 var child = this.find(evt.x,evt.y);
                 if( child ) child.state.current = true;
               });
            </script>
        </head>
        <body>
    
           <section>
             <div>1</div>
             <div>2</div>
             <div>3</div>
             <div>4</div>
             <div>5</div>
             <div>6</div>
           </section>
    
        </body>
    </html>

    Could you modify this sample to demonstrate the problem?

    • #48849

      gaoqiangz
      Participant
      <script type="text/tiscript">
      			var elDrag = null;
                 $(section).on("mousemove",function(evt){
                   var child = this.find(evt.x,evt.y);
                   if( child ) child.state.current = true;
                 });
                 $(section).on("mousedown",function(evt){
      				if(evt.target == this) return;
      				elDrag = evt.target;
      				elDrag.capture(#strict);
                 });
                 $(section).on("mouseup",function(evt){
      				if(elDrag)
      				{
      					elDrag.capture(false);
      					elDrag = null;
      				}
                 });
              </script>
    • #48852

      Andrew
      Keymaster

      Thanks, now it is clear what you mean…

      I believe that you are setting capture on wrong element, it should be set on element where you handle those events:

                var elDrag = null;
                $(section).on("mousemove",function(evt){
                    var child = this.find(evt.x,evt.y);
                    if( child ) child.state.current = true;
                });
                $(section).on("mousedown",function(evt){
                    if(evt.target == this) return;
                    elDrag = evt.target;
                    this.capture(#strict); // NOTE: this.capture
                 });
                 $(section).on("mouseup",function(evt){
                    if(elDrag)
                    {
                      this.capture(false); // NOTE: this.capture
                      elDrag = null;
                    }
                 });

      In any case I’ll take a look on Element.find(), AFAIR it was some good reason why find() worked that way.

    • #48869

      gaoqiangz
      Participant

      thank you very much!
      Finally, please look at the outline CSS property problem when after scrolling:

You must be logged in to reply to this topic.