Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Multiple calendar control in jQuery Accordion (Read 9255 times)
Xylon
Junior Member
**
Offline


I Love MindFusion!

Posts: 96
Joined: Feb 17th, 2014
Multiple calendar control in jQuery Accordion
Jun 10th, 2014 at 4:59pm
Print Post  
Hi,

I was trying put four calendar control in a page with jQuery accordion so that I could collapse and expand them.  But there is a error confused for a long time. This page works well on chrome, but once work on IE, when I try to resize the IE window, I mean if it's maximized at this moment then I click "Restore down" button between "Minimize" and "Close", then visual studio will pop up an error as attachment 1. This only happen on IE. And if I only put some word paragraphs in stead of mindfusion calendar control, page also works on IE. I guess there are some size conflict bwtween the calendar control and jQuery?


My code:
Code
Select All
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="test1.aspx.cs" Inherits="me.test1" %>
<%@ Register Assembly="MindFusion.Scheduling.WebForms" Namespace="MindFusion.Scheduling.WebForms"
    TagPrefix="MindFusion" %>

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
  <script src="//code.jquery.com/jquery-1.10.2.js"></script>
  <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>

  <script>
      $(function () {
          $("#accordion").accordion();
      });
  </script>


<div id="accordion">
  <h3>Section 1</h3>
  <div>
    <MindFusion:Calendar ID="calendar1" runat="server" Height="500px" Width="100%" Theme="Vista"
                    CurrentView="ResourceView" Culture="(Default)" AutoPostBack="false" >
                    </MindFusion:Calendar>
  </div>
  <h3>Section 2</h3>
  <div>
    <MindFusion:Calendar ID="calendar2" runat="server" Height="500px" Width="100%" Theme="Vista"
                    CurrentView="ResourceView" Culture="(Default)" AutoPostBack="false" >
                    </MindFusion:Calendar>
  </div>
  <h3>Section 3</h3>
  <div>
    <MindFusion:Calendar ID="calendar3" runat="server" Height="500px" Width="100%" Theme="Vista"
                    CurrentView="ResourceView" Culture="(Default)" AutoPostBack="false" >
                    </MindFusion:Calendar>
  </div>
  <h3>Section 4</h3>
  <div>
  <MindFusion:Calendar ID="calendar4" runat="server" Height="500px" Width="100%" Theme="Vista"
                    CurrentView="ResourceView" Culture="(Default)" AutoPostBack="false" >
                    </MindFusion:Calendar>
  </div>
</div>

</asp:Content>
 



And my master page is simple:
Code
Select All
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Master.cs" Inherits="Me.Site" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head id="Head1" runat="server">
	<title></title>
	<link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
    <!--link href="~/Styles/bootstrap.css" rel="stylesheet" type="text/css" /-->
    <!--link href="~/Styles/bootstrap.min.css" rel="stylesheet" type="text/css" /-->
	<asp:ContentPlaceHolder ID="HeadContent" runat="server">

	</asp:ContentPlaceHolder>
</head>

<body>
	<form id="Form1" runat="server">
	<asp:ScriptManager ID="ScriptManager1" runat="server" />
	<div class="page">
		<div class="header">
			<div class="title">
				<h1>

				</h1>
			</div>
			<div class="clear hideSkiplink">
				<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false"
					IncludeStyleBlock="false" Orientation="Horizontal" >
					<Items>
						<asp:MenuItem NavigateUrl="~/Default.aspx" Text="def" />

                        <asp:MenuItem NavigateUrl="~/test2.aspx" Text="test2" />

                        <asp:MenuItem NavigateUrl="test3.aspx" Text="test3" />

					</Items>

				</asp:Menu>
			</div>
		</div>
		<div class="main">
			<asp:ContentPlaceHolder ID="MainContent" runat="server" />
		</div>

	</div>

	</form>
</body>
</html>
 



Reference: http://jqueryui.com/accordion/

I also tried to use jQuery toggle-box, which is similar with accordion, but has the same issue. Tried many different methods like put minimum size for each section to hold the calendar control, but still does't work.

Do you have any idea?

I appreciate! 
  

q23.JPG (Attachment deleted)
Back to top
 
IP Logged
 
Lyubo
God Member
*****
Offline


MindFusion team

Posts: 511
Joined: Jun 17th, 2010
Re: Multiple calendar control in jQuery Accordion
Reply #1 - Jun 11th, 2014 at 8:56am
Print Post  
Hi,

It seems that the jQuery accordion uses display: none; to collapse pages, which messes up some of the sizing computations that the calendar control does. We will provide a fix for that in the next release, but in the meantime, you can use the following workaround:

Code (Javascript)
Select All
var originalGetDimensions = MindFusion.Scheduling.ResourceView.prototype.getDimensions;
MindFusion.Scheduling.ResourceView.prototype.getDimensions = function (e) {
    if ($mindfusion(this._calendar.get_element()).is(":hidden")) { return; }
    originalGetDimensions.apply(this, [e]);
}; 



In addition to that, you'll need to recalculate the dimensions of the control when its parent accordion page is expanded. To do that, call the adjust method of the calendar in the accordion's Activate handler:

Code (Javascript)
Select All
$(function () {
    $("#accordion").accordion({ activate: function (event, ui) {
        var plannerDiv = ui.newPanel.find('div.WebPlannerResourceView')[0];
        if (plannerDiv)
            plannerDiv.Calendar.adjust();
        }
    });
}); 



If the adjustments in the sizes are visible during the opening of a calendar's accordion item - that can happen if animations on the Accordion control are enabled - you may consider disabling the animations or using an overlay div over the calendar to hide it until the adjustments are complete. You can use calendar's own built-in overlay. To do that, modify the accordion initialization code like this:

Code (Javascript)
Select All
$(function () {
    $("#accordion").accordion({
        animate: true, /*false - to disable animations*/
        beforeActivate: function (event, ui) {
            var jqPlanner = ui.newPanel.find('div.WebPlannerResourceView');
            if (jqPlanner) {
                jqPlanner.children().append("<div class=\"WebPlannerLoader\"></div>");
            }
        },
        activate: function (event, ui) {
            var plannerDiv = ui.newPanel.find('div.WebPlannerResourceView')[0];
            if (plannerDiv) {
                plannerDiv.Calendar.adjust();
                plannerDiv.Calendar.endInit();
            }
        }
    });
}); 



Regards,
Lyubo
  
Back to top
 
IP Logged
 
Xylon
Junior Member
**
Offline


I Love MindFusion!

Posts: 96
Joined: Feb 17th, 2014
Re: Multiple calendar control in jQuery Accordion
Reply #2 - Jun 12th, 2014 at 2:21pm
Print Post  
Honestly I don't quite understand your code lol.

In the first snippet "function (e)", what is the "e"? event? when the function is invoked the event is passed to the function itself?

Then judge the condition if calendar is not hidden return the original size?

For the snippet two and three, how do you get function (event, ui)? 

I need to take some times to understand it...

Thank you very much!

Lyubo wrote on Jun 11th, 2014 at 8:56am:
Hi,

It seems that the jQuery accordion uses display: none; to collapse pages, which messes up some of the sizing computations that the calendar control does. We will provide a fix for that in the next release, but in the meantime, you can use the following workaround:

Code (Javascript)
Select All
var originalGetDimensions = MindFusion.Scheduling.ResourceView.prototype.getDimensions;
MindFusion.Scheduling.ResourceView.prototype.getDimensions = function (e) {
    if ($mindfusion(this._calendar.get_element()).is(":hidden")) { return; }
    originalGetDimensions.apply(this, [e]);
}; 



In addition to that, you'll need to recalculate the dimensions of the control when its parent accordion page is expanded. To do that, call the adjust method of the calendar in the accordion's Activate handler:

Code (Javascript)
Select All
$(function () {
    $("#accordion").accordion({ activate: function (event, ui) {
        var plannerDiv = ui.newPanel.find('div.WebPlannerResourceView')[0];
        if (plannerDiv)
            plannerDiv.Calendar.adjust();
        }
    });
}); 



If the adjustments in the sizes are visible during the opening of a calendar's accordion item - that can happen if animations on the Accordion control are enabled - you may consider disabling the animations or using an overlay div over the calendar to hide it until the adjustments are complete. You can use calendar's own built-in overlay. To do that, modify the accordion initialization code like this:

Code (Javascript)
Select All
$(function () {
    $("#accordion").accordion({
        animate: true, /*false - to disable animations*/
        beforeActivate: function (event, ui) {
            var jqPlanner = ui.newPanel.find('div.WebPlannerResourceView');
            if (jqPlanner) {
                jqPlanner.children().append("<div class=\"WebPlannerLoader\"></div>");
            }
        },
        activate: function (event, ui) {
            var plannerDiv = ui.newPanel.find('div.WebPlannerResourceView')[0];
            if (plannerDiv) {
                plannerDiv.Calendar.adjust();
                plannerDiv.Calendar.endInit();
            }
        }
    });
}); 



Regards,
Lyubo

  
Back to top
 
IP Logged
 
Lyubo
God Member
*****
Offline


MindFusion team

Posts: 511
Joined: Jun 17th, 2010
Re: Multiple calendar control in jQuery Accordion
Reply #3 - Jun 15th, 2014 at 12:43pm
Print Post  
Hi,

In the getDimensions overload, the "e" is just a parameter that is passed to the function. The actual name is irrelevant, with the condition that it must match the variable name in the method body. The function itself is invoked internally by the control when it needs to recalculate its bounds and positioning. When the calendar is hidden by using display:none, its dimensions cannot be determined and the calculations return incorrect results, hence the error you were seeing. The solution is not to run these calculations when the calendar is currently hidden.

In the second and third snippet, the "beforeActivate" and "activate" parameters are used to pass method handlers for the respective Accordion events. You can find additional information about this in the Accordion documentation files here.

Regards,
Lyubo
  
Back to top
 
IP Logged
 
Xylon
Junior Member
**
Offline


I Love MindFusion!

Posts: 96
Joined: Feb 17th, 2014
Re: Multiple calendar control in jQuery Accordion
Reply #4 - Jun 17th, 2014 at 6:15pm
Print Post  
Appreciate that

Lyubo wrote on Jun 15th, 2014 at 12:43pm:
Hi,

In the getDimensions overload, the "e" is just a parameter that is passed to the function. The actual name is irrelevant, with the condition that it must match the variable name in the method body. The function itself is invoked internally by the control when it needs to recalculate its bounds and positioning. When the calendar is hidden by using display:none, its dimensions cannot be determined and the calculations return incorrect results, hence the error you were seeing. The solution is not to run these calculations when the calendar is currently hidden.

In the second and third snippet, the "beforeActivate" and "activate" parameters are used to pass method handlers for the respective Accordion events. You can find additional information about this in the Accordion documentation files here.

Regards,
Lyubo

  
Back to top
 
IP Logged
 
Xylon
Junior Member
**
Offline


I Love MindFusion!

Posts: 96
Joined: Feb 17th, 2014
Re: Multiple calendar control in jQuery Accordion
Reply #5 - Jun 20th, 2014 at 10:16pm
Print Post  
Is that possible to add another dropdown list on the "New appointment" window?

I mean by default the "New appointment" window has a textbox to input new app headtext, then a dropdown list to select available location, then another dropdown list in parallel to or below location dropdown list.

Appointment has task and resource collections to contains data for the new dropdown list.

Thanks!

Lyubo wrote on Jun 15th, 2014 at 12:43pm:
Hi,

In the getDimensions overload, the "e" is just a parameter that is passed to the function. The actual name is irrelevant, with the condition that it must match the variable name in the method body. The function itself is invoked internally by the control when it needs to recalculate its bounds and positioning. When the calendar is hidden by using display:none, its dimensions cannot be determined and the calculations return incorrect results, hence the error you were seeing. The solution is not to run these calculations when the calendar is currently hidden.

In the second and third snippet, the "beforeActivate" and "activate" parameters are used to pass method handlers for the respective Accordion events. You can find additional information about this in the Accordion documentation files here.

Regards,
Lyubo

  
Back to top
 
IP Logged
 
Lyubo
God Member
*****
Offline


MindFusion team

Posts: 511
Joined: Jun 17th, 2010
Re: Multiple calendar control in jQuery Accordion
Reply #6 - Jun 22nd, 2014 at 10:28am
Print Post  
Hi,

It is possible, but since the popup control doesn't have built-in support for tasks and resources, it will require some tricks to make this work.

What you can do is build on the techniques used in this topic. and add logic for the property changes. Something like:

Code (Javascript)
Select All
<script type="text/javascript">

    var drawContentOriginal = MindFusion.Scheduling.EditForm.prototype.drawContent;
    MindFusion.Scheduling.EditForm.prototype.drawContent = function() {

        drawContentOriginal.apply(this, arguments);

        // Hide some controls that won't be used.
        this._content.find('div.reminder-row')[0].style.display = 'none';
        this._content.find('div.hr-line')[1].style.display = 'none';
        this._content.find('table')[1].parentNode.style.display = 'none';

        // Indentify the parent Div element that will contain the new drop-downs.
        var parentDiv = $mindfusion(this.getControls()['location'].element.parentNode);

        // Create the tasks drop-down and add it to the parent Div.
        var tasksDropDown = this.createDropDownList({ id: "task", items: getTasks(this.calendar), initValue: getTaskIndex(this.calendar, this.item) });
        tasksDropDown.element.style.width = "45%";
        var row = this._getNewRow().append('<span class="text-label">Task: </span>').append(tasksDropDown.element);
        parentDiv.append(row);
        this.addControl(tasksDropDown);

        // Create the resources drop-down and add it to the parent Div.
        var resourcesDropDown = this.createDropDownList({ id: "resource", items: getResources(this.calendar), initValue: getResourceIndex(this.calendar, this.item) });
        resourcesDropDown.element.style.width = "45%";
        row = this._getNewRow().append('<span class="text-label">Resource: </span>').append(resourcesDropDown.element);
        parentDiv.append(row);
        this.addControl(resourcesDropDown);
    };

    var _getChangesOriginal = MindFusion.Scheduling.EditForm.prototype._getChanges;
    MindFusion.Scheduling.EditForm.prototype._getChanges = function(type) {
        var args = _getChangesOriginal.apply(this, arguments);
        if (args == null) {
            var changed = type == 'new';
            args = {};
        }
        else {
            var changed = true;
        }
        var currentItem = this.item;

        //task
        var index = this.getControls()["task"].getValue();
        if (index.length > 0) {
            //task changed
            var appItemTask = this.calendar.getTasks()[index].id;
        }
        else {
            //task cleared
            var appItemTask = null;
        }
        if (appItemTask != currentItem.task) {
            changed = true;
            args.task = appItemTask;
        }
        if (type == 'new' && appItemTask) {
            args.task = appItemTask;
        }

        //resource
        index = this.getControls()["resource"].getValue();
        if (index.length > 0) {
            //resource changed
            var appItemRes = this.calendar.getResources()[index].id;
        }
        else {
            //resource cleared
            var appItemRes = null;
        }
        if (appItemRes) {
            if (!currentItem.resources || currentItem.resources.length == 0 || currentItem.resources[0] != appItemRes) {
                changed = true;
                args.resources = [appItemRes];
            }
        }
        else {
            if (currentItem.resources && currentItem.resources.length != 0) {
                changed = true;
                args.resources = null;
            }
        }

        if (changed) {
            args.id = currentItem.id;
            args.occurrenceIndex = currentItem.occurrenceIndex;
            return args;
        }
        return null;
    };


    // Helper methods
    function getTasks(calendar) {
        var list = null;
        if (calendar != null)
            list = calendar.getTasks();
        if (list != null) {
            var result = new Array();
            for (var l in list) {
                if (list[l] != null) {
                    result.push({ value: l, text: list[l].name || list[l].text });
                }
            }
            return result;
        }
        return null;
    }

    function getTaskIndex(calendar, item) {
        if (item != null && item.getTask) {
            var task = item.getTask();
            if (task != null) {
                for (var i = 0, tasks = calendar.getTasks(), l = tasks.length; i < l; i++) {
                    if (task.id == tasks[i].id) {
                        return i;
                    }
                }
            }
        }
        return -1;
    }

    function getResources(calendar) {
        var list = null;
        if (calendar != null)
            list = calendar.getResources();
        if (list != null) {
            var result = new Array();
            for (var l in list) {
                if (list[l] != null) {
                    result.push({ value: l, text: list[l].name });
                }
            }
            return result;
        }
        return null;
    }

    function getResourceIndex(calendar, item) {
        if (item != null && item.getResources) {
            var res = item.getResources()[0];
            if (res != null) {
                for (var i = 0, resources = calendar.getResources(), l = resources.length; i < l; i++) {
                    if (res.id == resources[i].id) {
                        return i;
                    }
                }
            }
        }
        return -1;
    }
</script> 



In the above snippet, an EditForm.drawContent override is used to add two new drop-down lists to the popup - for tasks and resources. The EditForm._getChanges override is responsible for updating the item if the there were changes in the task/resources property values. The rest are some helper methods, used to populate the task and resource collection values in the popup.

Regards,
Lyubo
« Last Edit: Jun 23rd, 2014 at 6:19am by Lyubo »  
Back to top
 
IP Logged
 
Xylon
Junior Member
**
Offline


I Love MindFusion!

Posts: 96
Joined: Feb 17th, 2014
Re: Multiple calendar control in jQuery Accordion
Reply #7 - Jun 24th, 2014 at 2:07pm
Print Post  
Thank you a tons.

Now I see what my error was. I didn't update the new collection via EditForm._getChanges and missed some of the conditions judgement.

Lyubo wrote on Jun 22nd, 2014 at 10:28am:
Hi,

It is possible, but since the popup control doesn't have built-in support for tasks and resources, it will require some tricks to make this work.

What you can do is build on the techniques used in this topic. and add logic for the property changes. Something like:

Code (Javascript)
Select All
<script type="text/javascript">

    var drawContentOriginal = MindFusion.Scheduling.EditForm.prototype.drawContent;
    MindFusion.Scheduling.EditForm.prototype.drawContent = function() {

        drawContentOriginal.apply(this, arguments);

        // Hide some controls that won't be used.
        this._content.find('div.reminder-row')[0].style.display = 'none';
        this._content.find('div.hr-line')[1].style.display = 'none';
        this._content.find('table')[1].parentNode.style.display = 'none';

        // Indentify the parent Div element that will contain the new drop-downs.
        var parentDiv = $mindfusion(this.getControls()['location'].element.parentNode);

        // Create the tasks drop-down and add it to the parent Div.
        var tasksDropDown = this.createDropDownList({ id: "task", items: getTasks(this.calendar), initValue: getTaskIndex(this.calendar, this.item) });
        tasksDropDown.element.style.width = "45%";
        var row = this._getNewRow().append('<span class="text-label">Task: </span>').append(tasksDropDown.element);
        parentDiv.append(row);
        this.addControl(tasksDropDown);

        // Create the resources drop-down and add it to the parent Div.
        var resourcesDropDown = this.createDropDownList({ id: "resource", items: getResources(this.calendar), initValue: getResourceIndex(this.calendar, this.item) });
        resourcesDropDown.element.style.width = "45%";
        row = this._getNewRow().append('<span class="text-label">Resource: </span>').append(resourcesDropDown.element);
        parentDiv.append(row);
        this.addControl(resourcesDropDown);
    };

    var _getChangesOriginal = MindFusion.Scheduling.EditForm.prototype._getChanges;
    MindFusion.Scheduling.EditForm.prototype._getChanges = function(type) {
        var args = _getChangesOriginal.apply(this, arguments);
        if (args == null) {
            var changed = type == 'new';
            args = {};
        }
        else {
            var changed = true;
        }
        var currentItem = this.item;

        //task
        var index = this.getControls()["task"].getValue();
        if (index.length > 0) {
            //task changed
            var appItemTask = this.calendar.getTasks()[index].id;
        }
        else {
            //task cleared
            var appItemTask = null;
        }
        if (appItemTask != currentItem.task) {
            changed = true;
            args.task = appItemTask;
        }
        if (type == 'new' && appItemTask) {
            args.task = appItemTask;
        }

        //resource
        index = this.getControls()["resource"].getValue();
        if (index.length > 0) {
            //resource changed
            var appItemRes = this.calendar.getResources()[index].id;
        }
        else {
            //resource cleared
            var appItemRes = null;
        }
        if (appItemRes) {
            if (!currentItem.resources || currentItem.resources.length == 0 || currentItem.resources[0] != appItemRes) {
                changed = true;
                args.resources = [appItemRes];
            }
        }
        else {
            if (currentItem.resources && currentItem.resources.length != 0) {
                changed = true;
                args.resources = null;
            }
        }

        if (changed) {
            args.id = currentItem.id;
            args.occurrenceIndex = currentItem.occurrenceIndex;
            return args;
        }
        return null;
    };


    // Helper methods
    function getTasks(calendar) {
        var list = null;
        if (calendar != null)
            list = calendar.getTasks();
        if (list != null) {
            var result = new Array();
            for (var l in list) {
                if (list[l] != null) {
                    result.push({ value: l, text: list[l].name || list[l].text });
                }
            }
            return result;
        }
        return null;
    }

    function getTaskIndex(calendar, item) {
        if (item != null && item.getTask) {
            var task = item.getTask();
            if (task != null) {
                for (var i = 0, tasks = calendar.getTasks(), l = tasks.length; i < l; i++) {
                    if (task.id == tasks[i].id) {
                        return i;
                    }
                }
            }
        }
        return -1;
    }

    function getResources(calendar) {
        var list = null;
        if (calendar != null)
            list = calendar.getResources();
        if (list != null) {
            var result = new Array();
            for (var l in list) {
                if (list[l] != null) {
                    result.push({ value: l, text: list[l].name });
                }
            }
            return result;
        }
        return null;
    }

    function getResourceIndex(calendar, item) {
        if (item != null && item.getResources) {
            var res = item.getResources()[0];
            if (res != null) {
                for (var i = 0, resources = calendar.getResources(), l = resources.length; i < l; i++) {
                    if (res.id == resources[i].id) {
                        return i;
                    }
                }
            }
        }
        return -1;
    }
</script> 



In the above snippet, an EditForm.drawContent override is used to add two new drop-down lists to the popup - for tasks and resources. The EditForm._getChanges override is responsible for updating the item if the there were changes in the task/resources property values. The rest are some helper methods, used to populate the task and resource collection values in the popup.

Regards,
Lyubo

  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint