2

I am using primefaces p:schedule component to display events as shown here . p:schedule

These events can be draggable if we set property draggable="true" and with event 'eventMove'.

I have two type of events, which I can differntiate by using their 'title'

I want type1 events to be draggable and type 2 not to be draggable.

How can I achieve it? As we provide syntax to become draggable events in this way.

<p:schedule value="#{scheduleController.eventModel}" widgetVar="myschedule" draggable="true">  

        <p:ajax event="dateSelect" listener="#{scheduleController.onDateSelect}" update="eventDetails" oncomplete="eventDialog.show()" />  
        <p:ajax event="eventSelect" listener="#{scheduleController.onEventSelect}" update="eventDetails" oncomplete="eventDialog.show()" />  
        <p:ajax event="eventMove" listener="#{scheduleController.onEventMove}" update="messages" />  


    </p:schedule>
Mindwin Remember Monica
  • 1,469
  • 2
  • 20
  • 35
Java
  • 2,451
  • 10
  • 48
  • 85
  • try to set `draggable="false"` , than inspect your generated schedule... look if the events got a different style class maybe... if so , try to apply them manually (jquery...) when working with `draggable="true"` – Daniel Dec 17 '12 at 07:32
  • So its not really a primefaces or a jsf-2 question, but a "jquery" "fullcalendar". but since the PF community might be interested in the schedule, leave the tags. – Mindwin Remember Monica Dec 18 '12 at 16:51

2 Answers2

3

You have to dive into the fullcalendar plugin to make it. check these SO questions:

FullCalendar: How to stop dragging custom events?

How do I disable drag and drop in fullcalendar

http://code.google.com/p/fullcalendar/issues/detail?id=1243

http://arshaw.com/fullcalendar/docs/event_data/Event_Object/

Maybe if you can edit the response of the JSF server before it goes out, try using a filter.

The events have this general structure when draggable is ON:

notice the classes of the main div:

<div style="position: absolute; z-index: 8; top: 83px; left: 359px; width: 133.85px; height: 166px;" class="fc-event fc-event-skin fc-event-vert fc-event-draggable fc-corner-top fc-corner-bottom ui-draggable ui-resizable">

<div class="fc-event-inner fc-event-skin">
    <div class="fc-event-head fc-event-skin">
        <div class="fc-event-time">19/12 8:00 - 19/12 10:00</div>
    </div>
    <div class="fc-event-content">
        <div class="fc-event-title">Breakfast at Tiffanys</div>
    </div>
    <div class="fc-event-bg"></div>
</div>
<div class="ui-resizable-handle ui-resizable-s">=</div>
</div>
</div>

<!-- COMMENTED IN ORDER TO KEEP SAME CODE BLOCK -->
<!--When draggable is off, you can see the classes: -->

<div style="position: absolute; z-index: 8; top: 83px; left: 359px; width: 133.85px; height: 166px;" class="fc-event fc-event-skin fc-event-vert fc-corner-top fc-corner-bottom ui-resizable">
<div class="fc-event-inner fc-event-skin">
    <div class="fc-event-head fc-event-skin">
        <div class="fc-event-time">19/12 8:00 - 19/12 10:00</div>
    </div>
    <div class="fc-event-content">
        <div class="fc-event-title">Breakfast at Tiffanys</div>
    </div>
        <div class="fc-event-bg"></div>
    </div>
    <div class="ui-resizable-handle ui-resizable-s">=</div>
</div>
</div>

You need then to unregister the DOM events of the scheduled-events you want, BUT...

Schedule re-renders every time, and it re-registers the events and the classes back. You have little control over the items, since primefaces forwards the data to the jQuery schedule plugin.

So you would need to mark your events as un-draggable every time it re-renders.

the PF response on the ajax code is a javascript object with the data the plugin needs to re-render the schedule, so I don't think that anything server-side would help you.

Here is the server response on a event drag:

<partial-response>
<changes>
<update id="formNotificacao:j_idt72">{"events" : [{"id": "0df04a40-3477-4564-ae2c-340509acd09e","title": "Champions League Match","start": 1355781614894,"end": 1355792414894,"allDay":false,"editable":true},{"id": "3d1e23ec-3a85-488b-aea4-00fa5f2205da","title": "Birthday Party","start": 1355748300000,"end": 1355766300000,"allDay":false,"editable":true},{"id": "35dec60d-0e7a-431d-aef4-b077616908ab","title": "Breakfast at Tiffanys","start": 1355919300000,"end": 1355926500000,"allDay":false,"editable":true},{"id": "4b6c8d2c-bcf1-444c-a92f-d5a0b60499a1","title": "Plant the new garden stuff","start": 1356022814910,"end": 1356195614910,"allDay":false,"editable":true}]}</update>
<update id="javax.faces.ViewState">-8755441948733966113:8810728330896833649</update>
</changes>
</partial-response>

I think you have to use some javascript to unregister the events from the elements you want. But since they are loaded from the server with only data, you have to identify them by name, by date or something else.

See this question for info on how to unregister events: jquery override event

So the path is:

  • put some javascript on your JSF page that will unregister event for the selected scheduled-items.
  • pass into this javascript info on how it will identify the scheduled-itens that will be made un-draggable.
  • find out what element is being listened for the drag event.
  • overrride the drag event so it won't work, while not messing with the other scheduled-itens.

As an added bonus, here goes the source I tested on:

You have to bind the draggable property of the <p:schedule> to a managed bean boolean property, and then use a control (in the example below, a selectbooleancheckbox:

<p:schedule value="#{scheduleController.eventModel}" draggable="#{scheduleController.draggable}" (...) />

notice the ajax tag to communicate with the server:

<p:selectBooleanCheckbox value="#{scheduleController.draggable}">
<p:ajax update=":formNotificacao:toggleDraggableSchedule"/>
</p:selectBooleanCheckbox>

the whole JSF code:

                <h:form id="formNotificacao">

                    <p:growl id="messages" showDetail="true" />
<h:panelGroup id="toggleDraggableSchedule">
                    <p:schedule value="#{scheduleController.eventModel}" draggable="#{scheduleController.draggable}"
                        widgetVar="myschedule" view="agendaWeek" allDaySlot="false"
                        slotMinutes="15" firstHour="7" showWeekends="FALSE"
                        leftHeaderTemplate="prev,next" rightHeaderTemplate=""
                        minTime="7am" maxTime="21pm"
                        timeFormat="dd/MM H:mm{ - dd/MM H:mm}" axisFormat="HH"
                        timeZone="#{rotulo.timeZone}">

                        <p:ajax event="dateSelect"
                            listener="#{scheduleController.onDateSelect}"
                            update="formNotificacao" oncomplete="eventDialog.show()" />
                        <p:ajax event="eventSelect"
                            listener="#{scheduleController.onEventSelect}"
                            update="formNotificacao" oncomplete="eventDialog.show()" />
                        <p:ajax event="eventMove"
                            listener="#{scheduleController.onEventMove}" update="formNotificacao" />
                        <p:ajax event="eventResize"
                            listener="#{scheduleController.onEventResize}" update="formNotificacao" />

                    </p:schedule>
</h:panelGroup>
                    <p:dialog widgetVar="eventDialog" header="Event Details"
                        showEffect="clip" hideEffect="clip">
                        <h:panelGrid id="eventDetails" columns="2">
                            <h:outputLabel for="title" value="Title:" />
                            <p:inputText id="title"
                                value="#{scheduleController.event.title}" required="true" />

                            <h:outputLabel for="from" value="From:" />
                            <p:calendar value="#{scheduleController.event.startDate}" pattern="MM/dd/yyyy HH:mm"  stepMinute="15" />

                            <h:outputLabel for="to" value="To:" />
                            <p:calendar value="#{scheduleController.event.endDate}" pattern="MM/dd/yyyy HH:mm"  stepMinute="15" />

                            <h:outputLabel for="allDay" value="All Day:" />
                            <h:selectBooleanCheckbox id="allDay"
                                value="#{scheduleController.event.allDay}" />

                            <p:commandButton type="reset" value="Reset" />
                            <p:commandButton value="Save"
                                actionListener="#{scheduleController.addEvent}"
                                oncomplete="myschedule.update();eventDialog.hide();" />
                        </h:panelGrid>
                    </p:dialog>

<p:selectBooleanCheckbox value="#{scheduleController.draggable}">
<p:ajax update=":formNotificacao:toggleDraggableSchedule"/>
</p:selectBooleanCheckbox>

                </h:form>

the managed bean:

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.event.DateSelectEvent;
import org.primefaces.event.ScheduleEntryMoveEvent;
import org.primefaces.event.ScheduleEntryResizeEvent;
import org.primefaces.event.ScheduleEntrySelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;

@ManagedBean
@ViewScoped
public class ScheduleController {

private ScheduleModel eventModel;

private ScheduleEvent event = new DefaultScheduleEvent();

private List<ScheduleEvent> eventos;

private String theme;

private boolean draggable;

public ScheduleController() {

    eventModel = new DefaultScheduleModel();
    eventModel.addEvent(new DefaultScheduleEvent("Champions League Match",
            previousDay8Pm(), previousDay11Pm()));
    eventModel.addEvent(new DefaultScheduleEvent("Birthday Party",
            today1Pm(), today6Pm()));
    eventModel.addEvent(new DefaultScheduleEvent("Breakfast at Tiffanys",
            nextDay9Am(), nextDay11Am()));
    eventModel.addEvent(new DefaultScheduleEvent(
            "Plant the new garden stuff", theDayAfter3Pm(),
            fourDaysLater3pm()));
    setEventos(eventModel.getEvents());

}

private Date fourDaysLater3pm() {
    return getDate(4, 15);
}

private Date theDayAfter3Pm() {
    return getDate(2, 15);
}

private Date nextDay11Am() {
    return getDate(1, 11);
}

private Date nextDay9Am() {
    return getDate(+1, 9);
}

private Date today6Pm() {
    return getDate(0, 18);
}

private Date today1Pm() {
    return getDate(0, 13);
}

private Date previousDay11Pm() {
    return getDate(-1, 23);
}

private Date previousDay8Pm() {
    return getDate(-1, 20);
}

private Date getDate(int deltaDay, int hour) {
    Calendar cal = Calendar.getInstance();

    cal.setTime(new Date());
    cal.set(Calendar.HOUR_OF_DAY, hour);
    cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH)
            + deltaDay);
    return cal.getTime();
}

public void addEvent(ActionEvent actionEvent) {
    if (event.getId() == null)
        eventModel.addEvent(event);
    else
        eventModel.updateEvent(event);

    event = new DefaultScheduleEvent();
}

public void onEventSelect(ScheduleEntrySelectEvent selectEvent) {
    event = selectEvent.getScheduleEvent();
}

public void onDateSelect(DateSelectEvent selectEvent) {
    event = new DefaultScheduleEvent(Math.random() + "",
            selectEvent.getDate(), selectEvent.getDate());
}

public void onEventMove(ScheduleEntryMoveEvent event) {
    snapToFifteen((DefaultScheduleEvent) event.getScheduleEvent());
    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
            "Event moved", "Day delta:" + event.getDayDelta()
                    + ", Minute delta:" + event.getMinuteDelta());
    addMessage(message);
}

public void onEventResize(ScheduleEntryResizeEvent event) {
    snapToFifteen((DefaultScheduleEvent) event.getScheduleEvent());
    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
            "Event resized", "Day delta:" + event.getDayDelta()
                    + ", Minute delta:" + event.getMinuteDelta());
    addMessage(message);
}

private void snapToFifteen(DefaultScheduleEvent ev) {
    DateFormat sdf = DateFormat.getDateTimeInstance(DateFormat.FULL,
            DateFormat.FULL);
    sdf.setTimeZone(TimeZone.getTimeZone("GMT-3"));
    System.out.println("CALLING SNAP ON event: Start = "
            + sdf.format(ev.getStartDate()) + " End = "
            + sdf.format(ev.getEndDate()));
    Date inicio = fifteenize(ev.getStartDate());
    Date fim = fifteenize(ev.getEndDate());
    ev.setStartDate(inicio);
    ev.setEndDate(fim);
    System.out.println("Snapped: Start = " + sdf.format(ev.getStartDate())
            + " End = " + sdf.format(ev.getEndDate()));
}

private Date fifteenize(Date data) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(data);
    int minutos = cal.get(Calendar.MINUTE);
    int modQuinze = (minutos + 7) / 15;

    cal.set(Calendar.MINUTE, modQuinze * 15);
    cal.set(Calendar.HOUR, cal.get(Calendar.HOUR));
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}

private void addMessage(FacesMessage message) {
    FacesContext.getCurrentInstance().addMessage(null, message);
}

public ScheduleModel getEventModel() {
    return eventModel;
}

public void setEventModel(ScheduleModel eventModel) {
    this.eventModel = eventModel;
}

public ScheduleEvent getEvent() {
    return event;
}

public void setEvent(ScheduleEvent event) {
    this.event = event;
}

public String getTheme() {
    return theme;
}

public void setTheme(String theme) {
    this.theme = theme;
}

public void setEventos(List<ScheduleEvent> eventos) {
    this.eventos = eventos;
}

public List<ScheduleEvent> getEventos() {
    return eventos;
}

public void setDraggable(boolean draggable) {
    this.draggable = draggable;
}

public boolean isDraggable() {
    return draggable;
}

}

If you look closely to the managed bean, it has some other changes from the primefaces showcase example, for one, all events are snapped to 15 minutes intervals, and other stuff.

Community
  • 1
  • 1
Mindwin Remember Monica
  • 1,469
  • 2
  • 20
  • 35
0

How I did it:

public class MyScheduleEvent extends DefaultScheduleEvent {
    public MyScheduleEvent(MyEntity myEntity) {
        super(....)
        this.setEditable(myEntity.isEditable());
    }
}

I use the lazy model but this would work with the default model. This work like expected. Used PrimeFaces 4.11