Swiping of dynamic pages

Hi,

I’m trying to make a calendar component, and want to be able to swipe between the months. The month is generated in JS. Any ideas / pointer to how to make functionality like this in Fuse.

<App>
	<JavaScript>
	var Observable = require('FuseJS/Observable');
	var dates = Observable();
	var monthname = Observable('');
	var year;
	var month;

	function build_month (y, m) {
		year = y;
		month = m;
		monthname.value = (m + 1) + " / " + y;
	    var m_date = new Date();
	    m_date.setYear(y);
	    m_date.setMonth(m);
	    m_date.setDate(1);
	    dates.clear();
	    var add = m_date.getDay() - 1;
	    if (add < 0) add = 6;
	    m_date.setDate(m_date.getDate() - add);
	    for (var i = 0; i < add; i++) {
	    	dates.add({
	            day: m_date.getDate(),
	            col:"#D8D8D8"
	        });
	        m_date.setDate(m_date.getDate() + 1);
	    }
	    while (m_date.getMonth() === m) {
	        dates.add({
	            day: m_date.getDate(),
	            col:"#333"
	        });
	        m_date.setDate(m_date.getDate() + 1);
	    }
	    
	    add = 7 - (m_date.getDay() - 1);
	    if (add >= 7) add = add - 7;
	    for (var i = 0; i < add; i++) {
	    	dates.add({
	            day: m_date.getDate(),
	            col:"#D8D8D8"
	        });
	        m_date.setDate(m_date.getDate() + 1);
	    }
	}

	function next_month () {
	    var m_date = new Date();
	    m_date.setYear(year);
	    m_date.setMonth(month + 1);
	    build_month(m_date.getUTCFullYear(), m_date.getMonth());
	}

	function prev_month () {
	    var m_date = new Date();
	    m_date.setYear(year);
	    m_date.setMonth(month - 1);
	    build_month(m_date.getUTCFullYear(), m_date.getMonth());
	}

	function init () {
		var d = new Date();
		year = d.getUTCFullYear();
		month = d.getMonth();
	}

	function build_current () {
		build_month(year, month);
	}

	init();
	build_current();

	module.exports = {
		dates,
		monthname,
		next_month,
		prev_month
	}

	</JavaScript>
		<Grid ColumnCount="7" >
		  <Text Value="{monthname}" ColumnSpan="7" Alignment="Center" />
		  <Button Text="Previous" ColumnSpan="4" Alignment="Left" Clicked="{prev_month}"/>
		  <Button Text="Next" ColumnSpan="3" Alignment="Right" Clicked="{next_month}"/>
		  <Text FontSize="14" Value="Ma" TextColor="#999"/>
		  <Text FontSize="14" Value="Ti" TextColor="#999"/>
		  <Text FontSize="14" Value="On" TextColor="#999"/>
		  <Text FontSize="14" Value="To" TextColor="#999"/>
		  <Text FontSize="14" Value="Fr" TextColor="#999"/>
		  <Text FontSize="14" Value="Lø" TextColor="#999"/>
		  <Text FontSize="14" Value="Sø" TextColor="#999"/>
		  <Each Items="{dates}">
		  	<Text FontSize="14" Value="{day}" TextColor="{col}"/>
		  </Each>
		</Grid>
</App>

I now created a swipe that kind of works, but it flickers.

<App>
	<JavaScript>
	var Observable = require('FuseJS/Observable');
	var dates = Observable();
	var ndates = Observable();
	var pdates = Observable();
	var monthname = Observable('');
	var year;
	var month;

	function build_obs (date, dates) {
		dates.clear();
		var m = date.getMonth();
		var add = date.getDay() - 1;
		if (add < 0) add = 6;
		date.setDate(date.getDate() - add);
		for (var i = 0; i < add; i++) {
			dates.add({
		        day: date.getDate(),
		        col:"#D8D8D8"
		    });
		    date.setDate(date.getDate() + 1);
		}
		console.log("m: " + m);
		console.log(date.getMonth());
		while (date.getMonth() === m) {
		    dates.add({
		        day: date.getDate(),
		        col:"#333"
		    });
		    date.setDate(date.getDate() + 1);
		}
		
		add = 7 - (date.getDay() - 1);
		if (add >= 7) add = add - 7;
		for (var i = 0; i < add; i++) {
			dates.add({
		        day: date.getDate(),
		        col:"#D8D8D8"
		    });
		    date.setDate(date.getDate() + 1);
		}
	}

	function build_month (y, m) {
		year = y;
		month = m;
		monthname.value = (m + 1) + " / " + y;
	    var m_date = new Date();
	    m_date.setYear(y);
	    m_date.setMonth(m);
	    m_date.setDate(1);
	    dates.clear();
	    build_obs(m_date, dates);

	    m_date = new Date();
	    m_date.setYear(y);
	    m_date.setMonth(m - 1);
	    m_date.setDate(1);
	    build_obs(m_date, pdates);

	    m_date = new Date();
	    m_date.setYear(y);
	    m_date.setMonth(m + 2);
	    m_date.setDate(1);
	    build_obs(m_date, ndates);


	}

	function next_month () {
		pdates.clear();
		pdates.replaceAll(dates.toArray());
		dates.clear();
		dates.replaceAll(ndates.toArray());
	    var m_date = new Date();
	    m_date.setDate(1);
	    m_date.setYear(year);
	    m_date.setMonth(month + 1);
	    year = m_date.getUTCFullYear();
	    month = m_date.getMonth();
	    monthname.value = (month + 1) + " / " + year;
	    m_date.setMonth(month + 1);
	    build_obs(m_date, ndates);
	}

	function prev_month () {
		ndates.clear();
		ndates.replaceAll(dates.toArray());
		dates.clear();
		dates.replaceAll(pdates.toArray());
	    var m_date = new Date();
	    m_date.setDate(1);
	    m_date.setYear(year);
	    m_date.setMonth(month - 1);
	    year = m_date.getUTCFullYear();
	    month = m_date.getMonth();
	    monthname.value = (month + 1) + " / " + year;
	    m_date.setMonth(month - 1);
	    build_obs(m_date, pdates);
	}

	function init () {
		var d = new Date();
		year = d.getUTCFullYear();
		month = d.getMonth();
	}

	function build_current () {
		build_month(year, month);
	}

	init();
	build_current();

	module.exports = {
		dates,
		ndates,
		pdates,
		monthname,
		next_month,
		prev_month
	}

	</JavaScript>
		<Grid ColumnCount="7" ux:Name="LGrid" X="-100%" Width="100%">
		  <Text Value="{monthname}" ColumnSpan="7" Alignment="Center" />
		  <Button Text="Previous" ColumnSpan="4" Alignment="Left" Clicked="{prev_month}"/>
		  <Button Text="Next" ColumnSpan="3" Alignment="Right" Clicked="{next_month}"/>
		  <Text FontSize="14" Value="Ma" TextColor="#999"/>
		  <Text FontSize="14" Value="Ti" TextColor="#999"/>
		  <Text FontSize="14" Value="On" TextColor="#999"/>
		  <Text FontSize="14" Value="To" TextColor="#999"/>
		  <Text FontSize="14" Value="Fr" TextColor="#999"/>
		  <Text FontSize="14" Value="Lø" TextColor="#999"/>
		  <Text FontSize="14" Value="Sø" TextColor="#999"/>
		  <Each Items="{pdates}">
		  	<Text FontSize="14" Value="{day}" TextColor="{col}"/>
		  </Each>
		</Grid>
		<Grid ColumnCount="7" ux:Name="CGrid">
		  <Text Value="{monthname}" ColumnSpan="7" Alignment="Center" />
		  <Button Text="Previous" ColumnSpan="4" Alignment="Left" Clicked="{prev_month}"/>
		  <Button Text="Next" ColumnSpan="3" Alignment="Right" Clicked="{next_month}"/>
		  <Text FontSize="14" Value="Ma" TextColor="#999"/>
		  <Text FontSize="14" Value="Ti" TextColor="#999"/>
		  <Text FontSize="14" Value="On" TextColor="#999"/>
		  <Text FontSize="14" Value="To" TextColor="#999"/>
		  <Text FontSize="14" Value="Fr" TextColor="#999"/>
		  <Text FontSize="14" Value="Lø" TextColor="#999"/>
		  <Text FontSize="14" Value="Sø" TextColor="#999"/>
		  <Each Items="{dates}">
		  	<Text FontSize="14" Value="{day}" TextColor="{col}"/>
		  </Each>
		  <SwipeGesture ux:Name="swiper" Direction="Right" LengthNode="CGrid" />
		  <SwipingAnimation Source="swiper">
            <Move X="1" RelativeTo="Size" RelativeNode="CGrid" />
            <Move X="1" Target="LGrid" RelativeTo="Size" RelativeNode="CGrid" />
		  </SwipingAnimation>
		  <Swiped Source="swiper">
		  	<Callback Handler="{prev_month}"/>
		  </Swiped>
		  <SwipeGesture ux:Name="swipel" Direction="Left" LengthNode="CGrid" />
		  <SwipingAnimation Source="swipel">
            <Move X="-1" RelativeTo="Size" RelativeNode="CGrid" />
            <Move X="-1" Target="RGrid" RelativeTo="Size" RelativeNode="CGrid" />
		  </SwipingAnimation>
		  <Swiped Source="swipel">
		  	<Callback Handler="{next_month}"/>
		  	<DebugAction Message="Next!" />
		  </Swiped>
		</Grid>
		<Grid ColumnCount="7" ux:Name="RGrid" X="100%" Width="100%">
		  <Text Value="{monthname}" ColumnSpan="7" Alignment="Center" />
		  <Button Text="Previous" ColumnSpan="4" Alignment="Left" Clicked="{prev_month}"/>
		  <Button Text="Next" ColumnSpan="3" Alignment="Right" Clicked="{next_month}"/>
		  <Text FontSize="14" Value="Ma" TextColor="#999"/>
		  <Text FontSize="14" Value="Ti" TextColor="#999"/>
		  <Text FontSize="14" Value="On" TextColor="#999"/>
		  <Text FontSize="14" Value="To" TextColor="#999"/>
		  <Text FontSize="14" Value="Fr" TextColor="#999"/>
		  <Text FontSize="14" Value="Lø" TextColor="#999"/>
		  <Text FontSize="14" Value="Sø" TextColor="#999"/>
		  <Each Items="{ndates}">
		  	<Text FontSize="14" Value="{day}" TextColor="{col}"/>
		  </Each>
		</Grid>
</App>

I made an example that does calendar navigation, using actual navigation between the pages:

It’s not yet been merged to main fuse-sample repository, but you can see if on the branch there above.

<3

If I put the calNav inside a PageControl like this:

<PageControl>
  <MainPage ux:Name="_wrong_" />
  <CalendarView ux:Name="calendar" />
</PageControl>

I get

Error: Unable to navigate to route: main/_wrong_/month?{"month":1,"year":2017} in Fuse.Navigation.Router

Is there a way to initialize this, without using gotoRelative?

You can just leave out that JS code. It’ll be initialized when you first navigate to there from some other page. The push relative is just a way to get the example started by navigating to the current month.

Thank you! Got it working.

But since I have a PageControl high in my hiearchy I think it get initialized, and then relative will use the current path, and not the path that is relative to the viewNode. I ended up doing this for the next and prev bookmark:

router.bookmark({
	name: "prevMonth",
	relative: pageControl,
	path: [ 
		"kalender", null, 
		"overview", null, 
		"calendar", null,
		"month", { month: p.getMonth(), year: p.getFullYear() } ]
})

Is there a way to do this like you did, and not hardcode the paths higher in the hierarchy? I feel that this is kind of a bug.

This might be a bug in the relative paths. There are not supposed to be using the current path, but actually the one they are relative. Maybe it doesn’t work right if that isn’t the current path. I’ll take a look at this.

Yes. It worked with relative paths if the calendar page was in the first in the PageControl, but I get an error if it is instansiated, without being the current.