From a1b82974acf891d105d5297348c22dcef449db45 Mon Sep 17 00:00:00 2001 From: Bernard Labno Date: Mon, 14 Jun 2010 17:05:11 +0000 Subject: [PATCH] Added ajax attributes (process,reRender,ajaxSingle,etc.). Added widgetVar (for JavaScript). Added JavaScript callbacks for all events that trigger ajax requests, so that developer could program veto on client side and still be notified when request finishes. Fixed entities in message bundle (fix for WebKit bug). Reformatted code. Secured ScopeChain for JavaScript callbacks. Added samples with fetching additional data, model panel with item details and internationalization. --- src/main/config/component/schedule.xml | 301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- src/main/java/org/richfaces/component/ScheduleCommonViewAttributes.java | 6 ++++++ src/main/java/org/richfaces/component/UISchedule.java | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/main/java/org/richfaces/component/UIScheduleBasicDayView.java | 2 +- src/main/java/org/richfaces/component/event/ScheduleDateRangeChangedEvent.java | 4 +--- src/main/java/org/richfaces/component/event/ScheduleDateSelectedEvent.java | 2 +- src/main/java/org/richfaces/component/event/ScheduleItemMoveListener.java | 2 +- src/main/java/org/richfaces/component/event/ScheduleItemResizeListener.java | 2 +- src/main/java/org/richfaces/component/event/ScheduleViewChangedListener.java | 2 +- src/main/java/org/richfaces/component/model/DateRange.java | 3 ++- src/main/java/org/richfaces/renderkit/ScheduleRendererBase.java | 15 ++++++++++++++- src/main/java/org/richfaces/taglib/ScheduleTagHandlerBase.java | 11 ++++------- src/main/resources/org/richfaces/component/UIScheduleMessages_en.properties | 8 ++++---- src/main/resources/org/richfaces/component/UIScheduleMessages_pl.properties | 8 ++++---- src/main/resources/org/richfaces/renderkit/html/css/fullcalendar.css | 799 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/main/resources/org/richfaces/renderkit/html/scripts/gcal.js | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------- src/main/resources/org/richfaces/renderkit/html/scripts/richfaces.schedule.js | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------- src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js | 1033 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/main/resources/org/richfaces/renderkit/html/scripts/ui.draggable.js | 1442 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/main/resources/org/richfaces/renderkit/html/scripts/ui.resizable.js | 1362 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/main/templates/org/richfaces/htmlSchedule.jspx | 3 ++- 21 files changed, 3047 insertions(+), 2464 deletions(-) diff --git a/src/main/config/component/schedule.xml b/src/main/config/component/schedule.xml index f8a3d12..be12fbe 100644 --- a/src/main/config/component/schedule.xml +++ b/src/main/config/component/schedule.xml @@ -36,7 +36,7 @@ --> &ui_component_attributes; &commonViewAttributes; - + &ajax_component_attributes; @@ -53,6 +53,15 @@ "ajax" + widgetVar + java.lang.String + + Variable name of JavaScript component. + default: null + + null + + view java.lang.String @@ -456,7 +465,30 @@ onItemSelected java.lang.String - + JavaScript code for handling event. + Following data will be available in context: +
    +
  • item - selected item
  • +
  • event - javascript event
  • +
  • view - object representing current view
  • +
+
+ null +
+ + onItemSelectedComplete + java.lang.String + + JavaScript code called when ajax request triggered when item + is selected has finished. + Following data will be available in context: +
    +
  • item - selected item
  • +
  • event - javascript event
  • +
  • view - object representing current view
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
null
@@ -464,7 +496,14 @@ onItemDragStart java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + null @@ -472,7 +511,14 @@ onItemDragStop java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + null @@ -480,7 +526,14 @@ onItemResizeStart java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + null @@ -488,7 +541,14 @@ onItemResizeStop java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + null @@ -496,7 +556,53 @@ onItemDrop java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + + + null + + + onItemDropComplete + java.lang.String + + JavaScript code called when ajax request triggered when item + is dropped has finished. + Following data will be available in context: +
    +
  • item - selected item
  • +
  • dayDelta - holds the number of days the event was moved forward (a positive number) or backwards + (a negative number) +
  • +
  • minuteDelta - holds the number of minutes the event was moved forward (a positive number) or + backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed in. +
  • +
  • allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in + the agenda views. It will be false if dropped on a slot in the agenda views (meaning it has been + assigned a time). +
  • +
  • vetoed - is true if server side listener has raised veto and modification has been reverted
  • +
  • event - javascript event
  • +
  • ui - jQuery UI object
  • +
  • view - object representing current view
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
null
@@ -504,7 +610,47 @@ onItemResized java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + + + null + + + onItemResizedComplete + java.lang.String + + JavaScript code called when ajax request triggered when item + is resized has finished. + Following data will be available in context: +
    +
  • item - selected item
  • +
  • dayDelta - holds the number of days the event was moved forward (a positive number) or backwards + (a negative number) +
  • +
  • minuteDelta - holds the number of minutes the event was moved forward (a positive number) or + backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed in. +
  • +
  • vetoed - is true if server side listener has raised veto and modification has been reverted
  • +
  • event - javascript event
  • +
  • ui - jQuery UI object
  • +
  • view - object representing current view
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
null
@@ -512,7 +658,13 @@ onItemMouseover java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + null @@ -520,15 +672,42 @@ onItemMouseout java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + + + null + + + onViewChanged + java.lang.String + + JavaScript code for handling event. + Any return instruction will be ignored + so this code cannot block anything. + Following data will be available in context: +
    +
  • view - object representing current view
  • +
null
- onViewDisplay + onViewChangedComplete java.lang.String - + JavaScript code called when ajax request triggered when view + changes has finished. + Following data will be available in context: +
    +
  • view - object representing current view
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
null
@@ -536,7 +715,36 @@ onDateSelected java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + + + null + + + onDateSelectedComplete + java.lang.String + + JavaScript code called when ajax request triggered when date + is selected has finished. + Following data will be available in context: +
    +
  • date - selected date
  • +
  • allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in + the agenda views. +
  • +
  • event - javascript event
  • +
  • view - object representing current view
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
null
@@ -544,7 +752,67 @@ onDateRangeSelected java.lang.String - + JavaScript code for handling event. + Following data will be available in context: + + + null + + + onDateRangeSelectedComplete + java.lang.String + + JavaScript code called when ajax request triggered when date + range is selected has finished. + Following data will be available in context: +
    +
  • startDate - selection start date
  • +
  • endDate - selection end date
  • +
  • allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in + the agenda views. +
  • +
  • view - object representing current view
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
+
+ null +
+ + onDateRangeChanged + java.lang.String + + JavaScript code for handling event. + Any return instruction will be ignored + so this code cannot block anything. + Following data will be available in context: +
    +
  • startDate - start date
  • +
  • endDate - end date
  • +
+
+ null +
+ + onDateRangeChangedComplete + java.lang.String + + JavaScript code called when ajax request triggered when displayed + date range is changed has finished. + Following data will be available in context: +
    +
  • startDate - selection start date
  • +
  • endDate - selection end date
  • +
  • request - ajax request
  • +
  • data - data returned by ajax request
  • +
null
@@ -555,7 +823,6 @@ null - itemMoveListener @@ -594,6 +861,10 @@ javax.faces.el.MethodBinding + + &listeners; diff --git a/src/main/java/org/richfaces/component/ScheduleCommonViewAttributes.java b/src/main/java/org/richfaces/component/ScheduleCommonViewAttributes.java index ff363e0..3a43c0f 100644 --- a/src/main/java/org/richfaces/component/ScheduleCommonViewAttributes.java +++ b/src/main/java/org/richfaces/component/ScheduleCommonViewAttributes.java @@ -1,5 +1,11 @@ package org.richfaces.component; +/** + * Interface with common attributes of all view components. + * Saves some lines in UISchedule...View classes. + * + * @author Bernard Labno + */ public interface ScheduleCommonViewAttributes { public String getTimeFormat(); diff --git a/src/main/java/org/richfaces/component/UISchedule.java b/src/main/java/org/richfaces/component/UISchedule.java index 19b5801..8a0bf2a 100644 --- a/src/main/java/org/richfaces/component/UISchedule.java +++ b/src/main/java/org/richfaces/component/UISchedule.java @@ -1,8 +1,12 @@ package org.richfaces.component; +import org.ajax4jsf.component.AjaxActionComponent; +import org.ajax4jsf.component.AjaxComponent; import org.ajax4jsf.context.AjaxContext; +import org.ajax4jsf.event.AjaxEvent; import org.ajax4jsf.model.DataVisitor; import org.ajax4jsf.model.ExtendedDataModel; +import org.ajax4jsf.renderkit.RendererUtils; import org.richfaces.component.event.*; import org.richfaces.component.model.DateRange; @@ -22,16 +26,24 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; -public abstract class UISchedule extends UIComponentBase implements ScheduleCommonViewAttributes, ScheduleListenerEventsProducer { +public abstract class UISchedule extends UIComponentBase implements ScheduleCommonViewAttributes, ScheduleListenerEventsProducer, AjaxComponent { public static final String COMPONENT_TYPE = "org.richfaces.Schedule"; public static final String COMPONENT_FAMILY = "org.richfaces.Schedule"; + /** + * Values of view attribute. + */ public static final String VIEW_MONTH = "month"; public static final String VIEW_BASIC_WEEK = "basicWeek"; public static final String VIEW_AGENDA_WEEK = "agendaWeek"; public static final String VIEW_BASIC_DAY = "basicDay"; public static final String VIEW_AGENDA_DAY = "agendaDay"; + /** + * Values of weekMode attribute. + */ public static final String WEEK_MODE_FIXED = "fixed"; + public static final String WEEK_MODE_LIQUID = "liquid"; + public static final String WEEK_MODE_VARIABLE = "variable"; private DataModel model; public abstract Object getValue(); @@ -174,6 +186,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm public abstract void setOnItemSelected(String onItemSelect); + public abstract String getOnItemSelectedComplete(); + + public abstract void setOnItemSelectedComplete(String onItemSelectedComplete); + public abstract String getOnItemDragStart(); public abstract void setOnItemDragStart(String onItemDragStart); @@ -186,6 +202,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm public abstract void setOnItemDrop(String onItemDrop); + public abstract String getOnItemDropComplete(); + + public abstract void setOnItemDropComplete(String onItemDropComplete); + public abstract String getOnItemResizeStart(); public abstract void setOnItemResizeStart(String onItemResizeStart); @@ -198,6 +218,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm public abstract void setOnItemResized(String onItemMouseover); + public abstract String getOnItemResizedComplete(); + + public abstract void setOnItemResizedComplete(String setOnItemResizedComplete); + public abstract String getOnItemMouseover(); public abstract void setOnItemMouseover(String onItemMouseover); @@ -206,18 +230,38 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm public abstract void setOnItemMouseout(String onItemMouseout); - public abstract String getOnViewDisplay(); + public abstract String getOnViewChanged(); + + public abstract void setOnViewChanged(String onViewChanged); + + public abstract String getOnViewChangedComplete(); - public abstract void setOnViewDisplay(String onViewDisplay); + public abstract void setOnViewChangedComplete(String onViewDisplayComplete); public abstract String getOnDateSelected(); public abstract void setOnDateSelected(String onDaySelected); + public abstract String getOnDateSelectedComplete(); + + public abstract void setOnDateSelectedComplete(String setOnDateSelectedComplete); + public abstract String getOnDateRangeSelected(); public abstract void setOnDateRangeSelected(String onDateRangeSelected); + public abstract String getOnDateRangeSelectedComplete(); + + public abstract void setOnDateRangeSelectedComplete(String onDateRangeSelectedComplete); + + public abstract String getOnDateRangeChanged(); + + public abstract void setOnDateRangeChanged(String onDateRangeChanged); + + public abstract String getOnDateRangeChangedComplete(); + + public abstract void setOnDateRangeChangedComplete(String onDateRangeChangedComplete); + // TODO do we use MethodBinding or MethodExpression? public abstract MethodBinding getItemMoveListener(); @@ -248,10 +292,35 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm public abstract void setDateSelectedListener(MethodBinding listener); + public abstract String getWidgetVar(); + + public abstract void setWidgetVar(String widgetVar); + + /** + * React on various events. + * Vetoable events are first broadcasted to listeners bound via EL to + * component attribtues and then if no veto is raised then to the rest of + * listeners. + * In case of non vetoable events the order of broadcast is reverse. + * Vetoable events are: ScheduleItemMoveEvent, ScheduleItemResizeEvent + * Non-vetoable events: ScheduleDateRangeChangedEvent, ScheduleItemSelectedEvent, + * ScheduleViewChangedEvent, ScheduleDateSelectedEvent, + * ScheduleDateRangeSelectedEvent + * In case of ScheduleDateRangeChangedEvent new items are returned + * via response data map of ajaxContext. + * In case of ScheduleItemMoveEvent and ScheduleItemResizeEvent, the + * decision if veto was raised is sent back to client via response data map + * of ajaxContext as boolean. + * + * @param event broadcasted event + * @throws AbortProcessingException if broadcasting of particular event + * should stop + */ @Override public void broadcast(FacesEvent event) throws AbortProcessingException { if (event instanceof ScheduleDateRangeChangedEvent) { super.broadcast(event); + new AjaxEvent(this).queue(); ScheduleDateRangeChangedEvent calendarAjaxEvent = (ScheduleDateRangeChangedEvent) event; FacesContext facesContext = getFacesContext(); AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext); @@ -273,8 +342,9 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm Object result = expression.invoke(facesContext, new Object[]{event}); allow = ((Boolean) result); } - ajaxContext.setResponseData(allow); + ajaxContext.getResponseDataMap().put("_ajax:scheduleData", allow); super.broadcast(event); + new AjaxEvent(this).queue(); } else if (event instanceof ScheduleItemResizeEvent) { FacesContext facesContext = getFacesContext(); AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext); @@ -284,10 +354,12 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm Object result = expression.invoke(facesContext, new Object[]{event}); allow = ((Boolean) result); } - ajaxContext.setResponseData(allow); + ajaxContext.getResponseDataMap().put("_ajax:scheduleData", allow); super.broadcast(event); + new AjaxEvent(this).queue(); } else if (event instanceof ScheduleItemSelectedEvent) { super.broadcast(event); + new AjaxEvent(this).queue(); FacesContext facesContext = getFacesContext(); MethodBinding expression = getItemSelectedListener(); if (expression != null) { @@ -295,6 +367,7 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm } } else if (event instanceof ScheduleViewChangedEvent) { super.broadcast(event); + new AjaxEvent(this).queue(); FacesContext facesContext = getFacesContext(); MethodBinding expression = getViewChangedListener(); if (expression != null) { @@ -302,6 +375,7 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm } } else if (event instanceof ScheduleDateSelectedEvent) { super.broadcast(event); + new AjaxEvent(this).queue(); FacesContext facesContext = getFacesContext(); MethodBinding expression = getDateSelectedListener(); if (expression != null) { @@ -309,11 +383,38 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm } } else if (event instanceof ScheduleDateRangeSelectedEvent) { super.broadcast(event); + new AjaxEvent(this).queue(); FacesContext facesContext = getFacesContext(); MethodBinding expression = getDateRangeSelectedListener(); if (expression != null) { expression.invoke(facesContext, new Object[]{event}); } + } else if (event instanceof AjaxEvent) { + FacesContext context = getFacesContext(); + // complete re-Render fields. AjaxEvent deliver before render + // response. + AjaxContext.getCurrentInstance(context).addRegionsFromComponent(this); + // Put data for send in response + Object data = getData(); + AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context); + if (null != data) { + ajaxContext.setResponseData(data); + } + String focus = getFocus(); + if (null != focus) { + // search for component in tree. + // XXX - use more pourful search, as in h:outputLabel + // component. + UIComponent focusComponent = RendererUtils.getInstance(). + findComponentFor(this, focus); + if (null != focusComponent) { + focus = focusComponent.getClientId(context); + } + ajaxContext.getResponseDataMap().put(AjaxActionComponent.FOCUS_DATA_ID, focus); + } + ajaxContext.setOncomplete(getOncomplete()); + } else { + super.broadcast(event); } } diff --git a/src/main/java/org/richfaces/component/UIScheduleBasicDayView.java b/src/main/java/org/richfaces/component/UIScheduleBasicDayView.java index f8a83bd..ac4c89d 100644 --- a/src/main/java/org/richfaces/component/UIScheduleBasicDayView.java +++ b/src/main/java/org/richfaces/component/UIScheduleBasicDayView.java @@ -2,7 +2,7 @@ package org.richfaces.component; import javax.faces.component.UIComponentBase; -public abstract class UIScheduleBasicDayView extends UIComponentBase implements ScheduleCommonViewAttributes{ +public abstract class UIScheduleBasicDayView extends UIComponentBase implements ScheduleCommonViewAttributes { public static final String COMPONENT_TYPE = "org.richfaces.ScheduleBasicDayView"; public static final String COMPONENT_FAMILY = "org.richfaces.Schedule"; diff --git a/src/main/java/org/richfaces/component/event/ScheduleDateRangeChangedEvent.java b/src/main/java/org/richfaces/component/event/ScheduleDateRangeChangedEvent.java index 02fce6b..54d1fe6 100644 --- a/src/main/java/org/richfaces/component/event/ScheduleDateRangeChangedEvent.java +++ b/src/main/java/org/richfaces/component/event/ScheduleDateRangeChangedEvent.java @@ -1,11 +1,9 @@ package org.richfaces.component.event; -import java.util.Date; - import javax.faces.component.UIComponent; - import javax.faces.event.FacesEvent; import javax.faces.event.FacesListener; +import java.util.Date; public class ScheduleDateRangeChangedEvent extends FacesEvent { diff --git a/src/main/java/org/richfaces/component/event/ScheduleDateSelectedEvent.java b/src/main/java/org/richfaces/component/event/ScheduleDateSelectedEvent.java index 75a66e9..fa21a2f 100644 --- a/src/main/java/org/richfaces/component/event/ScheduleDateSelectedEvent.java +++ b/src/main/java/org/richfaces/component/event/ScheduleDateSelectedEvent.java @@ -1,9 +1,9 @@ package org.richfaces.component.event; -import java.util.Date; import javax.faces.component.UIComponent; import javax.faces.event.FacesEvent; import javax.faces.event.FacesListener; +import java.util.Date; public class ScheduleDateSelectedEvent extends FacesEvent { diff --git a/src/main/java/org/richfaces/component/event/ScheduleItemMoveListener.java b/src/main/java/org/richfaces/component/event/ScheduleItemMoveListener.java index d30484f..8bed1a4 100644 --- a/src/main/java/org/richfaces/component/event/ScheduleItemMoveListener.java +++ b/src/main/java/org/richfaces/component/event/ScheduleItemMoveListener.java @@ -2,7 +2,7 @@ package org.richfaces.component.event; import javax.faces.event.FacesListener; -public interface ScheduleItemMoveListener extends FacesListener{ +public interface ScheduleItemMoveListener extends FacesListener { void itemMove(ScheduleItemMoveEvent event); } diff --git a/src/main/java/org/richfaces/component/event/ScheduleItemResizeListener.java b/src/main/java/org/richfaces/component/event/ScheduleItemResizeListener.java index 032e16e..e28fefd 100644 --- a/src/main/java/org/richfaces/component/event/ScheduleItemResizeListener.java +++ b/src/main/java/org/richfaces/component/event/ScheduleItemResizeListener.java @@ -2,7 +2,7 @@ package org.richfaces.component.event; import javax.faces.event.FacesListener; -public interface ScheduleItemResizeListener extends FacesListener{ +public interface ScheduleItemResizeListener extends FacesListener { void itemResize(ScheduleItemResizeEvent event); } diff --git a/src/main/java/org/richfaces/component/event/ScheduleViewChangedListener.java b/src/main/java/org/richfaces/component/event/ScheduleViewChangedListener.java index 2da6982..19d8001 100644 --- a/src/main/java/org/richfaces/component/event/ScheduleViewChangedListener.java +++ b/src/main/java/org/richfaces/component/event/ScheduleViewChangedListener.java @@ -2,7 +2,7 @@ package org.richfaces.component.event; import javax.faces.event.FacesListener; -public interface ScheduleViewChangedListener extends FacesListener{ +public interface ScheduleViewChangedListener extends FacesListener { void viewChanged(ScheduleViewChangedEvent event); } diff --git a/src/main/java/org/richfaces/component/model/DateRange.java b/src/main/java/org/richfaces/component/model/DateRange.java index d47b583..0b65734 100644 --- a/src/main/java/org/richfaces/component/model/DateRange.java +++ b/src/main/java/org/richfaces/component/model/DateRange.java @@ -1,8 +1,9 @@ package org.richfaces.component.model; -import java.util.Date; import org.ajax4jsf.model.Range; +import java.util.Date; + public class DateRange implements Range { private Date startDate; diff --git a/src/main/java/org/richfaces/renderkit/ScheduleRendererBase.java b/src/main/java/org/richfaces/renderkit/ScheduleRendererBase.java index 11e4b87..043dcb0 100644 --- a/src/main/java/org/richfaces/renderkit/ScheduleRendererBase.java +++ b/src/main/java/org/richfaces/renderkit/ScheduleRendererBase.java @@ -121,6 +121,10 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase { ResponseWriter writer = context.getResponseWriter(); String clientId = component.getClientId(context); Locale locale = context.getViewRoot().getLocale(); + String widgetVar = component.getWidgetVar(); + if (widgetVar != null) { + writer.writeText("var " + widgetVar + " = ", null); + } writer.writeText(new JSObject("RichFaces.Schedule", clientId, locale.toString(), getOptions(component), DATE_RANGE_CHANGED_EVENT, @@ -205,18 +209,27 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase { options.put("header", headerOptions); } addOptionIfSet("allDayDefault", schedule.getAllDayByDefault(), options); + addOptionIfSet("onItemSelected", schedule.getOnItemSelected(), options); + addOptionIfSet("onItemSelectedComplete", schedule.getOnItemSelectedComplete(), options); addOptionIfSet("onItemDrop", schedule.getOnItemDrop(), options); + addOptionIfSet("onItemDropComplete", schedule.getOnItemDropComplete(), options); addOptionIfSet("onItemResized", schedule.getOnItemResized(), options); + addOptionIfSet("onItemResizedComplete", schedule.getOnItemResizedComplete(), options); addOptionIfSet("onItemResizeStart", schedule.getOnItemResizeStart(), options); addOptionIfSet("onItemResizeStop", schedule.getOnItemResizeStop(), options); addOptionIfSet("onItemDragStart", schedule.getOnItemDragStart(), options); addOptionIfSet("onItemDragStop", schedule.getOnItemDragStop(), options); addOptionIfSet("onItemMouseover", schedule.getOnItemMouseover(), options); addOptionIfSet("onItemMouseout", schedule.getOnItemMouseout(), options); - addOptionIfSet("onViewDisplay", schedule.getOnViewDisplay(), options); + addOptionIfSet("onViewChanged", schedule.getOnViewChanged(), options); + addOptionIfSet("onViewChangedComplete", schedule.getOnViewChangedComplete(), options); addOptionIfSet("onDateSelected", schedule.getOnDateSelected(), options); + addOptionIfSet("onDateSelectedComplete", schedule.getOnDateSelectedComplete(), options); addOptionIfSet("onDateRangeSelected", schedule.getOnDateRangeSelected(), options); + addOptionIfSet("onDateRangeSelectedComplete", schedule.getOnDateRangeSelectedComplete(), options); + addOptionIfSet("onDateRangeChanged", schedule.getOnDateRangeChanged(), options); + addOptionIfSet("onDateRangeChangedComplete", schedule.getOnDateRangeChangedComplete(), options); if (schedule.getDate() != null) { Calendar calendar = Calendar.getInstance(); calendar.setTime(schedule.getDate()); diff --git a/src/main/java/org/richfaces/taglib/ScheduleTagHandlerBase.java b/src/main/java/org/richfaces/taglib/ScheduleTagHandlerBase.java index 1964387..b49e6d7 100644 --- a/src/main/java/org/richfaces/taglib/ScheduleTagHandlerBase.java +++ b/src/main/java/org/richfaces/taglib/ScheduleTagHandlerBase.java @@ -1,18 +1,15 @@ package org.richfaces.taglib; import com.sun.facelets.FaceletContext; -import com.sun.facelets.tag.MetaRule; -import com.sun.facelets.tag.MetaRuleset; -import com.sun.facelets.tag.Metadata; -import com.sun.facelets.tag.MetadataTarget; -import com.sun.facelets.tag.TagAttribute; +import com.sun.facelets.tag.*; import com.sun.facelets.tag.jsf.ComponentConfig; import com.sun.facelets.tag.jsf.ComponentHandler; -import javax.faces.component.UIComponent; -import javax.faces.el.MethodBinding; import org.richfaces.event.NodeExpandedEvent; import org.richfaces.event.NodeSelectedEvent; +import javax.faces.component.UIComponent; +import javax.faces.el.MethodBinding; + public class ScheduleTagHandlerBase extends ComponentHandler { private final static String DATE_RANGE_CHANGED_LISTENER = "dateRangeChangedListener"; diff --git a/src/main/resources/org/richfaces/component/UIScheduleMessages_en.properties b/src/main/resources/org/richfaces/component/UIScheduleMessages_en.properties index 8a85c05..ac1ea48 100644 --- a/src/main/resources/org/richfaces/component/UIScheduleMessages_en.properties +++ b/src/main/resources/org/richfaces/component/UIScheduleMessages_en.properties @@ -37,10 +37,10 @@ org.richfaces.component.UISchedule.dayNamesShort.WEDNESDAY=Wed org.richfaces.component.UISchedule.dayNamesShort.THURSDAY=Thu org.richfaces.component.UISchedule.dayNamesShort.FRIDAY=Fri org.richfaces.component.UISchedule.dayNamesShort.SATURDAY=Sat -org.richfaces.component.UISchedule.buttonTexts.prev= ◄  -org.richfaces.component.UISchedule.buttonTexts.next= ►  -org.richfaces.component.UISchedule.buttonTexts.prevYear= <<  -org.richfaces.component.UISchedule.buttonTexts.nextYear= >>  +org.richfaces.component.UISchedule.buttonTexts.prev= ◄  +org.richfaces.component.UISchedule.buttonTexts.next= ►  +org.richfaces.component.UISchedule.buttonTexts.prevYear= <<  +org.richfaces.component.UISchedule.buttonTexts.nextYear= >>  org.richfaces.component.UISchedule.buttonTexts.today=today org.richfaces.component.UISchedule.buttonTexts.month=month org.richfaces.component.UISchedule.buttonTexts.week=week diff --git a/src/main/resources/org/richfaces/component/UIScheduleMessages_pl.properties b/src/main/resources/org/richfaces/component/UIScheduleMessages_pl.properties index 361ca72..c045e2f 100644 --- a/src/main/resources/org/richfaces/component/UIScheduleMessages_pl.properties +++ b/src/main/resources/org/richfaces/component/UIScheduleMessages_pl.properties @@ -37,10 +37,10 @@ org.richfaces.component.UISchedule.dayNamesShort.WEDNESDAY=\u015Aro org.richfaces.component.UISchedule.dayNamesShort.THURSDAY=Czw org.richfaces.component.UISchedule.dayNamesShort.FRIDAY=Pi\u0105 org.richfaces.component.UISchedule.dayNamesShort.SATURDAY=Sob -org.richfaces.component.UISchedule.buttonTexts.prev= ◄  -org.richfaces.component.UISchedule.buttonTexts.next= ►  -org.richfaces.component.UISchedule.buttonTexts.prevYear= <<  -org.richfaces.component.UISchedule.buttonTexts.nextYear= >>  +org.richfaces.component.UISchedule.buttonTexts.prev= ◄  +org.richfaces.component.UISchedule.buttonTexts.next= ►  +org.richfaces.component.UISchedule.buttonTexts.prevYear= <<  +org.richfaces.component.UISchedule.buttonTexts.nextYear= >>  org.richfaces.component.UISchedule.buttonTexts.today=Dzi\u015B org.richfaces.component.UISchedule.buttonTexts.month=Miesi\u0105c org.richfaces.component.UISchedule.buttonTexts.week=Tydzie\u0144 diff --git a/src/main/resources/org/richfaces/renderkit/html/css/fullcalendar.css b/src/main/resources/org/richfaces/renderkit/html/css/fullcalendar.css index 888f6ea..6ef114b 100644 --- a/src/main/resources/org/richfaces/renderkit/html/css/fullcalendar.css +++ b/src/main/resources/org/richfaces/renderkit/html/css/fullcalendar.css @@ -10,566 +10,555 @@ * TODO adjust class names to richfaces naming conventions */ - .fc, .fc .fc-header, .fc .fc-content { - font-size: 1em; - } - + font-size: 1em; +} + .fc { - direction: ltr; - text-align: left; - } - -.fc table { - border-collapse: collapse; - border-spacing: 0; - } - -.fc td, .fc th { - padding: 0; - vertical-align: top; - } + direction: ltr; + text-align: left; +} +.fc table { + border-collapse: collapse; + border-spacing: 0; +} +.fc td, .fc th { + padding: 0; + vertical-align: top; +} /* Header ------------------------------------------------------------------------*/ - + table.fc-header { - width: 100%; - } - + width: 100%; +} + .fc-header-left { - width: 25%; - } - + width: 25%; +} + .fc-header-left table { - float: left; - } - + float: left; +} + .fc-header-center { - width: 50%; - text-align: center; - } - + width: 50%; + text-align: center; +} + .fc-header-center table { - margin: 0 auto; - } - + margin: 0 auto; +} + .fc-header-right { - width: 25%; - } - + width: 25%; +} + .fc-header-right table { - float: right; - } - + float: right; +} + .fc-header-title { - margin-top: 0; - white-space: nowrap; - } - + margin-top: 0; + white-space: nowrap; +} + .fc-header-space { - padding-left: 10px; - } - + padding-left: 10px; +} + /* right-to-left */ .fc-rtl .fc-header-title { - direction: rtl; - } - - + direction: rtl; +} /* Buttons ------------------------------------------------------------------------*/ .fc-header .fc-state-default, .fc-header .ui-state-default { - margin-bottom: 1em; - cursor: pointer; - } - + margin-bottom: 1em; + cursor: pointer; +} + .fc-header .fc-state-default { - border-width: 1px 0; - padding: 0 1px; - } - + border-width: 1px 0; + padding: 0 1px; +} + .fc-header .fc-state-default, .fc-header .fc-state-default a { - border-style: solid; - } - + border-style: solid; +} + .fc-header .fc-state-default a { - display: block; - border-width: 0 1px; - margin: 0 -1px; - width: 100%; - text-decoration: none; - } - + display: block; + border-width: 0 1px; + margin: 0 -1px; + width: 100%; + text-decoration: none; +} + .fc-header .fc-state-default span { - display: block; - border-style: solid; - border-width: 1px 0 1px 1px; - padding: 3px 5px; - } - + display: block; + border-style: solid; + border-width: 1px 0 1px 1px; + padding: 3px 5px; +} + .fc-header .ui-state-default { - padding: 4px 6px; - } - + padding: 4px 6px; +} + .fc-header .fc-state-default span, .fc-header .ui-state-default span { - white-space: nowrap; - } - + white-space: nowrap; +} + /* for adjacent buttons */ - + .fc-header .fc-no-right { - padding-right: 0; - } - + padding-right: 0; +} + .fc-header .fc-no-right a { - margin-right: 0; - border-right: 0; - } - + margin-right: 0; + border-right: 0; +} + .fc-header .ui-no-right { - border-right: 0; - } - + border-right: 0; +} + /* for fake rounded corners */ - + .fc-header .fc-corner-left { - margin-left: 1px; - padding-left: 0; - } - + margin-left: 1px; + padding-left: 0; +} + .fc-header .fc-corner-right { - margin-right: 1px; - padding-right: 0; - } - + margin-right: 1px; + padding-right: 0; +} + /* DEFAULT button COLORS */ - + .fc-header .fc-state-default, .fc-header .fc-state-default a { - border-color: #777; /* outer border */ - color: #333; - } + border-color: #777; /* outer border */ + color: #333; +} .fc-header .fc-state-default span { - border-color: #fff #fff #d1d1d1; /* inner border */ - background: #e8e8e8; - } - + border-color: #fff #fff #d1d1d1; /* inner border */ + background: #e8e8e8; +} + /* PRESSED button COLORS (down and active) */ - + .fc-header .fc-state-active a { - color: #fff; - } - + color: #fff; +} + .fc-header .fc-state-down span, .fc-header .fc-state-active span { - background: #888; - border-color: #808080 #808080 #909090; /* inner border */ - } - + background: #888; + border-color: #808080 #808080 #909090; /* inner border */ +} + /* DISABLED button COLORS */ - + .fc-header .fc-state-disabled a { - color: #999; - } - + color: #999; +} + .fc-header .fc-state-disabled, .fc-header .fc-state-disabled a { - border-color: #ccc; /* outer border */ - } - + border-color: #ccc; /* outer border */ +} + .fc-header .fc-state-disabled span { - border-color: #fff #fff #f0f0f0; /* inner border */ - background: #f0f0f0; - } - - - + border-color: #fff #fff #f0f0f0; /* inner border */ + background: #f0f0f0; +} + /* Content Area & Global Cell Styles ------------------------------------------------------------------------*/ - + .fc-widget-content { - border: 1px solid #ccc; /* outer border color */ - } - + border: 1px solid #ccc; /* outer border color */ +} + .fc-content { - clear: both; - } - + clear: both; +} + .fc-content .fc-state-default { - border-style: solid; - border-color: #ccc; /* inner border color */ - } - -.fc-content .fc-state-highlight { /* today */ - background: #ffc; - } - + border-style: solid; + border-color: #ccc; /* inner border color */ +} + +.fc-content .fc-state-highlight { +/* today */ + background: #ffc; +} + .fc-content .fc-not-today { - background: none; - } - -.fc-cell-overlay { /* semi-transparent rectangle while dragging */ - background: #9cf; - opacity: .2; - filter: alpha(opacity=20); /* for IE */ - } - -.fc-view { /* prevents dragging outside of widget */ - width: 100%; - overflow: hidden; - } - - - + background: none; +} + +.fc-cell-overlay { +/* semi-transparent rectangle while dragging */ + background: #9cf; + opacity: .2; + filter: alpha(opacity = 20); /* for IE */ +} + +.fc-view { +/* prevents dragging outside of widget */ + width: 100%; + overflow: hidden; +} + /* Global Event Styles ------------------------------------------------------------------------*/ .fc-event, .fc-agenda .fc-event-time, .fc-event a { - border-style: solid; - border-color: #36c; /* default BORDER color (probably the same as background-color) */ - background-color: #36c; /* default BACKGROUND color */ - color: #fff; /* default TEXT color */ - } - - /* Use the 'className' CalEvent property and the following - * example CSS to change event color on a per-event basis: - * - * .myclass, - * .fc-agenda .myclass .fc-event-time, - * .myclass a { - * background-color: black; - * border-color: black; - * color: red; - * } - */ - + border-style: solid; + border-color: #36c; /* default BORDER color (probably the same as background-color) */ + background-color: #36c; /* default BACKGROUND color */ + color: #fff; /* default TEXT color */ +} + +/* Use the 'className' CalEvent property and the following + * example CSS to change event color on a per-event basis: + * + * .myclass, + * .fc-agenda .myclass .fc-event-time, + * .myclass a { + * background-color: black; + * border-color: black; + * color: red; + * } + */ + .fc-event { - text-align: left; - } - + text-align: left; +} + .fc-event a { - overflow: hidden; - font-size: .85em; - text-decoration: none; - cursor: pointer; - } - + overflow: hidden; + font-size: .85em; + text-decoration: none; + cursor: pointer; +} + .fc-event-editable { - cursor: pointer; - } - + cursor: pointer; +} + .fc-event-time, .fc-event-title { - padding: 0 1px; - } - + padding: 0 1px; +} + /* for fake rounded corners */ .fc-event a { - display: block; - position: relative; - width: 100%; - height: 100%; - } - + display: block; + position: relative; + width: 100%; + height: 100%; +} + /* right-to-left */ .fc-rtl .fc-event a { - text-align: right; - } - + text-align: right; +} + /* resizable */ - + .fc .ui-resizable-handle { - display: block; - position: absolute; - z-index: 99999; - border: 0 !important; /* important overrides pre jquery ui 1.7 styles */ - background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */ - } - - - + display: block; + position: absolute; + z-index: 99999; + border: 0 !important; /* important overrides pre jquery ui 1.7 styles */ + background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */ +} + /* Horizontal Events ------------------------------------------------------------------------*/ .fc-event-hori { - border-width: 1px 0; - margin-bottom: 1px; - } - + border-width: 1px 0; + margin-bottom: 1px; +} + .fc-event-hori a { - border-width: 0; - } - + border-width: 0; +} + /* for fake rounded corners */ - + .fc-content .fc-corner-left { - margin-left: 1px; - } - + margin-left: 1px; +} + .fc-content .fc-corner-left a { - margin-left: -1px; - border-left-width: 1px; - } - + margin-left: -1px; + border-left-width: 1px; +} + .fc-content .fc-corner-right { - margin-right: 1px; - } - + margin-right: 1px; +} + .fc-content .fc-corner-right a { - margin-right: -1px; - border-right-width: 1px; - } - + margin-right: -1px; + border-right-width: 1px; +} + /* resizable */ - + .fc-event-hori .ui-resizable-e { - top: 0 !important; /* importants override pre jquery ui 1.7 styles */ - right: -3px !important; - width: 7px !important; - height: 100% !important; - cursor: e-resize; - } - + top: 0 !important; /* importants override pre jquery ui 1.7 styles */ + right: -3px !important; + width: 7px !important; + height: 100% !important; + cursor: e-resize; +} + .fc-event-hori .ui-resizable-w { - top: 0 !important; - left: -3px !important; - width: 7px !important; - height: 100% !important; - cursor: w-resize; - } - + top: 0 !important; + left: -3px !important; + width: 7px !important; + height: 100% !important; + cursor: w-resize; +} + .fc-event-hori .ui-resizable-handle { - _padding-bottom: 14px; /* IE6 had 0 height */ - } - - + _padding-bottom: 14px; /* IE6 had 0 height */ +} /* Month View, Basic Week View, Basic Day View ------------------------------------------------------------------------*/ .fc-grid table { - width: 100%; - } - + width: 100%; +} + .fc .fc-grid th { - border-width: 0 0 0 1px; - text-align: center; - } - + border-width: 0 0 0 1px; + text-align: center; +} + .fc .fc-grid td { - border-width: 1px 0 0 1px; - } - + border-width: 1px 0 0 1px; +} + .fc-grid th.fc-leftmost, .fc-grid td.fc-leftmost { - border-left: 0; - } - + border-left: 0; +} + .fc-grid .fc-day-number { - float: right; - padding: 0 2px; - } - + float: right; + padding: 0 2px; +} + .fc-grid .fc-other-month .fc-day-number { - opacity: 0.3; - filter: alpha(opacity=30); /* for IE */ - /* opacity with small font can sometimes look too faded - might want to set the 'color' property instead - making day-numbers bold also fixes the problem */ - } - + opacity: 0.3; + filter: alpha(opacity = 30); /* for IE */ + /* opacity with small font can sometimes look too faded + might want to set the 'color' property instead + making day-numbers bold also fixes the problem */ +} + .fc-grid .fc-day-content { - clear: both; - padding: 2px 2px 0; /* distance between events and day edges */ - } - + clear: both; + padding: 2px 2px 0; /* distance between events and day edges */ +} + /* event styles */ - + .fc-grid .fc-event-time { - font-weight: bold; - } - + font-weight: bold; +} + /* right-to-left */ .fc-rtl .fc-grid { - direction: rtl; - } - + direction: rtl; +} + .fc-rtl .fc-grid .fc-day-number { - float: left; - } - + float: left; +} + .fc-rtl .fc-grid .fc-event-time { - float: right; - } - + float: right; +} + /* Agenda Week View, Agenda Day View ------------------------------------------------------------------------*/ .fc .fc-agenda th, .fc .fc-agenda td { - border-width: 1px 0 0 1px; - } - + border-width: 1px 0 0 1px; +} + .fc .fc-agenda .fc-leftmost { - border-left: 0; - } - + border-left: 0; +} + .fc-agenda tr.fc-first th, .fc-agenda tr.fc-first td { - border-top: 0; - } - + border-top: 0; +} + .fc-agenda-head tr.fc-last th { - border-bottom-width: 1px; - } - + border-bottom-width: 1px; +} + .fc .fc-agenda-head td, .fc .fc-agenda-body td { - background: none; - } - + background: none; +} + .fc-agenda-head th { - text-align: center; - } - + text-align: center; +} + /* the time axis running down the left side */ - + .fc-agenda .fc-axis { - width: 50px; - padding: 0 4px; - vertical-align: middle; - white-space: nowrap; - text-align: right; - font-weight: normal; - } - + width: 50px; + padding: 0 4px; + vertical-align: middle; + white-space: nowrap; + text-align: right; + font-weight: normal; +} + /* all-day event cells at top */ - + .fc-agenda-head tr.fc-all-day th { - height: 35px; - } - + height: 35px; +} + .fc-agenda-head td { - padding-bottom: 10px; - } - + padding-bottom: 10px; +} + .fc .fc-divider div { - font-size: 1px; /* for IE6/7 */ - height: 2px; - } - + font-size: 1px; /* for IE6/7 */ + height: 2px; +} + .fc .fc-divider .fc-state-default { - background: #eee; /* color for divider between all-day and time-slot events */ - } + background: #eee; /* color for divider between all-day and time-slot events */ +} /* body styles */ - + .fc .fc-agenda-body td div { - height: 20px; /* slot height */ - } - + height: 20px; /* slot height */ +} + .fc .fc-agenda-body tr.fc-minor th, .fc .fc-agenda-body tr.fc-minor td { - border-top-style: dotted; - } - -.fc-agenda .fc-day-content { - padding: 2px 2px 0; /* distance between events and day edges */ - } - + border-top-style: dotted; +} +.fc-agenda .fc-day-content { + padding: 2px 2px 0; /* distance between events and day edges */ +} /* Vertical Events ------------------------------------------------------------------------*/ .fc-event-vert { - border-width: 0 1px; - } - + border-width: 0 1px; +} + .fc-event-vert a { - border-width: 0; - } - + border-width: 0; +} + /* for fake rounded corners */ - + .fc-content .fc-corner-top { - margin-top: 1px; - } - + margin-top: 1px; +} + .fc-content .fc-corner-top a { - margin-top: -1px; - border-top-width: 1px; - } - + margin-top: -1px; + border-top-width: 1px; +} + .fc-content .fc-corner-bottom { - margin-bottom: 1px; - } - + margin-bottom: 1px; +} + .fc-content .fc-corner-bottom a { - margin-bottom: -1px; - border-bottom-width: 1px; - } - + margin-bottom: -1px; + border-bottom-width: 1px; +} + /* event content */ - + .fc-event-vert span { - display: block; - position: relative; - z-index: 2; - } - + display: block; + position: relative; + z-index: 2; +} + .fc-event-vert span.fc-event-time { - white-space: nowrap; - _white-space: normal; - overflow: hidden; - border: 0; - font-size: 10px; - } - + white-space: nowrap; + _white-space: normal; + overflow: hidden; + border: 0; + font-size: 10px; +} + .fc-event-vert span.fc-event-title { - line-height: 13px; - } - -.fc-event-vert span.fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay */ - position: absolute; - z-index: 1; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: #fff; - opacity: .3; - filter: alpha(opacity=30); /* for IE */ - } - + line-height: 13px; +} + +.fc-event-vert span.fc-event-bg { +/* makes the event lighter w/ a semi-transparent overlay */ + position: absolute; + z-index: 1; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #fff; + opacity: .3; + filter: alpha(opacity = 30); /* for IE */ +} + /* resizable */ - + .fc-event-vert .ui-resizable-s { - bottom: 0 !important; /* importants override pre jquery ui 1.7 styles */ - width: 100% !important; - height: 8px !important; - line-height: 8px !important; - font-size: 11px !important; - font-family: monospace; - text-align: center; - cursor: s-resize; - } + bottom: 0 !important; /* importants override pre jquery ui 1.7 styles */ + width: 100% !important; + height: 8px !important; + line-height: 8px !important; + font-size: 11px !important; + font-family: monospace; + text-align: center; + cursor: s-resize; +} diff --git a/src/main/resources/org/richfaces/renderkit/html/scripts/gcal.js b/src/main/resources/org/richfaces/renderkit/html/scripts/gcal.js index 773d326..c34babd 100644 --- a/src/main/resources/org/richfaces/renderkit/html/scripts/gcal.js +++ b/src/main/resources/org/richfaces/renderkit/html/scripts/gcal.js @@ -12,60 +12,60 @@ (function($) { - $.fullCalendar.gcalFeed = function(feedUrl, options) { - - feedUrl = feedUrl.replace(/\/basic$/, '/full'); - options = options || {}; - - return function(start, end, callback) { - var params = { - 'start-min': $.fullCalendar.formatDate(start, 'u'), - 'start-max': $.fullCalendar.formatDate(end, 'u'), - 'singleevents': true, - 'max-results': 9999 - }; - var ctz = options.currentTimezone; - if (ctz) { - params.ctz = ctz = ctz.replace(' ', '_'); - } - $.getJSON(feedUrl + "?alt=json-in-script&callback=?", params, function(data) { - var events = []; - if (data.feed.entry) { - $.each(data.feed.entry, function(i, entry) { - var startStr = entry['gd$when'][0]['startTime'], - start = $.fullCalendar.parseISO8601(startStr, true), - end = $.fullCalendar.parseISO8601(entry['gd$when'][0]['endTime'], true), - allDay = startStr.indexOf('T') == -1, - url; - $.each(entry.link, function() { - if (this.type == 'text/html') { - url = this.href; - if (ctz) { - url += (url.indexOf('?') == -1 ? '?' : '&') + 'ctz=' + ctz; - } - } - }); - if (allDay) { - $.fullCalendar.addDays(end, -1); // make inclusive - } - events.push({ - id: entry['gCal$uid']['value'], - title: entry['title']['$t'], - url: url, - start: start, - end: end, - allDay: allDay, - location: entry['gd$where'][0]['valueString'], - description: entry['content']['$t'], - className: options.className, - editable: options.editable || false - }); - }); - } - callback(events); - }); - } - - } + $.fullCalendar.gcalFeed = function(feedUrl, options) { + + feedUrl = feedUrl.replace(/\/basic$/, '/full'); + options = options || {}; + + return function(start, end, callback) { + var params = { + 'start-min': $.fullCalendar.formatDate(start, 'u'), + 'start-max': $.fullCalendar.formatDate(end, 'u'), + 'singleevents': true, + 'max-results': 9999 + }; + var ctz = options.currentTimezone; + if (ctz) { + params.ctz = ctz = ctz.replace(' ', '_'); + } + $.getJSON(feedUrl + "?alt=json-in-script&callback=?", params, function(data) { + var events = []; + if (data.feed.entry) { + $.each(data.feed.entry, function(i, entry) { + var startStr = entry['gd$when'][0]['startTime'], + start = $.fullCalendar.parseISO8601(startStr, true), + end = $.fullCalendar.parseISO8601(entry['gd$when'][0]['endTime'], true), + allDay = startStr.indexOf('T') == -1, + url; + $.each(entry.link, function() { + if (this.type == 'text/html') { + url = this.href; + if (ctz) { + url += (url.indexOf('?') == -1 ? '?' : '&') + 'ctz=' + ctz; + } + } + }); + if (allDay) { + $.fullCalendar.addDays(end, -1); // make inclusive + } + events.push({ + id: entry['gCal$uid']['value'], + title: entry['title']['$t'], + url: url, + start: start, + end: end, + allDay: allDay, + location: entry['gd$where'][0]['valueString'], + description: entry['content']['$t'], + className: options.className, + editable: options.editable || false + }); + }); + } + callback(events); + }); + } + + } })(jQuery); diff --git a/src/main/resources/org/richfaces/renderkit/html/scripts/richfaces.schedule.js b/src/main/resources/org/richfaces/renderkit/html/scripts/richfaces.schedule.js index 67581d8..9c0a831 100644 --- a/src/main/resources/org/richfaces/renderkit/html/scripts/richfaces.schedule.js +++ b/src/main/resources/org/richfaces/renderkit/html/scripts/richfaces.schedule.js @@ -41,6 +41,12 @@ window.RichFaces.Schedule = (function() { return; } } + if (options.onDateRangeChanged != null) { + RichFaces.Schedule.eval("(function(){" + options.onDateRangeChanged + "})()", { + 'startDate':startDate, + 'endDate':endDate + }); + } if (_this.submitEventFunction != null) { _this.submitEventFunction({} /* stub event */, null, @@ -54,32 +60,58 @@ window.RichFaces.Schedule = (function() { if (scheduleData != undefined) { callback(scheduleData); } + if (options.onDateRangeChangedComplete != null) { + RichFaces.Schedule.eval("(function(){" + options.onDateRangeChangedComplete + "})()", { + 'startDate':startDate, + 'endDate':endDate, + 'request':request, + 'data':data, + 'items':scheduleData + }); + } } ); } }; - var itemDragStart = function(item, event) { + var itemDragStart = function(item, event, ui, view) { if (options.onItemDragStart != null) { - eval("(function(){" + options.onItemDragStart + "})()"); + RichFaces.Schedule.eval("(function(){" + options.onItemDragStart + "})()", { + 'item':item, + 'event':event, + 'ui':ui, + 'view':view + }); } }; - var itemDragStop = function(item, event) { + var itemDragStop = function(item, event, ui, view) { if (options.onItemDragStop != null) { - eval("(function(){" + options.onItemDragStop + "})()"); + RichFaces.Schedule.eval("(function(){" + options.onItemDragStop + "})()", { + 'item':item, + 'event':event, + 'ui':ui, + 'view':view + }); } }; - var itemDrop = function(item, dayDelta, minuteDelta, allDay, revertFunc, event) { + var itemDrop = function(item, dayDelta, minuteDelta, allDay, revertFunc, event, ui, view) { + var result; if (options.onItemDrop != null) { - var result = eval("(function(){" + options.onItemDrop + "})()"); - if (result != null) { - if (result === false) { - revertFunc(); - } + result = RichFaces.Schedule.eval("(function(){" + options.onItemDrop + "})()", { + 'item':item, + 'dayDelta':dayDelta, + 'minuteDelta':minuteDelta, + 'allDay':allDay, + 'event':event, + 'ui':ui, + 'view':view + }); + if (result === false) { + revertFunc(); return; } } if (_this.submitEventFunction != null) { - _this.submitEventFunction({} /* stub event */, + _this.submitEventFunction(event, null, itemMovedEventName, item.id, @@ -87,25 +119,49 @@ window.RichFaces.Schedule = (function() { null, dayDelta, minuteDelta, allDay, function(request, event, data) { - if (data != undefined && data !== true) { + var decision = request.getJSON('_ajax:scheduleData'); + var vetoed = false; + if (decision != undefined && decision !== true) { revertFunc(); + vetoed = true; + } + if (options.onItemDropComplete != null) { + RichFaces.Schedule.eval("(function(){" + options.onItemDropComplete + "})()", { + 'item':item, + 'dayDelta':dayDelta, + 'minuteDelta':minuteDelta, + 'allDay':allDay, + 'event':event, + 'ui':ui, + 'view':view, + 'request':request, + 'data':data, + 'vetoed':vetoed + }); } } ); } + return; }; - var itemResized = function(item, dayDelta, minuteDelta, revertFunc, event) { + var itemResized = function(item, dayDelta, minuteDelta, revertFunc, event, ui, view) { + var result; if (options.onItemResized != null) { - var result = eval("(function(){" + options.onItemResized + "})()"); - if (result != null) { - if (result === false) { - revertFunc(); - } + result = RichFaces.Schedule.eval("(function(){" + options.onItemResized + "})()", { + 'item':item, + 'dayDelta':dayDelta, + 'minuteDelta':minuteDelta, + 'event':event, + 'ui':ui, + 'view':view + }); + if (result === false) { + revertFunc(); return; } } if (_this.submitEventFunction != null) { - _this.submitEventFunction({} /* stub event */, + _this.submitEventFunction(event, null, itemResizedEventName, item.id, @@ -113,93 +169,181 @@ window.RichFaces.Schedule = (function() { null, dayDelta, minuteDelta, null, function(request, event, data) { - if (data != undefined && data !== true) { + var decision = request.getJSON('_ajax:scheduleData'); + var vetoed = false; + if (decision != undefined && decision !== true) { revertFunc(); + vetoed = true; + } + if (options.onItemResizedComplete != null) { + RichFaces.Schedule.eval("(function(){" + options.onItemResizedComplete + "})()", { + 'item':item, + 'dayDelta':dayDelta, + 'minuteDelta':minuteDelta, + 'event':event, + 'ui':ui, + 'view':view, + 'request':request, + 'data':data, + 'vetoed':vetoed + }); } } ); } }; - var itemResizeStart = function(item, event) { + var itemResizeStart = function(item, event, ui, view) { if (options.onItemResizeStart != null) { - eval("(function(){" + options.onItemResizeStart + "})()"); + RichFaces.Schedule.eval("(function(){" + options.onItemResizeStart + "})()", { + 'item':item, + 'event':event, + 'ui':ui, + 'view':view + }); } }; - var itemResizeStop = function(item, event) { + var itemResizeStop = function(item, event, ui, view) { if (options.onItemResizeStop != null) { - eval("(function(){" + options.onItemResizeStop + "})()"); + RichFaces.Schedule.eval("(function(){" + options.onItemResizeStop + "})()", { + 'item':item, + 'event':event, + 'ui':ui, + 'view':view + }); } }; - var itemMouseover = function(item) { + var itemMouseover = function(item, event, view) { if (options.onItemMouseover != null) { - eval("(function(){" + options.onItemMouseover + "})()"); + RichFaces.Schedule.eval("(function(){" + options.onItemMouseover + "})()", { + 'item':item, + 'event':event, + 'view':view + }); } }; - var itemMouseout = function(item) { + var itemMouseout = function(item, event, view) { if (options.onItemMouseout != null) { - eval("(function(){" + options.onItemMouseout + "})()"); + RichFaces.Schedule.eval("(function(){" + options.onItemMouseout + "})()", { + 'item':item, + 'event':event, + 'view':view + }); } }; - var itemClick = function(item, event) { + var itemClick = function(item, event, view) { + var result; if (options.onItemSelected != null) { - var result = eval("(function(){" + options.onItemSelected + "})()"); - if (result != null) { - return; - } + result = RichFaces.Schedule.eval("(function(){" + options.onItemSelected + "})()", { + 'item':item, + 'event':event, + 'view':view + }); + } + if (result === false) { + return false; } if (_this.submitEventFunction != null) { - _this.submitEventFunction({}, + _this.submitEventFunction(event, null, itemSelectedEventName, item.id, - null, null, null, null, null, null + null, null, null, null, null, function(request, event, data) { + if (options.onItemSelectedComplete != null) { + RichFaces.Schedule.eval("(function(){" + options.onItemSelectedComplete + "})()", { + 'item':item, + 'event':event, + 'view':view, + 'request':request, + 'data':data + }); + } + } ); } + return result; }; - var dayClick = function(date, allDay, event) { + var dayClick = function(date, allDay, event, view) { + var result; if (options.onDateSelected != null) { - var result = eval("(function(){" + options.onDateSelected + "})()"); - if (result != null) { - throw "return not allowed in onDaySelect"; - } + result = RichFaces.Schedule.eval("(function(){" + options.onDateSelected + "})()", { + 'date':date, + 'allDay':allDay, + 'event':event, + 'view':view + }); + } + if (result === false) { + return false; } if (_this.submitEventFunction != null) { - _this.submitEventFunction({}, + _this.submitEventFunction(event, null, daySelectedEventName, - null, formatDateParam(date), null, null, null, allDay, null + null, formatDateParam(date), null, null, null, allDay, function(request, event, data) { + if (options.onDateSelectedComplete != null) { + RichFaces.Schedule.eval("(function(){" + options.onDateSelectedComplete + "})()", { + 'date':date, + 'allDay':allDay, + 'request':request, + 'event':event, + 'view':view, + 'data':data + }); + } + } ); } + return result; }; var selectedView; - //TODO how to hide all (except for view param) scopeChain from code in options.onViewDisplay? - var viewDisplay = function(view) { - if (options.onViewDisplay != null) { - var result = eval("(function(){" + options.onViewDisplay + "})()"); - if (result != null) { - throw "return not allowed in onViewDisplay"; - } - } + var viewChanged = function(view) { if (selectedView != view && selectedView != undefined) { + if (options.onViewChanged != null) { + RichFaces.Schedule.eval("(function(){" + options.onViewChanged + "})()", { + 'view':view + }); + } if (_this.submitEventFunction != null) { _this.submitEventFunction({}, view.name, viewChangedEventName, - null, null, null, null, null, null, null + null, null, null, null, null, null, function(request, event, data) { + if (options.onViewChangedComplete != null) { + RichFaces.Schedule.eval("(function(){" + options.onViewChangedComplete + "})()", { + 'view':view, + 'request':request, + 'data':data + }); + } + } ); } } selectedView = view; }; - var onDateRangeSelected = function(startDate, endDate, allDay) { + var onDateRangeSelected = function(startDate, endDate, allDay, view) { if (!component.fullCalendar('option', 'selectable')) { - return; + return false; } + var result; if (options.onDateRangeSelected != null) { - var result = eval("(function(){" + options.onDateRangeSelected + "})()"); - if (result != null) { - return; - } + result = RichFaces.Schedule.eval("(function(){" + options.onDateRangeSelected + "})()", { + 'startDate':startDate, + 'endDate':endDate, + 'allDay':allDay, + 'view':view + }); + } + if (result === false) { + /** + * Unselect must be in all three places below in order to + * avoid situation where, while event is being sent via ajax + * to server, client side selection disapeares. + * Current implementation shortens delay between selection + * disapearing and potentialy created event appearing. + */ + component.fullCalendar('unselect'); + return false; } if (_this.submitEventFunction != null) { _this.submitEventFunction({}, @@ -209,11 +353,22 @@ window.RichFaces.Schedule = (function() { function(request, event, data) { component.fullCalendar('refetchEvents'); component.fullCalendar('unselect'); + if (options.onDateRangeSelected != null) { + RichFaces.Schedule.eval("(function(){" + options.onDateRangeSelectedComplete + "})()", { + 'startDate':startDate, + 'endDate':endDate, + 'allDay':allDay, + 'view':view, + 'request':request, + 'data':data + }); + } } ); } else { component.fullCalendar('unselect'); } + return result; }; options = jQuery.extend({ events: fillCalendarFunction, @@ -226,14 +381,26 @@ window.RichFaces.Schedule = (function() { eventClick: itemClick, eventMouseover: itemMouseover, eventMouseout: itemMouseout, - viewDisplay: viewDisplay, + viewDisplay: viewChanged, dayClick: dayClick, select: onDateRangeSelected }, options); jQuery(document).ready(function() { component = jQuery(elt).fullCalendar(options); + elt.component = _this; + _this.component = component; }); }; }()); -window.RichFaces.Schedule.prototype.messages = {}; \ No newline at end of file +window.RichFaces.Schedule.prototype.refetchItems = function() { + this.component.fullCalendar('refetchEvents'); +}; +window.RichFaces.Schedule.prototype.messages = {}; +window.RichFaces.Schedule.eval = function(template, object) { + var value = ''; + with (object) { + value = eval(template); + } + return value; +}; \ No newline at end of file diff --git a/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js b/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js index 5493e0a..698d6a0 100644 --- a/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js +++ b/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js @@ -7,513 +7,530 @@ * * http://docs.jquery.com/UI */ -;jQuery.ui || (function($) { - -var _remove = $.fn.remove, - isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9); - -//Helper functions and ui object -$.ui = { - version: "1.7.2", - - // $.ui.plugin is deprecated. Use the proxy pattern instead. - plugin: { - add: function(module, option, set) { - var proto = $.ui[module].prototype; - for(var i in set) { - proto.plugins[i] = proto.plugins[i] || []; - proto.plugins[i].push([option, set[i]]); - } - }, - call: function(instance, name, args) { - var set = instance.plugins[name]; - if(!set || !instance.element[0].parentNode) { return; } - - for (var i = 0; i < set.length; i++) { - if (instance.options[set[i][0]]) { - set[i][1].apply(instance.element, args); - } - } - } - }, - - contains: function(a, b) { - return document.compareDocumentPosition - ? a.compareDocumentPosition(b) & 16 - : a !== b && a.contains(b); - }, - - hasScroll: function(el, a) { - - //If overflow is hidden, the element might have extra content, but the user wants to hide it - if ($(el).css('overflow') == 'hidden') { return false; } - - var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop', - has = false; - - if (el[scroll] > 0) { return true; } - - // TODO: determine which cases actually cause this to happen - // if the element doesn't have the scroll set, see if it's possible to - // set the scroll - el[scroll] = 1; - has = (el[scroll] > 0); - el[scroll] = 0; - return has; - }, - - isOverAxis: function(x, reference, size) { - //Determines when x coordinate is over "b" element axis - return (x > reference) && (x < (reference + size)); - }, - - isOver: function(y, x, top, left, height, width) { - //Determines when x, y coordinates is over "b" element - return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width); - }, - - keyCode: { - BACKSPACE: 8, - CAPS_LOCK: 20, - COMMA: 188, - CONTROL: 17, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - INSERT: 45, - LEFT: 37, - NUMPAD_ADD: 107, - NUMPAD_DECIMAL: 110, - NUMPAD_DIVIDE: 111, - NUMPAD_ENTER: 108, - NUMPAD_MULTIPLY: 106, - NUMPAD_SUBTRACT: 109, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SHIFT: 16, - SPACE: 32, - TAB: 9, - UP: 38 - } -}; - -// WAI-ARIA normalization -if (isFF2) { - var attr = $.attr, - removeAttr = $.fn.removeAttr, - ariaNS = "http://www.w3.org/2005/07/aaa", - ariaState = /^aria-/, - ariaRole = /^wairole:/; - - $.attr = function(elem, name, value) { - var set = value !== undefined; - - return (name == 'role' - ? (set - ? attr.call(this, elem, name, "wairole:" + value) - : (attr.apply(this, arguments) || "").replace(ariaRole, "")) - : (ariaState.test(name) - ? (set - ? elem.setAttributeNS(ariaNS, - name.replace(ariaState, "aaa:"), value) - : attr.call(this, elem, name.replace(ariaState, "aaa:"))) - : attr.apply(this, arguments))); - }; - - $.fn.removeAttr = function(name) { - return (ariaState.test(name) - ? this.each(function() { - this.removeAttributeNS(ariaNS, name.replace(ariaState, "")); - }) : removeAttr.call(this, name)); - }; -} - -//jQuery plugins -$.fn.extend({ - remove: function() { - // Safari has a native remove event which actually removes DOM elements, - // so we have to use triggerHandler instead of trigger (#3037). - $("*", this).add(this).each(function() { - $(this).triggerHandler("remove"); - }); - return _remove.apply(this, arguments ); - }, - - enableSelection: function() { - return this - .attr('unselectable', 'off') - .css('MozUserSelect', '') - .unbind('selectstart.ui'); - }, - - disableSelection: function() { - return this - .attr('unselectable', 'on') - .css('MozUserSelect', 'none') - .bind('selectstart.ui', function() { return false; }); - }, - - scrollParent: function() { - var scrollParent; - if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { - scrollParent = this.parents().filter(function() { - return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); - }).eq(0); - } else { - scrollParent = this.parents().filter(function() { - return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); - }).eq(0); - } - - return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; - } -}); - - -//Additional selectors -$.extend($.expr[':'], { - data: function(elem, i, match) { - return !!$.data(elem, match[3]); - }, - - focusable: function(element) { - var nodeName = element.nodeName.toLowerCase(), - tabIndex = $.attr(element, 'tabindex'); - return (/input|select|textarea|button|object/.test(nodeName) - ? !element.disabled - : 'a' == nodeName || 'area' == nodeName - ? element.href || !isNaN(tabIndex) - : !isNaN(tabIndex)) - // the element and all of its ancestors must be visible - // the browser may report that the area is hidden - && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length; - }, - - tabbable: function(element) { - var tabIndex = $.attr(element, 'tabindex'); - return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable'); - } -}); - - -// $.widget is a factory to create jQuery plugins -// taking some boilerplate code out of the plugin code -function getter(namespace, plugin, method, args) { - function getMethods(type) { - var methods = $[namespace][plugin][type] || []; - return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods); - } - - var methods = getMethods('getter'); - if (args.length == 1 && typeof args[0] == 'string') { - methods = methods.concat(getMethods('getterSetter')); - } - return ($.inArray(method, methods) != -1); -} - -$.widget = function(name, prototype) { - var namespace = name.split(".")[0]; - name = name.split(".")[1]; - - // create plugin method - $.fn[name] = function(options) { - var isMethodCall = (typeof options == 'string'), - args = Array.prototype.slice.call(arguments, 1); - - // prevent calls to internal methods - if (isMethodCall && options.substring(0, 1) == '_') { - return this; - } - - // handle getter methods - if (isMethodCall && getter(namespace, name, options, args)) { - var instance = $.data(this[0], name); - return (instance ? instance[options].apply(instance, args) - : undefined); - } - - // handle initialization and non-getter methods - return this.each(function() { - var instance = $.data(this, name); - - // constructor - (!instance && !isMethodCall && - $.data(this, name, new $[namespace][name](this, options))._init()); - - // method call - (instance && isMethodCall && $.isFunction(instance[options]) && - instance[options].apply(instance, args)); - }); - }; - - // create widget constructor - $[namespace] = $[namespace] || {}; - $[namespace][name] = function(element, options) { - var self = this; - - this.namespace = namespace; - this.widgetName = name; - this.widgetEventPrefix = $[namespace][name].eventPrefix || name; - this.widgetBaseClass = namespace + '-' + name; - - this.options = $.extend({}, - $.widget.defaults, - $[namespace][name].defaults, - $.metadata && $.metadata.get(element)[name], - options); - - this.element = $(element) - .bind('setData.' + name, function(event, key, value) { - if (event.target == element) { - return self._setData(key, value); - } - }) - .bind('getData.' + name, function(event, key) { - if (event.target == element) { - return self._getData(key); - } - }) - .bind('remove', function() { - return self.destroy(); - }); - }; - - // add widget prototype - $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype); - - // TODO: merge getter and getterSetter properties from widget prototype - // and plugin prototype - $[namespace][name].getterSetter = 'option'; -}; - -$.widget.prototype = { - _init: function() {}, - destroy: function() { - this.element.removeData(this.widgetName) - .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled') - .removeAttr('aria-disabled'); - }, - - option: function(key, value) { - var options = key, - self = this; - - if (typeof key == "string") { - if (value === undefined) { - return this._getData(key); - } - options = {}; - options[key] = value; - } - - $.each(options, function(key, value) { - self._setData(key, value); - }); - }, - _getData: function(key) { - return this.options[key]; - }, - _setData: function(key, value) { - this.options[key] = value; - - if (key == 'disabled') { - this.element - [value ? 'addClass' : 'removeClass']( - this.widgetBaseClass + '-disabled' + ' ' + - this.namespace + '-state-disabled') - .attr("aria-disabled", value); - } - }, - - enable: function() { - this._setData('disabled', false); - }, - disable: function() { - this._setData('disabled', true); - }, - - _trigger: function(type, event, data) { - var callback = this.options[type], - eventName = (type == this.widgetEventPrefix - ? type : this.widgetEventPrefix + type); - - event = $.Event(event); - event.type = eventName; - - // copy original event properties over to the new event - // this would happen if we could call $.event.fix instead of $.Event - // but we don't have a way to force an event to be fixed multiple times - if (event.originalEvent) { - for (var i = $.event.props.length, prop; i;) { - prop = $.event.props[--i]; - event[prop] = event.originalEvent[prop]; - } - } - - this.element.trigger(event, data); - - return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false - || event.isDefaultPrevented()); - } -}; - -$.widget.defaults = { - disabled: false -}; - - -/** Mouse Interaction Plugin **/ - -$.ui.mouse = { - _mouseInit: function() { - var self = this; - - this.element - .bind('mousedown.'+this.widgetName, function(event) { - return self._mouseDown(event); - }) - .bind('click.'+this.widgetName, function(event) { - if(self._preventClickEvent) { - self._preventClickEvent = false; - event.stopImmediatePropagation(); - return false; - } - }); - - // Prevent text selection in IE - if ($.browser.msie) { - this._mouseUnselectable = this.element.attr('unselectable'); - this.element.attr('unselectable', 'on'); - } - - this.started = false; - }, - - // TODO: make sure destroying one instance of mouse doesn't mess with - // other instances of mouse - _mouseDestroy: function() { - this.element.unbind('.'+this.widgetName); - - // Restore text selection in IE - ($.browser.msie - && this.element.attr('unselectable', this._mouseUnselectable)); - }, - - _mouseDown: function(event) { - // don't let more than one widget handle mouseStart - // TODO: figure out why we have to use originalEvent - event.originalEvent = event.originalEvent || {}; - if (event.originalEvent.mouseHandled) { return; } - - // we may have missed mouseup (out of window) - (this._mouseStarted && this._mouseUp(event)); - - this._mouseDownEvent = event; - - var self = this, - btnIsLeft = (event.which == 1), - elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false); - if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { - return true; - } - - this.mouseDelayMet = !this.options.delay; - if (!this.mouseDelayMet) { - this._mouseDelayTimer = setTimeout(function() { - self.mouseDelayMet = true; - }, this.options.delay); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = (this._mouseStart(event) !== false); - if (!this._mouseStarted) { - event.preventDefault(); - return true; - } - } - - // these delegates are required to keep context - this._mouseMoveDelegate = function(event) { - return self._mouseMove(event); - }; - this._mouseUpDelegate = function(event) { - return self._mouseUp(event); - }; - $(document) - .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) - .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); - - // preventDefault() is used to prevent the selection of text here - - // however, in Safari, this causes select boxes not to be selectable - // anymore, so this fix is needed - ($.browser.safari || event.preventDefault()); - - event.originalEvent.mouseHandled = true; - return true; - }, - - _mouseMove: function(event) { - // IE mouseup check - mouseup happened when mouse was out of window - if ($.browser.msie && !event.button) { - return this._mouseUp(event); - } - - if (this._mouseStarted) { - this._mouseDrag(event); - return event.preventDefault(); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = - (this._mouseStart(this._mouseDownEvent, event) !== false); - (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); - } - - return !this._mouseStarted; - }, - - _mouseUp: function(event) { - $(document) - .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) - .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); - - if (this._mouseStarted) { - this._mouseStarted = false; - this._preventClickEvent = (event.target == this._mouseDownEvent.target); - this._mouseStop(event); - } - - return false; - }, - - _mouseDistanceMet: function(event) { - return (Math.max( - Math.abs(this._mouseDownEvent.pageX - event.pageX), - Math.abs(this._mouseDownEvent.pageY - event.pageY) - ) >= this.options.distance - ); - }, - - _mouseDelayMet: function(event) { - return this.mouseDelayMet; - }, - - // These are placeholder methods, to be overriden by extending plugin - _mouseStart: function(event) {}, - _mouseDrag: function(event) {}, - _mouseStop: function(event) {}, - _mouseCapture: function(event) { return true; } -}; - -$.ui.mouse.defaults = { - cancel: null, - distance: 1, - delay: 0 -}; +; +jQuery.ui || (function($) { + + var _remove = $.fn.remove, + isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9); + + //Helper functions and ui object + $.ui = { + version: "1.7.2", + + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function(module, option, set) { + var proto = $.ui[module].prototype; + for (var i in set) { + proto.plugins[i] = proto.plugins[i] || []; + proto.plugins[i].push([option, set[i]]); + } + }, + call: function(instance, name, args) { + var set = instance.plugins[name]; + if (!set || !instance.element[0].parentNode) { + return; + } + + for (var i = 0; i < set.length; i++) { + if (instance.options[set[i][0]]) { + set[i][1].apply(instance.element, args); + } + } + } + }, + + contains: function(a, b) { + return document.compareDocumentPosition + ? a.compareDocumentPosition(b) & 16 + : a !== b && a.contains(b); + }, + + hasScroll: function(el, a) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ($(el).css('overflow') == 'hidden') { + return false; + } + + var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop', + has = false; + + if (el[scroll] > 0) { + return true; + } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[scroll] = 1; + has = (el[scroll] > 0); + el[scroll] = 0; + return has; + }, + + isOverAxis: function(x, reference, size) { + //Determines when x coordinate is over "b" element axis + return (x > reference) && (x < (reference + size)); + }, + + isOver: function(y, x, top, left, height, width) { + //Determines when x, y coordinates is over "b" element + return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width); + }, + + keyCode: { + BACKSPACE: 8, + CAPS_LOCK: 20, + COMMA: 188, + CONTROL: 17, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + INSERT: 45, + LEFT: 37, + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SHIFT: 16, + SPACE: 32, + TAB: 9, + UP: 38 + } + }; + + // WAI-ARIA normalization + if (isFF2) { + var attr = $.attr, + removeAttr = $.fn.removeAttr, + ariaNS = "http://www.w3.org/2005/07/aaa", + ariaState = /^aria-/, + ariaRole = /^wairole:/; + + $.attr = function(elem, name, value) { + var set = value !== undefined; + + return (name == 'role' + ? (set + ? attr.call(this, elem, name, "wairole:" + value) + : (attr.apply(this, arguments) || "").replace(ariaRole, "")) + : (ariaState.test(name) + ? (set + ? elem.setAttributeNS(ariaNS, + name.replace(ariaState, "aaa:"), value) + : attr.call(this, elem, name.replace(ariaState, "aaa:"))) + : attr.apply(this, arguments))); + }; + + $.fn.removeAttr = function(name) { + return (ariaState.test(name) + ? this.each(function() { + this.removeAttributeNS(ariaNS, name.replace(ariaState, "")); + }) : removeAttr.call(this, name)); + }; + } + + //jQuery plugins + $.fn.extend({ + remove: function() { + // Safari has a native remove event which actually removes DOM elements, + // so we have to use triggerHandler instead of trigger (#3037). + $("*", this).add(this).each(function() { + $(this).triggerHandler("remove"); + }); + return _remove.apply(this, arguments); + }, + + enableSelection: function() { + return this + .attr('unselectable', 'off') + .css('MozUserSelect', '') + .unbind('selectstart.ui'); + }, + + disableSelection: function() { + return this + .attr('unselectable', 'on') + .css('MozUserSelect', 'none') + .bind('selectstart.ui', function() { + return false; + }); + }, + + scrollParent: function() { + var scrollParent; + if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.curCSS(this, 'position', 1)) && (/(auto|scroll)/).test($.curCSS(this, 'overflow', 1) + $.curCSS(this, 'overflow-y', 1) + $.curCSS(this, 'overflow-x', 1)); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.curCSS(this, 'overflow', 1) + $.curCSS(this, 'overflow-y', 1) + $.curCSS(this, 'overflow-x', 1)); + }).eq(0); + } + + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; + } + }); + + + //Additional selectors + $.extend($.expr[':'], { + data: function(elem, i, match) { + return !!$.data(elem, match[3]); + }, + + focusable: function(element) { + var nodeName = element.nodeName.toLowerCase(), + tabIndex = $.attr(element, 'tabindex'); + return (/input|select|textarea|button|object/.test(nodeName) + ? !element.disabled + : 'a' == nodeName || 'area' == nodeName + ? element.href || !isNaN(tabIndex) + : !isNaN(tabIndex)) + // the element and all of its ancestors must be visible + // the browser may report that the area is hidden + && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length; + }, + + tabbable: function(element) { + var tabIndex = $.attr(element, 'tabindex'); + return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable'); + } + }); + + + // $.widget is a factory to create jQuery plugins + // taking some boilerplate code out of the plugin code + function getter(namespace, plugin, method, args) { + function getMethods(type) { + var methods = $[namespace][plugin][type] || []; + return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods); + } + + var methods = getMethods('getter'); + if (args.length == 1 && typeof args[0] == 'string') { + methods = methods.concat(getMethods('getterSetter')); + } + return ($.inArray(method, methods) != -1); + } + + $.widget = function(name, prototype) { + var namespace = name.split(".")[0]; + name = name.split(".")[1]; + + // create plugin method + $.fn[name] = function(options) { + var isMethodCall = (typeof options == 'string'), + args = Array.prototype.slice.call(arguments, 1); + + // prevent calls to internal methods + if (isMethodCall && options.substring(0, 1) == '_') { + return this; + } + + // handle getter methods + if (isMethodCall && getter(namespace, name, options, args)) { + var instance = $.data(this[0], name); + return (instance ? instance[options].apply(instance, args) + : undefined); + } + + // handle initialization and non-getter methods + return this.each(function() { + var instance = $.data(this, name); + + // constructor + (!instance && !isMethodCall && + $.data(this, name, new $[namespace][name](this, options))._init()); + + // method call + (instance && isMethodCall && $.isFunction(instance[options]) && + instance[options].apply(instance, args)); + }); + }; + + // create widget constructor + $[namespace] = $[namespace] || {}; + $[namespace][name] = function(element, options) { + var self = this; + + this.namespace = namespace; + this.widgetName = name; + this.widgetEventPrefix = $[namespace][name].eventPrefix || name; + this.widgetBaseClass = namespace + '-' + name; + + this.options = $.extend({}, + $.widget.defaults, + $[namespace][name].defaults, + $.metadata && $.metadata.get(element)[name], + options); + + this.element = $(element) + .bind('setData.' + name, function(event, key, value) { + if (event.target == element) { + return self._setData(key, value); + } + }) + .bind('getData.' + name, function(event, key) { + if (event.target == element) { + return self._getData(key); + } + }) + .bind('remove', function() { + return self.destroy(); + }); + }; + + // add widget prototype + $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype); + + // TODO: merge getter and getterSetter properties from widget prototype + // and plugin prototype + $[namespace][name].getterSetter = 'option'; + }; + + $.widget.prototype = { + _init: function() { + }, + destroy: function() { + this.element.removeData(this.widgetName) + .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled') + .removeAttr('aria-disabled'); + }, + + option: function(key, value) { + var options = key, + self = this; + + if (typeof key == "string") { + if (value === undefined) { + return this._getData(key); + } + options = {}; + options[key] = value; + } + + $.each(options, function(key, value) { + self._setData(key, value); + }); + }, + _getData: function(key) { + return this.options[key]; + }, + _setData: function(key, value) { + this.options[key] = value; + + if (key == 'disabled') { + this.element + [value ? 'addClass' : 'removeClass']( + this.widgetBaseClass + '-disabled' + ' ' + + this.namespace + '-state-disabled') + .attr("aria-disabled", value); + } + }, + + enable: function() { + this._setData('disabled', false); + }, + disable: function() { + this._setData('disabled', true); + }, + + _trigger: function(type, event, data) { + var callback = this.options[type], + eventName = (type == this.widgetEventPrefix + ? type : this.widgetEventPrefix + type); + + event = $.Event(event); + event.type = eventName; + + // copy original event properties over to the new event + // this would happen if we could call $.event.fix instead of $.Event + // but we don't have a way to force an event to be fixed multiple times + if (event.originalEvent) { + for (var i = $.event.props.length, prop; i;) { + prop = $.event.props[--i]; + event[prop] = event.originalEvent[prop]; + } + } + + this.element.trigger(event, data); + + return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false + || event.isDefaultPrevented()); + } + }; + + $.widget.defaults = { + disabled: false + }; + + + /** Mouse Interaction Plugin **/ + + $.ui.mouse = { + _mouseInit: function() { + var self = this; + + this.element + .bind('mousedown.' + this.widgetName, function(event) { + return self._mouseDown(event); + }) + .bind('click.' + this.widgetName, function(event) { + if (self._preventClickEvent) { + self._preventClickEvent = false; + event.stopImmediatePropagation(); + return false; + } + }); + + // Prevent text selection in IE + if ($.browser.msie) { + this._mouseUnselectable = this.element.attr('unselectable'); + this.element.attr('unselectable', 'on'); + } + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind('.' + this.widgetName); + + // Restore text selection in IE + ($.browser.msie + && this.element.attr('unselectable', this._mouseUnselectable)); + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + // TODO: figure out why we have to use originalEvent + event.originalEvent = event.originalEvent || {}; + if (event.originalEvent.mouseHandled) { + return; + } + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var self = this, + btnIsLeft = (event.which == 1), + elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + self.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return self._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return self._mouseUp(event); + }; + $(document) + .bind('mousemove.' + this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.' + this.widgetName, this._mouseUpDelegate); + + // preventDefault() is used to prevent the selection of text here - + // however, in Safari, this causes select boxes not to be selectable + // anymore, so this fix is needed + ($.browser.safari || event.preventDefault()); + + event.originalEvent.mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.browser.msie && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind('mousemove.' + this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.' + this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + this._preventClickEvent = (event.target == this._mouseDownEvent.target); + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(event) { + }, + _mouseDrag: function(event) { + }, + _mouseStop: function(event) { + }, + _mouseCapture: function(event) { + return true; + } + }; + + $.ui.mouse.defaults = { + cancel: null, + distance: 1, + delay: 0 + }; })(jQuery); diff --git a/src/main/resources/org/richfaces/renderkit/html/scripts/ui.draggable.js b/src/main/resources/org/richfaces/renderkit/html/scripts/ui.draggable.js index 0402f0e..d4eec22 100644 --- a/src/main/resources/org/richfaces/renderkit/html/scripts/ui.draggable.js +++ b/src/main/resources/org/richfaces/renderkit/html/scripts/ui.draggable.js @@ -12,755 +12,763 @@ */ (function($) { -$.widget("ui.draggable", $.extend({}, $.ui.mouse, { + $.widget("ui.draggable", $.extend({}, $.ui.mouse, { - _init: function() { + _init: function() { - if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) - this.element[0].style.position = 'relative'; + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; - (this.options.addClasses && this.element.addClass("ui-draggable")); - (this.options.disabled && this.element.addClass("ui-draggable-disabled")); + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); - this._mouseInit(); + this._mouseInit(); - }, + }, - destroy: function() { - if(!this.element.data('draggable')) return; - this.element - .removeData("draggable") - .unbind(".draggable") - .removeClass("ui-draggable" - + " ui-draggable-dragging" - + " ui-draggable-disabled"); - this._mouseDestroy(); - }, + destroy: function() { + if (!this.element.data('draggable')) return; + this.element + .removeData("draggable") + .unbind(".draggable") + .removeClass("ui-draggable" + + " ui-draggable-dragging" + + " ui-draggable-disabled"); + this._mouseDestroy(); + }, - _mouseCapture: function(event) { + _mouseCapture: function(event) { - var o = this.options; + var o = this.options; - if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) - return false; + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; - //Quit if we're not on a valid handle - this.handle = this._getHandle(event); - if (!this.handle) - return false; + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; - return true; + return true; - }, + }, - _mouseStart: function(event) { + _mouseStart: function(event) { - var o = this.options; + var o = this.options; - //Create and append the visible helper - this.helper = this._createHelper(event); + //Create and append the visible helper + this.helper = this._createHelper(event); - //Cache the helper size - this._cacheHelperProportions(); + //Cache the helper size + this._cacheHelperProportions(); - //If ddmanager is used for droppables, set the global draggable - if($.ui.ddmanager) - $.ui.ddmanager.current = this; + //If ddmanager is used for droppables, set the global draggable + if ($.ui.ddmanager) + $.ui.ddmanager.current = this; - /* - * - Position generation - - * This block generates everything position related - it's the core of draggables. - */ + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ - //Cache the margins of the original element - this._cacheMargins(); + //Cache the margins of the original element + this._cacheMargins(); - //Store the helper's css position - this.cssPosition = this.helper.css("position"); - this.scrollParent = this.helper.scrollParent(); + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); - //The element's absolute position on the page minus margins - this.offset = this.element.offset(); - this.offset = { - top: this.offset.top - this.margins.top, - left: this.offset.left - this.margins.left - }; + //The element's absolute position on the page minus margins + this.offset = this.element.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; - $.extend(this.offset, { - click: { //Where the click happened, relative to the element - left: event.pageX - this.offset.left, - top: event.pageY - this.offset.top - }, - parent: this._getParentOffset(), - relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper - }); + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); - //Generate the original position - this.originalPosition = this._generatePosition(event); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; - //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied - if(o.cursorAt) - this._adjustOffsetFromHelper(o.cursorAt); + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + if (o.cursorAt) + this._adjustOffsetFromHelper(o.cursorAt); - //Set a containment if given in the options - if(o.containment) - this._setContainment(); + //Set a containment if given in the options + if (o.containment) + this._setContainment(); - //Call plugins and callbacks - this._trigger("start", event); + //Call plugins and callbacks + this._trigger("start", event); - //Recache the helper size - this._cacheHelperProportions(); + //Recache the helper size + this._cacheHelperProportions(); - //Prepare the droppable offsets - if ($.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(this, event); + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); - this.helper.addClass("ui-draggable-dragging"); - this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position - return true; - }, + this.helper.addClass("ui-draggable-dragging"); + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + }, - _mouseDrag: function(event, noPropagation) { + _mouseDrag: function(event, noPropagation) { - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); - - //Call plugins and callbacks and use the resulting position if something is returned - if (!noPropagation) { - var ui = this._uiHash(); - this._trigger('drag', event, ui); - this.position = ui.position; - } + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + this._trigger('drag', event, ui); + this.position = ui.position; + } - if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; - if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; - if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left + 'px'; + if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top + 'px'; + if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event); - return false; - }, - - _mouseStop: function(event) { - - //If we are using droppables, inform the manager about the drop - var dropped = false; - if ($.ui.ddmanager && !this.options.dropBehaviour) - dropped = $.ui.ddmanager.drop(this, event); - - //if a drop comes from outside (a sortable) - if(this.dropped) { - dropped = this.dropped; - this.dropped = false; - } - - if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { - var self = this; - $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { - self._trigger("stop", event); - self._clear(); - }); - } else { - this._trigger("stop", event); - this._clear(); - } - - return false; - }, - - _getHandle: function(event) { - - var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; - $(this.options.handle, this.element) - .find("*") - .andSelf() - .each(function() { - if(this == event.target) handle = true; - }); - - return handle; - - }, - - _createHelper: function(event) { - - var o = this.options; - var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element); - - if(!helper.parents('body').length) - helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); - - if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) - helper.css("position", "absolute"); - - return helper; - - }, - - _adjustOffsetFromHelper: function(obj) { - if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left; - if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; - if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top; - if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; - }, - - _getParentOffset: function() { - - //Get the offsetParent and cache its position - this.offsetParent = this.helper.offsetParent(); - var po = this.offsetParent.offset(); - - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); - } - - if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information - || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix - po = { top: 0, left: 0 }; - - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; - - }, - - _getRelativeOffset: function() { - - if(this.cssPosition == "relative") { - var p = this.element.position(); - return { - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() - }; - } else { - return { top: 0, left: 0 }; - } - - }, - - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.element.css("marginLeft"),10) || 0), - top: (parseInt(this.element.css("marginTop"),10) || 0) - }; - }, - - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, - - _setContainment: function() { - - var o = this.options; - if(o.containment == 'parent') o.containment = this.helper[0].parentNode; - if(o.containment == 'document' || o.containment == 'window') this.containment = [ - 0 - this.offset.relative.left - this.offset.parent.left, - 0 - this.offset.relative.top - this.offset.parent.top, - $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, - ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top - ]; - - if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { - var ce = $(o.containment)[0]; if(!ce) return; - var co = $(o.containment).offset(); - var over = ($(ce).css("overflow") != 'hidden'); - - this.containment = [ - co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, - co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, - co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, - co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - ]; - } else if(o.containment.constructor == Array) { - this.containment = o.containment; - } - - }, - - _convertPositionTo: function(d, pos) { - - if(!pos) pos = this.position; - var mod = d == "absolute" ? 1 : -1; - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - return { - top: ( - pos.top // The absolute mouse position - + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent - + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) - - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) - ), - left: ( - pos.left // The absolute mouse position - + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent - + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) - - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; - - }, - - _generatePosition: function(event) { - - var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - // This is another very weird special case that only happens for relative elements: - // 1. If the css position is relative - // 2. and the scroll parent is the document or similar to the offset parent - // we have to refresh the relative offset during the scroll so there are no jumps - if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { - this.offset.relative = this._getRelativeOffset(); - } - - var pageX = event.pageX; - var pageY = event.pageY; - - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ - - if(this.originalPosition) { //If we are not dragging yet, we won't check for options - - if(this.containment) { - if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; - if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; - if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; - if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; - } - - if(o.grid) { - var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; - pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - - var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; - pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } - - } - - return { - top: ( - pageY // The absolute mouse position - - this.offset.click.top // Click offset (relative to the element) - - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent - - this.offset.parent.top // The offsetParent's offset without borders (offset + border) - + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) - ), - left: ( - pageX // The absolute mouse position - - this.offset.click.left // Click offset (relative to the element) - - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent - - this.offset.parent.left // The offsetParent's offset without borders (offset + border) - + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; - - }, - - _clear: function() { - this.helper.removeClass("ui-draggable-dragging"); - if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); - //if($.ui.ddmanager) $.ui.ddmanager.current = null; - this.helper = null; - this.cancelHelperRemoval = false; - }, - - // From now on bulk stuff - mainly helpers - - _trigger: function(type, event, ui) { - ui = ui || this._uiHash(); - $.ui.plugin.call(this, type, [event, ui]); - if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins - return $.widget.prototype._trigger.call(this, type, event, ui); - }, - - plugins: {}, - - _uiHash: function(event) { - return { - helper: this.helper, - position: this.position, - absolutePosition: this.positionAbs, //deprecated - offset: this.positionAbs - }; - } - -})); - -$.extend($.ui.draggable, { - version: "1.7.2", - eventPrefix: "drag", - defaults: { - addClasses: true, - appendTo: "parent", - axis: false, - cancel: ":input,option", - connectToSortable: false, - containment: false, - cursor: "auto", - cursorAt: false, - delay: 0, - distance: 1, - grid: false, - handle: false, - helper: "original", - iframeFix: false, - opacity: false, - refreshPositions: false, - revert: false, - revertDuration: 500, - scope: "default", - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - snap: false, - snapMode: "both", - snapTolerance: 20, - stack: false, - zIndex: false - } -}); - -$.ui.plugin.add("draggable", "connectToSortable", { - start: function(event, ui) { - - var inst = $(this).data("draggable"), o = inst.options, - uiSortable = $.extend({}, ui, { item: inst.element }); - inst.sortables = []; - $(o.connectToSortable).each(function() { - var sortable = $.data(this, 'sortable'); - if (sortable && !sortable.options.disabled) { - inst.sortables.push({ - instance: sortable, - shouldRevert: sortable.options.revert - }); - sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache - sortable._trigger("activate", event, uiSortable); - } - }); - - }, - stop: function(event, ui) { - - //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper - var inst = $(this).data("draggable"), - uiSortable = $.extend({}, ui, { item: inst.element }); - - $.each(inst.sortables, function() { - if(this.instance.isOver) { - - this.instance.isOver = 0; - - inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance - this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) - - //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' - if(this.shouldRevert) this.instance.options.revert = true; - - //Trigger the stop of the sortable - this.instance._mouseStop(event); - - this.instance.options.helper = this.instance.options._helper; - - //If the helper has been the original item, restore properties in the sortable - if(inst.options.helper == 'original') - this.instance.currentItem.css({ top: 'auto', left: 'auto' }); - - } else { - this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance - this.instance._trigger("deactivate", event, uiSortable); - } - - }); - - }, - drag: function(event, ui) { - - var inst = $(this).data("draggable"), self = this; - - var checkPos = function(o) { - var dyClick = this.offset.click.top, dxClick = this.offset.click.left; - var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; - var itemHeight = o.height, itemWidth = o.width; - var itemTop = o.top, itemLeft = o.left; - - return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); - }; - - $.each(inst.sortables, function(i) { - - //Copy over some variables to allow calling the sortable's native _intersectsWith - this.instance.positionAbs = inst.positionAbs; - this.instance.helperProportions = inst.helperProportions; - this.instance.offset.click = inst.offset.click; - - if(this.instance._intersectsWith(this.instance.containerCache)) { - - //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once - if(!this.instance.isOver) { - - this.instance.isOver = 1; - //Now we fake the start of dragging for the sortable instance, - //by cloning the list group item, appending it to the sortable and using it as inst.currentItem - //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) - this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true); - this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it - this.instance.options.helper = function() { return ui.helper[0]; }; - - event.target = this.instance.currentItem[0]; - this.instance._mouseCapture(event, true); - this.instance._mouseStart(event, true, true); - - //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes - this.instance.offset.click.top = inst.offset.click.top; - this.instance.offset.click.left = inst.offset.click.left; - this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; - this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; - - inst._trigger("toSortable", event); - inst.dropped = this.instance.element; //draggable revert needs that - //hack so receive/update callbacks work (mostly) - inst.currentItem = inst.element; - this.instance.fromOutside = inst; - - } - - //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable - if(this.instance.currentItem) this.instance._mouseDrag(event); - - } else { - - //If it doesn't intersect with the sortable, and it intersected before, - //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval - if(this.instance.isOver) { - - this.instance.isOver = 0; - this.instance.cancelHelperRemoval = true; - - //Prevent reverting on this forced stop - this.instance.options.revert = false; - - // The out event needs to be triggered independently - this.instance._trigger('out', event, this.instance._uiHash(this.instance)); - - this.instance._mouseStop(event, true); - this.instance.options.helper = this.instance.options._helper; - - //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size - this.instance.currentItem.remove(); - if(this.instance.placeholder) this.instance.placeholder.remove(); - - inst._trigger("fromSortable", event); - inst.dropped = false; //draggable revert needs that - } - - }; - - }); - - } -}); - -$.ui.plugin.add("draggable", "cursor", { - start: function(event, ui) { - var t = $('body'), o = $(this).data('draggable').options; - if (t.css("cursor")) o._cursor = t.css("cursor"); - t.css("cursor", o.cursor); - }, - stop: function(event, ui) { - var o = $(this).data('draggable').options; - if (o._cursor) $('body').css("cursor", o._cursor); - } -}); - -$.ui.plugin.add("draggable", "iframeFix", { - start: function(event, ui) { - var o = $(this).data('draggable').options; - $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { - $('
') - .css({ - width: this.offsetWidth+"px", height: this.offsetHeight+"px", - position: "absolute", opacity: "0.001", zIndex: 1000 - }) - .css($(this).offset()) - .appendTo("body"); - }); - }, - stop: function(event, ui) { - $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers - } -}); - -$.ui.plugin.add("draggable", "opacity", { - start: function(event, ui) { - var t = $(ui.helper), o = $(this).data('draggable').options; - if(t.css("opacity")) o._opacity = t.css("opacity"); - t.css('opacity', o.opacity); - }, - stop: function(event, ui) { - var o = $(this).data('draggable').options; - if(o._opacity) $(ui.helper).css('opacity', o._opacity); - } -}); - -$.ui.plugin.add("draggable", "scroll", { - start: function(event, ui) { - var i = $(this).data("draggable"); - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); - }, - drag: function(event, ui) { - - var i = $(this).data("draggable"), o = i.options, scrolled = false; - - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { - - if(!o.axis || o.axis != 'x') { - if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) - i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; - else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) - i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; - } - - if(!o.axis || o.axis != 'y') { - if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) - i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; - else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) - i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; - } - - } else { - - if(!o.axis || o.axis != 'x') { - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); - } - - if(!o.axis || o.axis != 'y') { - if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); - } - - } - - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) - $.ui.ddmanager.prepareOffsets(i, event); - - } -}); - -$.ui.plugin.add("draggable", "snap", { - start: function(event, ui) { - - var i = $(this).data("draggable"), o = i.options; - i.snapElements = []; - - $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { - var $t = $(this); var $o = $t.offset(); - if(this != i.element[0]) i.snapElements.push({ - item: this, - width: $t.outerWidth(), height: $t.outerHeight(), - top: $o.top, left: $o.left - }); - }); - - }, - drag: function(event, ui) { - - var inst = $(this).data("draggable"), o = inst.options; - var d = o.snapTolerance; - - var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, - y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; - - for (var i = inst.snapElements.length - 1; i >= 0; i--){ - - var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, - t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; - - //Yes, I know, this is insane ;) - if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { - if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); - inst.snapElements[i].snapping = false; - continue; - } - - if(o.snapMode != 'inner') { - var ts = Math.abs(t - y2) <= d; - var bs = Math.abs(b - y1) <= d; - var ls = Math.abs(l - x2) <= d; - var rs = Math.abs(r - x1) <= d; - if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; - if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; - if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; - if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; - } - - var first = (ts || bs || ls || rs); - - if(o.snapMode != 'outer') { - var ts = Math.abs(t - y1) <= d; - var bs = Math.abs(b - y2) <= d; - var ls = Math.abs(l - x1) <= d; - var rs = Math.abs(r - x2) <= d; - if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; - if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; - if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; - if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; - } - - if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) - (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); - inst.snapElements[i].snapping = (ts || bs || ls || rs || first); - - }; - - } -}); - -$.ui.plugin.add("draggable", "stack", { - start: function(event, ui) { - - var o = $(this).data("draggable").options; - - var group = $.makeArray($(o.stack.group)).sort(function(a,b) { - return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min); - }); - - $(group).each(function(i) { - this.style.zIndex = o.stack.min + i; - }); - - this[0].style.zIndex = o.stack.min + group.length; - - } -}); - -$.ui.plugin.add("draggable", "zIndex", { - start: function(event, ui) { - var t = $(ui.helper), o = $(this).data("draggable").options; - if(t.css("zIndex")) o._zIndex = t.css("zIndex"); - t.css('zIndex', o.zIndex); - }, - stop: function(event, ui) { - var o = $(this).data("draggable").options; - if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); - } -}); + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if (this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + if ((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var self = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + self._trigger("stop", event); + self._clear(); + }); + } else { + this._trigger("stop", event); + this._clear(); + } + + return false; + }, + + _getHandle: function(event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function() { + if (this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element); + + if (!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if (helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (obj.left != undefined) this.offset.click.left = obj.left + this.margins.left; + if (obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + if (obj.top != undefined) this.offset.click.top = obj.top + this.margins.top; + if (obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if (this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if ((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if (this.cssPosition == "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"), 10) || 0), + top: (parseInt(this.element.css("marginTop"), 10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if (o.containment == 'parent') o.containment = this.helper[0].parentNode; + if (o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if (!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var ce = $(o.containment)[0]; + if (!ce) return; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top, + co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left, + co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top + ]; + } else if (o.containment.constructor == Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo: function(d, pos) { + + if (!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if (this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if (this.originalPosition) { //If we are not dragging yet, we won't check for options + + if (this.containment) { + if (event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if (event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if (event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if (event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if (o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if (this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if (type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins: {}, + + _uiHash: function(event) { + return { + helper: this.helper, + position: this.position, + absolutePosition: this.positionAbs, //deprecated + offset: this.positionAbs + }; + } + + })); + + $.extend($.ui.draggable, { + version: "1.7.2", + eventPrefix: "drag", + defaults: { + addClasses: true, + appendTo: "parent", + axis: false, + cancel: ":input,option", + connectToSortable: false, + containment: false, + cursor: "auto", + cursorAt: false, + delay: 0, + distance: 1, + grid: false, + handle: false, + helper: "original", + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scope: "default", + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false + } + }); + + $.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop: function(event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); + + $.each(inst.sortables, function() { + if (this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if (this.shouldRevert) this.instance.options.revert = true; + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if (inst.options.helper == 'original') + this.instance.currentItem.css({ top: 'auto', left: 'auto' }); + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), self = this; + + var checkPos = function(o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; + + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; + + $.each(inst.sortables, function(i) { + + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if (this.instance._intersectsWith(this.instance.containerCache)) { + + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if (!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { + return ui.helper[0]; + }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if (this.instance.currentItem) this.instance._mouseDrag(event); + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if (this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if (this.instance.placeholder) this.instance.placeholder.remove(); + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + } + ; + + }); + + } + }); + + $.ui.plugin.add("draggable", "cursor", { + start: function(event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } + }); + + $.ui.plugin.add("draggable", "iframeFix", { + start: function(event, ui) { + var o = $(this).data('draggable').options; + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $('
') + .css({ + width: this.offsetWidth + "px", height: this.offsetHeight + "px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + }, + stop: function(event, ui) { + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); + }); //Remove frame helpers + } + }); + + $.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if (t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._opacity) $(ui.helper).css('opacity', o._opacity); + } + }); + + $.ui.plugin.add("draggable", "scroll", { + start: function(event, ui) { + var i = $(this).data("draggable"); + if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options, scrolled = false; + + if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + + if (!o.axis || o.axis != 'x') { + if ((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if (!o.axis || o.axis != 'y') { + if ((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if (!o.axis || o.axis != 'x') { + if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if (!o.axis || o.axis != 'y') { + if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); + + } + }); + + $.ui.plugin.add("draggable", "snap", { + start: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + var $t = $(this); + var $o = $t.offset(); + if (this != i.element[0]) i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; + + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (var i = inst.snapElements.length - 1; i >= 0; i--) { + + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if (!((l - d < x1 && x1 < r + d && t - d < y1 && y1 < b + d) || (l - d < x1 && x1 < r + d && t - d < y2 && y2 < b + d) || (l - d < x2 && x2 < r + d && t - d < y1 && y1 < b + d) || (l - d < x2 && x2 < r + d && t - d < y2 && y2 < b + d))) { + if (inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if (o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if (ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if (bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + if (ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + if (rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if (o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if (ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + if (bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if (ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + if (rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + + if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + } + ; + + } + }); + + $.ui.plugin.add("draggable", "stack", { + start: function(event, ui) { + + var o = $(this).data("draggable").options; + + var group = $.makeArray($(o.stack.group)).sort(function(a, b) { + return (parseInt($(a).css("zIndex"), 10) || o.stack.min) - (parseInt($(b).css("zIndex"), 10) || o.stack.min); + }); + + $(group).each(function(i) { + this.style.zIndex = o.stack.min + i; + }); + + this[0].style.zIndex = o.stack.min + group.length; + + } + }); + + $.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if (t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("draggable").options; + if (o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } + }); })(jQuery); diff --git a/src/main/resources/org/richfaces/renderkit/html/scripts/ui.resizable.js b/src/main/resources/org/richfaces/renderkit/html/scripts/ui.resizable.js index 6172d6c..946f717 100644 --- a/src/main/resources/org/richfaces/renderkit/html/scripts/ui.resizable.js +++ b/src/main/resources/org/richfaces/renderkit/html/scripts/ui.resizable.js @@ -12,789 +12,803 @@ */ (function($) { -$.widget("ui.resizable", $.extend({}, $.ui.mouse, { + $.widget("ui.resizable", $.extend({}, $.ui.mouse, { - _init: function() { + _init: function() { - var self = this, o = this.options; - this.element.addClass("ui-resizable"); + var self = this, o = this.options; + this.element.addClass("ui-resizable"); - $.extend(this, { - _aspectRatio: !!(o.aspectRatio), - aspectRatio: o.aspectRatio, - originalElement: this.element, - _proportionallyResizeElements: [], - _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null - }); + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null + }); - //Wrap the element if it cannot hold child nodes - if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { + //Wrap the element if it cannot hold child nodes + if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { - //Opera fix for relative positioning - if (/relative/.test(this.element.css('position')) && $.browser.opera) - this.element.css({ position: 'relative', top: 'auto', left: 'auto' }); + //Opera fix for relative positioning + if (/relative/.test(this.element.css('position')) && $.browser.opera) + this.element.css({ position: 'relative', top: 'auto', left: 'auto' }); - //Create a wrapper element and set the wrapper to the new current internal element - this.element.wrap( - $('
').css({ - position: this.element.css('position'), - width: this.element.outerWidth(), - height: this.element.outerHeight(), - top: this.element.css('top'), - left: this.element.css('left') - }) - ); + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $('
').css({ + position: this.element.css('position'), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css('top'), + left: this.element.css('left') + }) + ); - //Overwrite the original this.element - this.element = this.element.parent().data( - "resizable", this.element.data('resizable') - ); + //Overwrite the original this.element + this.element = this.element.parent().data( + "resizable", this.element.data('resizable') + ); - this.elementIsWrapper = true; + this.elementIsWrapper = true; - //Move margins to the wrapper - this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); - this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); - //Prevent Safari textarea resize - this.originalResizeStyle = this.originalElement.css('resize'); - this.originalElement.css('resize', 'none'); + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css('resize'); + this.originalElement.css('resize', 'none'); - //Push the actual element to our proportionallyResize internal array - this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); - // avoid IE jump (hard set the margin) - this.originalElement.css({ margin: this.originalElement.css('margin') }); + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css('margin') }); - // fix handlers offset - this._proportionallyResize(); + // fix handlers offset + this._proportionallyResize(); - } + } - this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); - if(this.handles.constructor == String) { + this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); + if (this.handles.constructor == String) { - if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; - var n = this.handles.split(","); this.handles = {}; + if (this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; + var n = this.handles.split(","); + this.handles = {}; - for(var i = 0; i < n.length; i++) { + for (var i = 0; i < n.length; i++) { - var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; - var axis = $('
'); + var handle = $.trim(n[i]), hname = 'ui-resizable-' + handle; + var axis = $('
'); - // increase zIndex of sw, se, ne, nw axis - //TODO : this modifies original option - if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); + // increase zIndex of sw, se, ne, nw axis + //TODO : this modifies original option + if (/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); - //TODO : What's going on here? - if ('se' == handle) { - axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); - }; + //TODO : What's going on here? + if ('se' == handle) { + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); + } + ; - //Insert into internal handles object and append to element - this.handles[handle] = '.ui-resizable-'+handle; - this.element.append(axis); - } + //Insert into internal handles object and append to element + this.handles[handle] = '.ui-resizable-' + handle; + this.element.append(axis); + } - } + } + + this._renderAxis = function(target) { - this._renderAxis = function(target) { + target = target || this.element; - target = target || this.element; + for (var i in this.handles) { - for(var i in this.handles) { + if (this.handles[i].constructor == String) + this.handles[i] = $(this.handles[i], this.element).show(); - if(this.handles[i].constructor == String) - this.handles[i] = $(this.handles[i], this.element).show(); + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { - //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) - if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + var axis = $(this.handles[i], this.element), padWrapper = 0; - var axis = $(this.handles[i], this.element), padWrapper = 0; + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); - //Checking the correct pad and border - padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + //The padding type i have to apply... + var padPos = [ 'padding', + /ne|nw|n/.test(i) ? 'Top' : + /se|sw|s/.test(i) ? 'Bottom' : + /^e$/.test(i) ? 'Right' : 'Left' ].join(""); - //The padding type i have to apply... - var padPos = [ 'padding', - /ne|nw|n/.test(i) ? 'Top' : - /se|sw|s/.test(i) ? 'Bottom' : - /^e$/.test(i) ? 'Right' : 'Left' ].join(""); + target.css(padPos, padWrapper); - target.css(padPos, padWrapper); + this._proportionallyResize(); - this._proportionallyResize(); + } - } + //TODO: What's that good for? There's not anything to be executed left + if (!$(this.handles[i]).length) + continue; - //TODO: What's that good for? There's not anything to be executed left - if(!$(this.handles[i]).length) - continue; + } + }; - } - }; + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); - //TODO: make renderAxis a prototype function - this._renderAxis(this.element); + this._handles = $('.ui-resizable-handle', this.element) + .disableSelection(); - this._handles = $('.ui-resizable-handle', this.element) - .disableSelection(); + //Matching axis name + this._handles.mouseover(function() { + if (!self.resizing) { + if (this.className) + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + //Axis, default = se + self.axis = axis && axis[1] ? axis[1] : 'se'; + } + }); - //Matching axis name - this._handles.mouseover(function() { - if (!self.resizing) { - if (this.className) - var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); - //Axis, default = se - self.axis = axis && axis[1] ? axis[1] : 'se'; - } - }); + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .hover(function() { + $(this).removeClass("ui-resizable-autohide"); + self._handles.show(); + }, + function() { + if (!self.resizing) { + $(this).addClass("ui-resizable-autohide"); + self._handles.hide(); + } + }); + } - //If we want to auto hide the elements - if (o.autoHide) { - this._handles.hide(); - $(this.element) - .addClass("ui-resizable-autohide") - .hover(function() { - $(this).removeClass("ui-resizable-autohide"); - self._handles.show(); - }, - function(){ - if (!self.resizing) { - $(this).addClass("ui-resizable-autohide"); - self._handles.hide(); - } - }); - } + //Initialize the mouse interaction + this._mouseInit(); - //Initialize the mouse interaction - this._mouseInit(); + }, - }, + destroy: function() { - destroy: function() { + this._mouseDestroy(); - this._mouseDestroy(); + var _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); + }; - var _destroy = function(exp) { - $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") - .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); - }; + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + var wrapper = this.element; + wrapper.parent().append( + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }) + ).end().remove(); + } - //TODO: Unwrap at same DOM position - if (this.elementIsWrapper) { - _destroy(this.element); - var wrapper = this.element; - wrapper.parent().append( - this.originalElement.css({ - position: wrapper.css('position'), - width: wrapper.outerWidth(), - height: wrapper.outerHeight(), - top: wrapper.css('top'), - left: wrapper.css('left') - }) - ).end().remove(); - } + this.originalElement.css('resize', this.originalResizeStyle); + _destroy(this.originalElement); - this.originalElement.css('resize', this.originalResizeStyle); - _destroy(this.originalElement); + }, - }, + _mouseCapture: function(event) { - _mouseCapture: function(event) { + var handle = false; + for (var i in this.handles) { + if ($(this.handles[i])[0] == event.target) handle = true; + } - var handle = false; - for(var i in this.handles) { - if($(this.handles[i])[0] == event.target) handle = true; - } + return this.options.disabled || !!handle; - return this.options.disabled || !!handle; + }, - }, + _mouseStart: function(event) { - _mouseStart: function(event) { + var o = this.options, iniPos = this.element.position(), el = this.element; - var o = this.options, iniPos = this.element.position(), el = this.element; + this.resizing = true; + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; - this.resizing = true; - this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; + // bugfix for http://dev.jquery.com/ticket/1749 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); + } - // bugfix for http://dev.jquery.com/ticket/1749 - if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { - el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); - } + //Opera fixing relative position + if ($.browser.opera && (/relative/).test(el.css('position'))) + el.css({ position: 'relative', top: 'auto', left: 'auto' }); - //Opera fixing relative position - if ($.browser.opera && (/relative/).test(el.css('position'))) - el.css({ position: 'relative', top: 'auto', left: 'auto' }); + this._renderProxy(); - this._renderProxy(); + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); - var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; + } - if (o.containment) { - curleft += $(o.containment).scrollLeft() || 0; - curtop += $(o.containment).scrollTop() || 0; - } + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; - //Store needed variables - this.offset = this.helper.offset(); - this.position = { left: curleft, top: curtop }; - this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; - this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; - this.originalPosition = { left: curleft, top: curtop }; - this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; - this.originalMousePosition = { left: event.pageX, top: event.pageY }; + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); - //Aspect Ratio - this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); + var cursor = $('.ui-resizable-' + this.axis).css('cursor'); + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); - var cursor = $('.ui-resizable-' + this.axis).css('cursor'); - $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; + }, - el.addClass("ui-resizable-resizing"); - this._propagate("start", event); - return true; - }, + _mouseDrag: function(event) { - _mouseDrag: function(event) { + //Increase performance, avoid regex + var el = this.helper, o = this.options, props = {}, + self = this, smp = this.originalMousePosition, a = this.axis; - //Increase performance, avoid regex - var el = this.helper, o = this.options, props = {}, - self = this, smp = this.originalMousePosition, a = this.axis; + var dx = (event.pageX - smp.left) || 0, dy = (event.pageY - smp.top) || 0; + var trigger = this._change[a]; + if (!trigger) return false; - var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; - var trigger = this._change[a]; - if (!trigger) return false; + // Calculate the attrs that will be change + var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; - // Calculate the attrs that will be change - var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; + if (this._aspectRatio || event.shiftKey) + data = this._updateRatio(data, event); - if (this._aspectRatio || event.shiftKey) - data = this._updateRatio(data, event); + data = this._respectSize(data, event); - data = this._respectSize(data, event); + // plugins callbacks need to be called first + this._propagate("resize", event); - // plugins callbacks need to be called first - this._propagate("resize", event); + el.css({ + top: this.position.top + "px", left: this.position.left + "px", + width: this.size.width + "px", height: this.size.height + "px" + }); - el.css({ - top: this.position.top + "px", left: this.position.left + "px", - width: this.size.width + "px", height: this.size.height + "px" - }); + if (!this._helper && this._proportionallyResizeElements.length) + this._proportionallyResize(); - if (!this._helper && this._proportionallyResizeElements.length) - this._proportionallyResize(); + this._updateCache(data); - this._updateCache(data); + // calling the user callback at the end + this._trigger('resize', event, this.ui()); - // calling the user callback at the end - this._trigger('resize', event, this.ui()); + return false; + }, - return false; - }, + _mouseStop: function(event) { - _mouseStop: function(event) { + this.resizing = false; + var o = this.options, self = this; - this.resizing = false; - var o = this.options, self = this; + if (this._helper) { + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; - if(this._helper) { - var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), - soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, - soffsetw = ista ? 0 : self.sizeDiff.width; + var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; - var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, - left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, - top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + if (!o.animate) + this.element.css($.extend(s, { top: top, left: left })); - if (!o.animate) - this.element.css($.extend(s, { top: top, left: left })); + self.helper.height(self.size.height); + self.helper.width(self.size.width); - self.helper.height(self.size.height); - self.helper.width(self.size.width); + if (this._helper && !o.animate) this._proportionallyResize(); + } - if (this._helper && !o.animate) this._proportionallyResize(); - } + $('body').css('cursor', 'auto'); - $('body').css('cursor', 'auto'); + this.element.removeClass("ui-resizable-resizing"); - this.element.removeClass("ui-resizable-resizing"); + this._propagate("stop", event); - this._propagate("stop", event); + if (this._helper) this.helper.remove(); + return false; - if (this._helper) this.helper.remove(); - return false; + }, - }, + _updateCache: function(data) { + var o = this.options; + this.offset = this.helper.offset(); + if (isNumber(data.left)) this.position.left = data.left; + if (isNumber(data.top)) this.position.top = data.top; + if (isNumber(data.height)) this.size.height = data.height; + if (isNumber(data.width)) this.size.width = data.width; + }, - _updateCache: function(data) { - var o = this.options; - this.offset = this.helper.offset(); - if (isNumber(data.left)) this.position.left = data.left; - if (isNumber(data.top)) this.position.top = data.top; - if (isNumber(data.height)) this.size.height = data.height; - if (isNumber(data.width)) this.size.width = data.width; - }, + _updateRatio: function(data, event) { - _updateRatio: function(data, event) { + var o = this.options, cpos = this.position, csize = this.size, a = this.axis; - var o = this.options, cpos = this.position, csize = this.size, a = this.axis; + if (data.height) data.width = (csize.height * this.aspectRatio); + else if (data.width) data.height = (csize.width / this.aspectRatio); - if (data.height) data.width = (csize.height * this.aspectRatio); - else if (data.width) data.height = (csize.width / this.aspectRatio); + if (a == 'sw') { + data.left = cpos.left + (csize.width - data.width); + data.top = null; + } + if (a == 'nw') { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); + } - if (a == 'sw') { - data.left = cpos.left + (csize.width - data.width); - data.top = null; - } - if (a == 'nw') { - data.top = cpos.top + (csize.height - data.height); - data.left = cpos.left + (csize.width - data.width); - } + return data; + }, - return data; - }, + _respectSize: function(data, event) { - _respectSize: function(data, event) { + var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); - var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, - ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), - isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); + if (isminw) data.width = o.minWidth; + if (isminh) data.height = o.minHeight; + if (ismaxw) data.width = o.maxWidth; + if (ismaxh) data.height = o.maxHeight; - if (isminw) data.width = o.minWidth; - if (isminh) data.height = o.minHeight; - if (ismaxw) data.width = o.maxWidth; - if (ismaxh) data.height = o.maxHeight; + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); - var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; - var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); + if (isminw && cw) data.left = dw - o.minWidth; + if (ismaxw && cw) data.left = dw - o.maxWidth; + if (isminh && ch) data.top = dh - o.minHeight; + if (ismaxh && ch) data.top = dh - o.maxHeight; - if (isminw && cw) data.left = dw - o.minWidth; - if (ismaxw && cw) data.left = dw - o.maxWidth; - if (isminh && ch) data.top = dh - o.minHeight; - if (ismaxh && ch) data.top = dh - o.maxHeight; + // fixing jump error on top/left - bug #2330 + var isNotwh = !data.width && !data.height; + if (isNotwh && !data.left && data.top) data.top = null; + else if (isNotwh && !data.top && data.left) data.left = null; - // fixing jump error on top/left - bug #2330 - var isNotwh = !data.width && !data.height; - if (isNotwh && !data.left && data.top) data.top = null; - else if (isNotwh && !data.top && data.left) data.left = null; + return data; + }, - return data; - }, + _proportionallyResize: function() { - _proportionallyResize: function() { + var o = this.options; + if (!this._proportionallyResizeElements.length) return; + var element = this.helper || this.element; + + for (var i = 0; i < this._proportionallyResizeElements.length; i++) { + + var prel = this._proportionallyResizeElements[i]; + + if (!this.borderDif) { + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; + + this.borderDif = $.map(b, function(v, i) { + var border = parseInt(v, 10) || 0, padding = parseInt(p[i], 10) || 0; + return border + padding; + }); + } + + if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) + continue; + + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); + + } + ; + + }, + + _renderProxy: function() { + + var el = this.element, o = this.options; + this.elementOffset = el.offset(); + + if (this._helper) { + + this.helper = this.helper || $('
'); + + // fix ie6 offset TODO: This seems broken + var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), + pxyoffset = ( ie6 ? 2 : -1 ); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() + pxyoffset, + height: this.element.outerHeight() + pxyoffset, + position: 'absolute', + left: this.elementOffset.left - ie6offset + 'px', + top: this.elementOffset.top - ie6offset + 'px', + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; + } + + }, + + _change: { + e: function(event, dx, dy) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + } + }, + + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n != "resize" && this._trigger(n, event, this.ui())); + }, + + plugins: {}, + + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } + + })); + + $.extend($.ui.resizable, { + version: "1.7.2", + eventPrefix: "resize", + defaults: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + cancel: ":input,option", + containment: false, + delay: 0, + distance: 1, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + zIndex: 1000 + } + }); + + /* + * Resizable Extensions + */ + + $.ui.plugin.add("resizable", "alsoResize", { + + start: function(event, ui) { + + var self = $(this).data("resizable"), o = self.options; + + _store = function(exp) { + $(exp).each(function() { + $(this).data("resizable-alsoresize", { + width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10), + left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10) + }); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { + o.alsoResize = o.alsoResize[0]; + _store(o.alsoResize); + } + else { + $.each(o.alsoResize, function(exp, c) { + _store(exp); + }); + } + } else { + _store(o.alsoResize); + } + }, + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; + + var delta = { + height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, + top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 + }, + + _alsoResize = function(exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left']; + + $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) { + var sum = (start[prop] || 0) + (delta[prop] || 0); + if (sum && sum >= 0) + style[prop] = sum || null; + }); + + //Opera fixing relative position + if (/relative/.test(el.css('position')) && $.browser.opera) { + self._revertToRelativePosition = true; + el.css({ position: 'absolute', top: 'auto', left: 'auto' }); + } + + el.css(style); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function(exp, c) { + _alsoResize(exp, c); + }); + } else { + _alsoResize(o.alsoResize); + } + }, + + stop: function(event, ui) { + var self = $(this).data("resizable"); + + //Opera fixing relative position + if (self._revertToRelativePosition && $.browser.opera) { + self._revertToRelativePosition = false; + el.css({ position: 'relative' }); + } + + $(this).removeData("resizable-alsoresize-start"); + } + }); + + $.ui.plugin.add("resizable", "animate", { + + stop: function(event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + self.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(self.element.css('width'), 10), + height: parseInt(self.element.css('height'), 10), + top: parseInt(self.element.css('top'), 10), + left: parseInt(self.element.css('left'), 10) + }; + + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); + + // propagating resize, and updating values for each animation step + self._updateCache(data); + self._propagate("resize", event); + + } + } + ); + } + + }); + + $.ui.plugin.add("resizable", "containment", { + + start: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, el = self.element; + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + if (!ce) return; + + self.containerElement = $(ce); - var o = this.options; - if (!this._proportionallyResizeElements.length) return; - var element = this.helper || this.element; - - for (var i=0; i < this._proportionallyResizeElements.length; i++) { - - var prel = this._proportionallyResizeElements[i]; - - if (!this.borderDif) { - var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], - p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; - - this.borderDif = $.map(b, function(v, i) { - var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; - return border + padding; - }); - } - - if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) - continue; - - prel.css({ - height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, - width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 - }); - - }; - - }, - - _renderProxy: function() { - - var el = this.element, o = this.options; - this.elementOffset = el.offset(); - - if(this._helper) { - - this.helper = this.helper || $('
'); - - // fix ie6 offset TODO: This seems broken - var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), - pxyoffset = ( ie6 ? 2 : -1 ); - - this.helper.addClass(this._helper).css({ - width: this.element.outerWidth() + pxyoffset, - height: this.element.outerHeight() + pxyoffset, - position: 'absolute', - left: this.elementOffset.left - ie6offset +'px', - top: this.elementOffset.top - ie6offset +'px', - zIndex: ++o.zIndex //TODO: Don't modify option - }); - - this.helper - .appendTo("body") - .disableSelection(); - - } else { - this.helper = this.element; - } - - }, - - _change: { - e: function(event, dx, dy) { - return { width: this.originalSize.width + dx }; - }, - w: function(event, dx, dy) { - var o = this.options, cs = this.originalSize, sp = this.originalPosition; - return { left: sp.left + dx, width: cs.width - dx }; - }, - n: function(event, dx, dy) { - var o = this.options, cs = this.originalSize, sp = this.originalPosition; - return { top: sp.top + dy, height: cs.height - dy }; - }, - s: function(event, dx, dy) { - return { height: this.originalSize.height + dy }; - }, - se: function(event, dx, dy) { - return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); - }, - sw: function(event, dx, dy) { - return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); - }, - ne: function(event, dx, dy) { - return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); - }, - nw: function(event, dx, dy) { - return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); - } - }, - - _propagate: function(n, event) { - $.ui.plugin.call(this, n, [event, this.ui()]); - (n != "resize" && this._trigger(n, event, this.ui())); - }, - - plugins: {}, - - ui: function() { - return { - originalElement: this.originalElement, - element: this.element, - helper: this.helper, - position: this.position, - size: this.size, - originalSize: this.originalSize, - originalPosition: this.originalPosition - }; - } - -})); - -$.extend($.ui.resizable, { - version: "1.7.2", - eventPrefix: "resize", - defaults: { - alsoResize: false, - animate: false, - animateDuration: "slow", - animateEasing: "swing", - aspectRatio: false, - autoHide: false, - cancel: ":input,option", - containment: false, - delay: 0, - distance: 1, - ghost: false, - grid: false, - handles: "e,s,se", - helper: false, - maxHeight: null, - maxWidth: null, - minHeight: 10, - minWidth: 10, - zIndex: 1000 - } -}); + if (/document/.test(oc) || oc == document) { + self.containerOffset = { left: 0, top: 0 }; + self.containerPosition = { left: 0, top: 0 }; -/* - * Resizable Extensions - */ - -$.ui.plugin.add("resizable", "alsoResize", { - - start: function(event, ui) { - - var self = $(this).data("resizable"), o = self.options; - - _store = function(exp) { - $(exp).each(function() { - $(this).data("resizable-alsoresize", { - width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10), - left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10) - }); - }); - }; - - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { - if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } - else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); } - }else{ - _store(o.alsoResize); - } - }, - - resize: function(event, ui){ - var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; - - var delta = { - height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, - top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 - }, - - _alsoResize = function(exp, c) { - $(exp).each(function() { - var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left']; - - $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) { - var sum = (start[prop]||0) + (delta[prop]||0); - if (sum && sum >= 0) - style[prop] = sum || null; - }); - - //Opera fixing relative position - if (/relative/.test(el.css('position')) && $.browser.opera) { - self._revertToRelativePosition = true; - el.css({ position: 'absolute', top: 'auto', left: 'auto' }); - } - - el.css(style); - }); - }; - - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { - $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); }); - }else{ - _alsoResize(o.alsoResize); - } - }, - - stop: function(event, ui){ - var self = $(this).data("resizable"); - - //Opera fixing relative position - if (self._revertToRelativePosition && $.browser.opera) { - self._revertToRelativePosition = false; - el.css({ position: 'relative' }); - } - - $(this).removeData("resizable-alsoresize-start"); - } -}); - -$.ui.plugin.add("resizable", "animate", { - - stop: function(event, ui) { - var self = $(this).data("resizable"), o = self.options; - - var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), - soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, - soffsetw = ista ? 0 : self.sizeDiff.width; - - var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, - left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, - top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; - - self.element.animate( - $.extend(style, top && left ? { top: top, left: left } : {}), { - duration: o.animateDuration, - easing: o.animateEasing, - step: function() { - - var data = { - width: parseInt(self.element.css('width'), 10), - height: parseInt(self.element.css('height'), 10), - top: parseInt(self.element.css('top'), 10), - left: parseInt(self.element.css('left'), 10) - }; - - if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); - - // propagating resize, and updating values for each animation step - self._updateCache(data); - self._propagate("resize", event); - - } - } - ); - } - -}); - -$.ui.plugin.add("resizable", "containment", { - - start: function(event, ui) { - var self = $(this).data("resizable"), o = self.options, el = self.element; - var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; - if (!ce) return; - - self.containerElement = $(ce); - - if (/document/.test(oc) || oc == document) { - self.containerOffset = { left: 0, top: 0 }; - self.containerPosition = { left: 0, top: 0 }; - - self.parentData = { - element: $(document), left: 0, top: 0, - width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight - }; - } - - // i'm a node, so compute top, left, right, bottom - else { - var element = $(ce), p = []; - $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); - - self.containerOffset = element.offset(); - self.containerPosition = element.position(); - self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; - - var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, - width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); - - self.parentData = { - element: ce, left: co.left, top: co.top, width: width, height: height - }; - } - }, + self.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; + } - resize: function(event, ui) { - var self = $(this).data("resizable"), o = self.options, - ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, - pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; - - if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; - - if (cp.left < (self._helper ? co.left : 0)) { - self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); - if (pRatio) self.size.height = self.size.width / o.aspectRatio; - self.position.left = o.helper ? co.left : 0; - } - - if (cp.top < (self._helper ? co.top : 0)) { - self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); - if (pRatio) self.size.width = self.size.height * o.aspectRatio; - self.position.top = self._helper ? co.top : 0; - } + // i'm a node, so compute top, left, right, bottom + else { + var element = $(ce), p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { + p[i] = num(element.css("padding" + name)); + }); - self.offset.left = self.parentData.left+self.position.left; - self.offset.top = self.parentData.top+self.position.top; - - var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), - hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); - - var isParent = self.containerElement.get(0) == self.element.parent().get(0), - isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); - - if(isParent && isOffsetRelative) woset -= self.parentData.left; - - if (woset + self.size.width >= self.parentData.width) { - self.size.width = self.parentData.width - woset; - if (pRatio) self.size.height = self.size.width / self.aspectRatio; - } - - if (hoset + self.size.height >= self.parentData.height) { - self.size.height = self.parentData.height - hoset; - if (pRatio) self.size.width = self.size.height * self.aspectRatio; - } - }, - - stop: function(event, ui){ - var self = $(this).data("resizable"), o = self.options, cp = self.position, - co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; - - var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; - - if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) - $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + self.containerOffset = element.offset(); + self.containerPosition = element.position(); + self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; - if (self._helper && !o.animate && (/static/).test(ce.css('position'))) - $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); - - } -}); + var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); -$.ui.plugin.add("resizable", "ghost", { - - start: function(event, ui) { + self.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; + } + }, - var self = $(this).data("resizable"), o = self.options, cs = self.size; - - self.ghost = self.originalElement.clone(); - self.ghost - .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) - .addClass('ui-resizable-ghost') - .addClass(typeof o.ghost == 'string' ? o.ghost : ''); - - self.ghost.appendTo(self.helper); - - }, - - resize: function(event, ui){ - var self = $(this).data("resizable"), o = self.options; - if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); - }, - - stop: function(event, ui){ - var self = $(this).data("resizable"), o = self.options; - if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); - } - -}); - -$.ui.plugin.add("resizable", "grid", { - - resize: function(event, ui) { - var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; - o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; - var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); - - if (/^(se|s|e)$/.test(a)) { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - } - else if (/^(ne)$/.test(a)) { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - self.position.top = op.top - oy; - } - else if (/^(sw)$/.test(a)) { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - self.position.left = op.left - ox; - } - else { - self.size.width = os.width + ox; - self.size.height = os.height + oy; - self.position.top = op.top - oy; - self.position.left = op.left - ox; - } - } + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, + ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, + pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; + + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; + + if (cp.left < (self._helper ? co.left : 0)) { + self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); + if (pRatio) self.size.height = self.size.width / o.aspectRatio; + self.position.left = o.helper ? co.left : 0; + } + + if (cp.top < (self._helper ? co.top : 0)) { + self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); + if (pRatio) self.size.width = self.size.height * o.aspectRatio; + self.position.top = self._helper ? co.top : 0; + } + + self.offset.left = self.parentData.left + self.position.left; + self.offset.top = self.parentData.top + self.position.top; + + var woset = Math.abs((self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width), + hoset = Math.abs((self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height); + + var isParent = self.containerElement.get(0) == self.element.parent().get(0), + isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); + + if (isParent && isOffsetRelative) woset -= self.parentData.left; + + if (woset + self.size.width >= self.parentData.width) { + self.size.width = self.parentData.width - woset; + if (pRatio) self.size.height = self.size.width / self.aspectRatio; + } + + if (hoset + self.size.height >= self.parentData.height) { + self.size.height = self.parentData.height - hoset; + if (pRatio) self.size.width = self.size.height * self.aspectRatio; + } + }, + + stop: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, cp = self.position, + co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; + + var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; + + if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + if (self._helper && !o.animate && (/static/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + } + }); + + $.ui.plugin.add("resizable", "ghost", { + + start: function(event, ui) { + + var self = $(this).data("resizable"), o = self.options, cs = self.size; + + self.ghost = self.originalElement.clone(); + self.ghost + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass('ui-resizable-ghost') + .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + + self.ghost.appendTo(self.helper); + + }, + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options; + if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); + }, + + stop: function(event, ui) { + var self = $(this).data("resizable"), o = self.options; + if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); + } + + }); + + $.ui.plugin.add("resizable", "grid", { + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; + var ox = Math.round((cs.width - os.width) / (o.grid[0] || 1)) * (o.grid[0] || 1), oy = Math.round((cs.height - os.height) / (o.grid[1] || 1)) * (o.grid[1] || 1); + + if (/^(se|s|e)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + } + else if (/^(ne)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + } + else if (/^(sw)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.left = op.left - ox; + } + else { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + self.position.left = op.left - ox; + } + } -}); - -var num = function(v) { - return parseInt(v, 10) || 0; -}; + }); + + var num = function(v) { + return parseInt(v, 10) || 0; + }; -var isNumber = function(value) { - return !isNaN(parseInt(value, 10)); -}; + var isNumber = function(value) { + return !isNaN(parseInt(value, 10)); + }; })(jQuery); diff --git a/src/main/templates/org/richfaces/htmlSchedule.jspx b/src/main/templates/org/richfaces/htmlSchedule.jspx index 2d5e2fa..d2a78b3 100644 --- a/src/main/templates/org/richfaces/htmlSchedule.jspx +++ b/src/main/templates/org/richfaces/htmlSchedule.jspx @@ -16,6 +16,7 @@ org.ajax4jsf.javascript.AjaxScript, /org/ajax4jsf/javascript/scripts/form.js, /org/richfaces/renderkit/html/scripts/form.js, + /org/richfaces/renderkit/html/scripts/utils.js, /org/richfaces/renderkit/html/scripts/jquery/jquery.js, /org/richfaces/renderkit/html/scripts/ui.core.js, /org/richfaces/renderkit/html/scripts/ui.draggable.js, @@ -31,6 +32,6 @@ x:passThruWithExclusions="value,name,type,id"> \ No newline at end of file -- libgit2 0.24.0