PageControl, ScrollView, Draggable, Grid

Hello guys,

I’m doing a proof of concept to see if Fuse has what is necessary to make a more complex app with the funcionalities I need, but I’ve bumped in some difficulties.

First of all, my goal is doing something like this:

I will have 3 major components:

  • A horizontal bar with the days (pageControl in the image), with lazy loading of the data
  • A scrollview with the user names
  • A grid with the content that maps days with users

The basic funcionality will be:

  • The content should scroll up and down with the user’s scrollview
  • The content should swipe left and right with the day’s page control

More complex funcionatilies are:

  • I should be able to drag a user to some cell in the grid (and know which cell the user is dropped)
  • I should be able to drag content in a cell and drop it on other cell (and know from which cell it was drag and to which cell is dropped)
  • I should be able to load the grid with the content in the right cells

I’ve done a minimal reproduction just to test what I can do with this idea (ready to copy, paste and run, it looks better with a landscape preview).

<App>

	<JavaScript>
		var Observable = require("FuseJS/Observable");

		var resources = Observable();
		for(var i = 0 ; i < 20 ; i++){
			resources.add({name : "user " + i})
		}
		
		var resourcesLenght = Observable(resources.length);

		var cells = [];
		for(var i = 0 ; i < 5 ; i++){
			for(var j = 0 ; j < resources.length ; j++){
				cells.push({x: i , y : j});
			}
		}

		var daysOfTheYear = Observable();
		var day = 0;
		for(var i = 0 ; i < 3 ; i++ ){
			var aux = [];
			var cell = [];
			cell.push(cells.filter(function(o){ return o.x === i;}))
			for(var j = 1 ; j <= 5 ; j++){
				aux.push({day : "day " + (day + 1), cells : cell})
				day++;
			}
			daysOfTheYear.add({days : aux})
		}
	
		module.exports = {
			resources : resources,
			resourcesLenght : resourcesLenght,
			daysOfTheYear : daysOfTheYear,
			cells : cells
		}

	</JavaScript>

	<DockPanel>

		<StatusBarBackground Dock="Top" Background="White" />
		
		<DockPanel>
			<!-- When dragging an element it goes behing the other elements, can't I drag it outside this DockPanel? -->
			<DockPanel Dock="Left" Width="150">
				<Panel Color="Gray" Height="51" Dock="Top"/>
				<ScrollView>
					<!-- users list -->
					<StackPanel ux:Name="ResourcesList" Width="150">
						<Each Items="{resources}">
						   <!-- When the resource is dragged and not dropped in any booking then it returns to the original place -->
						   <!-- This draw two rectangles because I don't want the "space" in the scrollview to be empty -->
							<Panel Physics.IsPhysicsWorld="true">
								<Rectangle Height="50">
									<Stroke Width="1" Color="Gray" />
									<Text Value="{name}" Margin="5,0,5,0" Alignment="Center"/>
									<Draggable/>
								</Rectangle>
								<PointAttractor Radius="500" Strength="100" Exclusive="True"/>
								<Rectangle Height="50">
									<Stroke Width="1" Color="Gray" />
									<Text Value="{name}" Margin="5,0,5,0" Alignment="Center"/>
								</Rectangle>
							</Panel>
						</Each>
					</StackPanel>
				</ScrollView>
			</DockPanel>
			
			<!-- Date bar / content-->
			<Panel>
				<PageControl ux:Name="pageControl" Transition="None" InactiveState="Disabled">
						<Each Items="{daysOfTheYear}">
							<!-- Day bar -->
							<Grid ux:Name="item" Rows="52,auto">
								<Activated>
									<Callback Handler="{activated}" />
								</Activated>
								<Grid Columns="1*, 1*, 1*, 1*, 1*" ux:Name="tabItem">
									<Each Items="{days}" >
										<Rectangle Height="52">
											<Stroke Width="1" Color="White" />
											<SolidColor Color="Gray" />
											<Text Value="{day}" Margin="5,0,5,0" Alignment="Center"/>
										</Rectangle>
									</Each>
								</Grid>
								<!-- Content -->
								<ScrollView>
									<StackPanel>
										<Grid Columns="1*, 1*, 1*, 1*, 1*" ux:Name="tabItem2">
											<Each Items="{cells}" >
												<Rectangle Height="50">
													<Stroke Width="1" Color="Gray" />
													<Text Value="{x},{y}" Margin="5,0,5,0" Alignment="Center"/>
												</Rectangle>
											</Each>
										</Grid>
									</StackPanel>
								</ScrollView>

								<EnteringAnimation Scale="1">
									<Move X="-1" RelativeTo="Size"/>
								</EnteringAnimation>
								<ExitingAnimation Scale="1">
									<Move X="1" RelativeTo="Size"/>
								</ExitingAnimation>
							</Grid>
						</Each>
				</PageControl>
			</Panel>
		</DockPanel>
	</DockPanel>
</App>

What I can do:

  • Swipe the content left and right (I chose a panel control, because I want to show always 5 days at a time)
  • When I’m trying to drag a user, if I release the element it goes back to the original position
  • When I drag the element with user, it is still shown a element with the user (this was achieve by drawing the same element twice, the top one draggable)

What I can’t do:

  • I cannot scroll both the resources and the content synchronously (I’ve tried this solution)
  • I cannot even scroll the content until the end
  • I’m not able to drag the user to the grid. I supposed I cannot drag the element outside the scrollview it is wrapped

I’ve already made a forum post about the drag and drop functionality inside the grid here.

These are core functionalities in the app, so if it’s not possible to make it then the app won’t be implemented with Fuse (unfortunately).

Maybe I’m seeing things in a wrong way and there is a better, more efficient and simpler way to achieve this.

Does someone have any ideas that can throw in my direction to check if I can make this work?

Thanks in advance.

Does anyone have some ideas, please?

Hey.

For content sync I tried solution you mentioned and it works in one way - when I scroll content user’s scrollview scrolls with me. To make it working in both ways, you could separate components and make classes with properties for each component.
I think using properties and knowing that you can pass observables through properties you could achieve drag and drop functionality. See this example for drag and drop.

Here is modified code with synchronised scrollview:

<App>

    <JavaScript>
        var Observable = require("FuseJS/Observable");

        var resources = Observable();
        for(var i = 0 ; i < 20 ; i++){
            resources.add({name : "user " + i})
        }
        
        var resourcesLenght = Observable(resources.length);

        var cells = [];
        for(var i = 0 ; i < 5 ; i++){
            for(var j = 0 ; j < resources.length ; j++){
                cells.push({x: i , y : j});
            }
        }

        var daysOfTheYear = Observable();
        var day = 0;
        for(var i = 0 ; i < 3 ; i++ ){
            var aux = [];
            var cell = [];
            cell.push(cells.filter(function(o){ return o.x === i;}))
            for(var j = 1 ; j <= 5 ; j++){
                aux.push({day : "day " + (day + 1), cells : cell})
                day++;
            }
            daysOfTheYear.add({days : aux})
        }
    
        module.exports = {
            resources : resources,
            resourcesLenght : resourcesLenght,
            daysOfTheYear : daysOfTheYear,
            cells : cells
        }

    </JavaScript>

    <DockPanel>

        <StatusBarBackground Dock="Top" Background="White" />
        
        <Grid ColumnCount="2" Columns="150, 1*">
            <!-- When dragging an element it goes behing the other elements, can't I drag it outside this DockPanel? -->
            <DockPanel>
                <Panel Color="Gray" Height="51" Dock="Top" />
                <ScrollView ux:Name="sw" UserScroll="false">
                    <!-- users list -->
                    <StackPanel ux:Name="ResourcesList" Width="150">
                        <Each Items="{resources}">
                           <!-- When the resource is dragged and not dropped in any booking then it returns to the original place -->
                           <!-- This draw two rectangles because I don't want the "space" in the scrollview to be empty -->
                            <Panel>
                                <Rectangle Height="50">
                                    <Stroke Width="1" Color="Gray" />
                                    <Text Value="{name}" Margin="5,0,5,0" Alignment="Center" />
                                </Rectangle>
                                <Rectangle Height="50">
                                    <Stroke Width="1" Color="Gray" />
                                    <Text Value="{name}" Margin="5,0,5,0" Alignment="Center" />
                                </Rectangle>
                            </Panel>
                        </Each>
                    </StackPanel>
                </ScrollView>
            </DockPanel>
            
            <!-- Date bar / content-->
            <Panel>
                <PageControl ux:Name="pageControl" Transition="None" InactiveState="Disabled" IsRouterOutlet="false">
                    <Each Items="{daysOfTheYear}">
                        <!-- Day bar -->
                        <DockPanel>
                        <Activated>
                            <Callback Handler="{activated}" />
                        </Activated>
                            <Grid Dock="Top" Columns="1*, 1*, 1*, 1*, 1*" ux:Name="tabItem">
                                <Each Items="{days}">
                                    <Rectangle Height="52">
                                        <Stroke Width="1" Color="White" />
                                        <SolidColor Color="Gray" />
                                        <Text Value="{day}" Margin="5,0,5,0" Alignment="Center" />
                                    </Rectangle>
                                </Each>
                            </Grid>
                            <!-- Content -->
                            <ScrollView>
                                <StackPanel>
                                    <Grid Columns="1*, 1*, 1*, 1*, 1*" ux:Name="tabItem2">
                                        <Each Items="{cells}">
                                            <Rectangle Height="50">
                                                <Stroke Width="1" Color="Gray" />
                                                <Text Value="{x},{y}" Margin="5,0,5,0" Alignment="Center" />
                                            </Rectangle>
                                        </Each>
                                    </Grid>
                                </StackPanel>
                                <ScrollingAnimation>
                                    <Change sw.RelativeScrollPosition="1,1" />
                                </ScrollingAnimation>
                            </ScrollView>

                            <EnteringAnimation Scale="1">
                                <Move X="-1" RelativeTo="Size" />
                            </EnteringAnimation>
                            <ExitingAnimation Scale="1">
                                <Move X="1" RelativeTo="Size" />
                            </ExitingAnimation>
                        </DockPanel>
                    </Each>
                </PageControl>
            </Panel>
        </Grid>
    </DockPanel>
</App>

Hope this helps.