Commit a1b82974acf891d105d5297348c22dcef449db45

Authored by bernard
1 parent f7c78b68

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.
... ... @@ -36,7 +36,7 @@
36 36 -->
37 37 &ui_component_attributes;
38 38 &commonViewAttributes;
39   - <!--&ui_data_attributes;-->
  39 + &ajax_component_attributes;
40 40 <!--TODO how about reRender ajaxSingle and others?-->
41 41 <!--TODO add style attribute-->
42 42 <property>
... ... @@ -53,6 +53,15 @@
53 53 <defaultvalue>"ajax"</defaultvalue>
54 54 </property>
55 55 <property>
  56 + <name>widgetVar</name>
  57 + <classname>java.lang.String</classname>
  58 + <description>
  59 + Variable name of JavaScript component.
  60 + default: null
  61 + </description>
  62 + <defaultvalue>null</defaultvalue>
  63 + </property>
  64 + <property>
56 65 <name>view</name>
57 66 <classname>java.lang.String</classname>
58 67 <description>
... ... @@ -456,7 +465,30 @@
456 465 <name>onItemSelected</name>
457 466 <classname>java.lang.String</classname>
458 467 <description>
459   - <!--TODO add description here-->
  468 + JavaScript code for handling event.
  469 + Following data will be available in context:
  470 + <ul>
  471 + <li>item - selected item</li>
  472 + <li>event - javascript event</li>
  473 + <li>view - object representing current view</li>
  474 + </ul>
  475 + </description>
  476 + <defaultvalue>null</defaultvalue>
  477 + </property>
  478 + <property>
  479 + <name>onItemSelectedComplete</name>
  480 + <classname>java.lang.String</classname>
  481 + <description>
  482 + JavaScript code called when ajax request triggered when item
  483 + is selected has finished.
  484 + Following data will be available in context:
  485 + <ul>
  486 + <li>item - selected item</li>
  487 + <li>event - javascript event</li>
  488 + <li>view - object representing current view</li>
  489 + <li>request - ajax request</li>
  490 + <li>data - data returned by ajax request</li>
  491 + </ul>
460 492 </description>
461 493 <defaultvalue>null</defaultvalue>
462 494 </property>
... ... @@ -464,7 +496,14 @@
464 496 <name>onItemDragStart</name>
465 497 <classname>java.lang.String</classname>
466 498 <description>
467   - <!--TODO add description here-->
  499 + JavaScript code for handling event.
  500 + Following data will be available in context:
  501 + <ul>
  502 + <li>item - selected item</li>
  503 + <li>event - javascript event</li>
  504 + <li>ui - jQuery UI object</li>
  505 + <li>view - object representing current view</li>
  506 + </ul>
468 507 </description>
469 508 <defaultvalue>null</defaultvalue>
470 509 </property>
... ... @@ -472,7 +511,14 @@
472 511 <name>onItemDragStop</name>
473 512 <classname>java.lang.String</classname>
474 513 <description>
475   - <!--TODO add description here-->
  514 + JavaScript code for handling event.
  515 + Following data will be available in context:
  516 + <ul>
  517 + <li>item - selected item</li>
  518 + <li>event - javascript event</li>
  519 + <li>ui - jQuery UI object</li>
  520 + <li>view - object representing current view</li>
  521 + </ul>
476 522 </description>
477 523 <defaultvalue>null</defaultvalue>
478 524 </property>
... ... @@ -480,7 +526,14 @@
480 526 <name>onItemResizeStart</name>
481 527 <classname>java.lang.String</classname>
482 528 <description>
483   - <!--TODO add description here-->
  529 + JavaScript code for handling event.
  530 + Following data will be available in context:
  531 + <ul>
  532 + <li>item - selected item</li>
  533 + <li>event - javascript event</li>
  534 + <li>ui - jQuery UI object</li>
  535 + <li>view - object representing current view</li>
  536 + </ul>
484 537 </description>
485 538 <defaultvalue>null</defaultvalue>
486 539 </property>
... ... @@ -488,7 +541,14 @@
488 541 <name>onItemResizeStop</name>
489 542 <classname>java.lang.String</classname>
490 543 <description>
491   - <!--TODO add description here-->
  544 + JavaScript code for handling event.
  545 + Following data will be available in context:
  546 + <ul>
  547 + <li>item - selected item</li>
  548 + <li>event - javascript event</li>
  549 + <li>ui - jQuery UI object</li>
  550 + <li>view - object representing current view</li>
  551 + </ul>
492 552 </description>
493 553 <defaultvalue>null</defaultvalue>
494 554 </property>
... ... @@ -496,7 +556,53 @@
496 556 <name>onItemDrop</name>
497 557 <classname>java.lang.String</classname>
498 558 <description>
499   - <!--TODO add description here-->
  559 + JavaScript code for handling event.
  560 + Following data will be available in context:
  561 + <ul>
  562 + <li>item - selected item</li>
  563 + <li>dayDelta - holds the number of days the event was moved forward (a positive number) or backwards
  564 + (a negative number)
  565 + </li>
  566 + <li>minuteDelta - holds the number of minutes the event was moved forward (a positive number) or
  567 + backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed in.
  568 + </li>
  569 + <li>allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in
  570 + the agenda views. It will be false if dropped on a slot in the agenda views (meaning it has been
  571 + assigned a time).
  572 + </li>
  573 + <li>event - javascript event</li>
  574 + <li>ui - jQuery UI object</li>
  575 + <li>view - object representing current view</li>
  576 + </ul>
  577 + </description>
  578 + <defaultvalue>null</defaultvalue>
  579 + </property>
  580 + <property>
  581 + <name>onItemDropComplete</name>
  582 + <classname>java.lang.String</classname>
  583 + <description>
  584 + JavaScript code called when ajax request triggered when item
  585 + is dropped has finished.
  586 + Following data will be available in context:
  587 + <ul>
  588 + <li>item - selected item</li>
  589 + <li>dayDelta - holds the number of days the event was moved forward (a positive number) or backwards
  590 + (a negative number)
  591 + </li>
  592 + <li>minuteDelta - holds the number of minutes the event was moved forward (a positive number) or
  593 + backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed in.
  594 + </li>
  595 + <li>allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in
  596 + the agenda views. It will be false if dropped on a slot in the agenda views (meaning it has been
  597 + assigned a time).
  598 + </li>
  599 + <li>vetoed - is true if server side listener has raised veto and modification has been reverted</li>
  600 + <li>event - javascript event</li>
  601 + <li>ui - jQuery UI object</li>
  602 + <li>view - object representing current view</li>
  603 + <li>request - ajax request</li>
  604 + <li>data - data returned by ajax request</li>
  605 + </ul>
500 606 </description>
501 607 <defaultvalue>null</defaultvalue>
502 608 </property>
... ... @@ -504,7 +610,47 @@
504 610 <name>onItemResized</name>
505 611 <classname>java.lang.String</classname>
506 612 <description>
507   - <!--TODO add description here-->
  613 + JavaScript code for handling event.
  614 + Following data will be available in context:
  615 + <ul>
  616 + <li>item - selected item</li>
  617 + <li>dayDelta - holds the number of days the event was moved forward (a positive number) or backwards
  618 + (a negative number)holds the number of minutes the event was moved forward (a positive number)
  619 + or backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed
  620 + in.
  621 + </li>
  622 + <li>minuteDelta - holds the number of minutes the event was moved forward (a positive number) or
  623 + backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed in.
  624 + </li>
  625 + <li>event - javascript event</li>
  626 + <li>ui - jQuery UI object</li>
  627 + <li>view - object representing current view</li>
  628 + </ul>
  629 + </description>
  630 + <defaultvalue>null</defaultvalue>
  631 + </property>
  632 + <property>
  633 + <name>onItemResizedComplete</name>
  634 + <classname>java.lang.String</classname>
  635 + <description>
  636 + JavaScript code called when ajax request triggered when item
  637 + is resized has finished.
  638 + Following data will be available in context:
  639 + <ul>
  640 + <li>item - selected item</li>
  641 + <li>dayDelta - holds the number of days the event was moved forward (a positive number) or backwards
  642 + (a negative number)
  643 + </li>
  644 + <li>minuteDelta - holds the number of minutes the event was moved forward (a positive number) or
  645 + backwards (a negative number). Only useful for the agenda views. In other views, 0 is passed in.
  646 + </li>
  647 + <li>vetoed - is true if server side listener has raised veto and modification has been reverted</li>
  648 + <li>event - javascript event</li>
  649 + <li>ui - jQuery UI object</li>
  650 + <li>view - object representing current view</li>
  651 + <li>request - ajax request</li>
  652 + <li>data - data returned by ajax request</li>
  653 + </ul>
508 654 </description>
509 655 <defaultvalue>null</defaultvalue>
510 656 </property>
... ... @@ -512,7 +658,13 @@
512 658 <name>onItemMouseover</name>
513 659 <classname>java.lang.String</classname>
514 660 <description>
515   - <!--TODO add description here-->
  661 + JavaScript code for handling event.
  662 + Following data will be available in context:
  663 + <ul>
  664 + <li>item - selected item</li>
  665 + <li>event - javascript event</li>
  666 + <li>view - object representing current view</li>
  667 + </ul>
516 668 </description>
517 669 <defaultvalue>null</defaultvalue>
518 670 </property>
... ... @@ -520,15 +672,42 @@
520 672 <name>onItemMouseout</name>
521 673 <classname>java.lang.String</classname>
522 674 <description>
523   - <!--TODO add description here-->
  675 + JavaScript code for handling event.
  676 + Following data will be available in context:
  677 + <ul>
  678 + <li>item - selected item</li>
  679 + <li>event - javascript event</li>
  680 + <li>view - object representing current view</li>
  681 + </ul>
  682 + </description>
  683 + <defaultvalue>null</defaultvalue>
  684 + </property>
  685 + <property>
  686 + <name>onViewChanged</name>
  687 + <classname>java.lang.String</classname>
  688 + <description>
  689 + JavaScript code for handling event.
  690 + <b>Any return instruction will be ignored</b>
  691 + so this code cannot block anything.
  692 + Following data will be available in context:
  693 + <ul>
  694 + <li>view - object representing current view</li>
  695 + </ul>
524 696 </description>
525 697 <defaultvalue>null</defaultvalue>
526 698 </property>
527 699 <property>
528   - <name>onViewDisplay</name>
  700 + <name>onViewChangedComplete</name>
529 701 <classname>java.lang.String</classname>
530 702 <description>
531   - <!--TODO add description here-->
  703 + JavaScript code called when ajax request triggered when view
  704 + changes has finished.
  705 + Following data will be available in context:
  706 + <ul>
  707 + <li>view - object representing current view</li>
  708 + <li>request - ajax request</li>
  709 + <li>data - data returned by ajax request</li>
  710 + </ul>
532 711 </description>
533 712 <defaultvalue>null</defaultvalue>
534 713 </property>
... ... @@ -536,7 +715,36 @@
536 715 <name>onDateSelected</name>
537 716 <classname>java.lang.String</classname>
538 717 <description>
539   - <!--TODO add description here-->
  718 + JavaScript code for handling event.
  719 + Following data will be available in context:
  720 + <ul>
  721 + <li>date - selected date</li>
  722 + <li>allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in
  723 + the agenda views.
  724 + </li>
  725 + <li>event - javascript event</li>
  726 + <li>view - object representing current view</li>
  727 + </ul>
  728 + </description>
  729 + <defaultvalue>null</defaultvalue>
  730 + </property>
  731 + <property>
  732 + <name>onDateSelectedComplete</name>
  733 + <classname>java.lang.String</classname>
  734 + <description>
  735 + JavaScript code called when ajax request triggered when date
  736 + is selected has finished.
  737 + Following data will be available in context:
  738 + <ul>
  739 + <li>date - selected date</li>
  740 + <li>allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in
  741 + the agenda views.
  742 + </li>
  743 + <li>event - javascript event</li>
  744 + <li>view - object representing current view</li>
  745 + <li>request - ajax request</li>
  746 + <li>data - data returned by ajax request</li>
  747 + </ul>
540 748 </description>
541 749 <defaultvalue>null</defaultvalue>
542 750 </property>
... ... @@ -544,7 +752,67 @@
544 752 <name>onDateRangeSelected</name>
545 753 <classname>java.lang.String</classname>
546 754 <description>
547   - <!--TODO add description here-->
  755 + JavaScript code for handling event.
  756 + Following data will be available in context:
  757 + <ul>
  758 + <li>startDate - selection start date</li>
  759 + <li>endDate - selection end date</li>
  760 + <li>allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in
  761 + the agenda views.
  762 + </li>
  763 + <li>view - object representing current view</li>
  764 + </ul>
  765 + </description>
  766 + <defaultvalue>null</defaultvalue>
  767 + </property>
  768 + <property>
  769 + <name>onDateRangeSelectedComplete</name>
  770 + <classname>java.lang.String</classname>
  771 + <description>
  772 + JavaScript code called when ajax request triggered when date
  773 + range is selected has finished.
  774 + Following data will be available in context:
  775 + <ul>
  776 + <li>startDate - selection start date</li>
  777 + <li>endDate - selection end date</li>
  778 + <li>allDay - is true if the event has been dropped on a day in month view, or the "all-day" slot in
  779 + the agenda views.
  780 + </li>
  781 + <li>view - object representing current view</li>
  782 + <li>request - ajax request</li>
  783 + <li>data - data returned by ajax request</li>
  784 + </ul>
  785 + </description>
  786 + <defaultvalue>null</defaultvalue>
  787 + </property>
  788 + <property>
  789 + <name>onDateRangeChanged</name>
  790 + <classname>java.lang.String</classname>
  791 + <description>
  792 + JavaScript code for handling event.
  793 + <b>Any return instruction will be ignored</b>
  794 + so this code cannot block anything.
  795 + Following data will be available in context:
  796 + <ul>
  797 + <li>startDate - start date</li>
  798 + <li>endDate - end date</li>
  799 + </ul>
  800 + </description>
  801 + <defaultvalue>null</defaultvalue>
  802 + </property>
  803 + <property>
  804 + <name>onDateRangeChangedComplete</name>
  805 + <classname>java.lang.String</classname>
  806 + <description>
  807 + JavaScript code called when ajax request triggered when displayed
  808 + date range is changed has finished.
  809 + Following data will be available in context:
  810 + <ul>
  811 + <li>startDate - selection start date</li>
  812 + <li>endDate - selection end date</li>
  813 + <li>request - ajax request</li>
  814 + <li>data - data returned by ajax request</li>
  815 + </ul>
548 816 </description>
549 817 <defaultvalue>null</defaultvalue>
550 818 </property>
... ... @@ -555,7 +823,6 @@
555 823 </description>
556 824 <defaultvalue>null</defaultvalue>
557 825 </property>
558   - <!--TODO what about buttonText and other language dependant stuff? there is so many attributes there-->
559 826
560 827 <property elonly="true" attachedstate="true">
561 828 <name>itemMoveListener</name>
... ... @@ -594,6 +861,10 @@
594 861 <classname>javax.faces.el.MethodBinding</classname>
595 862 </property>
596 863
  864 + <property exist="false" existintag="false" hidden="true">
  865 + <name>oncomplete</name>
  866 + </property>
  867 +
597 868
598 869 </component>
599 870 &listeners;
... ...
1 1 package org.richfaces.component;
2 2
  3 +/**
  4 + * Interface with common attributes of all view components.
  5 + * Saves some lines in UISchedule...View classes.
  6 + *
  7 + * @author Bernard Labno
  8 + */
3 9 public interface ScheduleCommonViewAttributes {
4 10
5 11 public String getTimeFormat();
... ...
1 1 package org.richfaces.component;
2 2
  3 +import org.ajax4jsf.component.AjaxActionComponent;
  4 +import org.ajax4jsf.component.AjaxComponent;
3 5 import org.ajax4jsf.context.AjaxContext;
  6 +import org.ajax4jsf.event.AjaxEvent;
4 7 import org.ajax4jsf.model.DataVisitor;
5 8 import org.ajax4jsf.model.ExtendedDataModel;
  9 +import org.ajax4jsf.renderkit.RendererUtils;
6 10 import org.richfaces.component.event.*;
7 11 import org.richfaces.component.model.DateRange;
8 12
... ... @@ -22,16 +26,24 @@ import java.text.DateFormat;
22 26 import java.text.SimpleDateFormat;
23 27 import java.util.*;
24 28
25   -public abstract class UISchedule extends UIComponentBase implements ScheduleCommonViewAttributes, ScheduleListenerEventsProducer {
  29 +public abstract class UISchedule extends UIComponentBase implements ScheduleCommonViewAttributes, ScheduleListenerEventsProducer, AjaxComponent {
26 30
27 31 public static final String COMPONENT_TYPE = "org.richfaces.Schedule";
28 32 public static final String COMPONENT_FAMILY = "org.richfaces.Schedule";
  33 + /**
  34 + * Values of view attribute.
  35 + */
29 36 public static final String VIEW_MONTH = "month";
30 37 public static final String VIEW_BASIC_WEEK = "basicWeek";
31 38 public static final String VIEW_AGENDA_WEEK = "agendaWeek";
32 39 public static final String VIEW_BASIC_DAY = "basicDay";
33 40 public static final String VIEW_AGENDA_DAY = "agendaDay";
  41 + /**
  42 + * Values of weekMode attribute.
  43 + */
34 44 public static final String WEEK_MODE_FIXED = "fixed";
  45 + public static final String WEEK_MODE_LIQUID = "liquid";
  46 + public static final String WEEK_MODE_VARIABLE = "variable";
35 47 private DataModel model;
36 48
37 49 public abstract Object getValue();
... ... @@ -174,6 +186,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
174 186
175 187 public abstract void setOnItemSelected(String onItemSelect);
176 188
  189 + public abstract String getOnItemSelectedComplete();
  190 +
  191 + public abstract void setOnItemSelectedComplete(String onItemSelectedComplete);
  192 +
177 193 public abstract String getOnItemDragStart();
178 194
179 195 public abstract void setOnItemDragStart(String onItemDragStart);
... ... @@ -186,6 +202,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
186 202
187 203 public abstract void setOnItemDrop(String onItemDrop);
188 204
  205 + public abstract String getOnItemDropComplete();
  206 +
  207 + public abstract void setOnItemDropComplete(String onItemDropComplete);
  208 +
189 209 public abstract String getOnItemResizeStart();
190 210
191 211 public abstract void setOnItemResizeStart(String onItemResizeStart);
... ... @@ -198,6 +218,10 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
198 218
199 219 public abstract void setOnItemResized(String onItemMouseover);
200 220
  221 + public abstract String getOnItemResizedComplete();
  222 +
  223 + public abstract void setOnItemResizedComplete(String setOnItemResizedComplete);
  224 +
201 225 public abstract String getOnItemMouseover();
202 226
203 227 public abstract void setOnItemMouseover(String onItemMouseover);
... ... @@ -206,18 +230,38 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
206 230
207 231 public abstract void setOnItemMouseout(String onItemMouseout);
208 232
209   - public abstract String getOnViewDisplay();
  233 + public abstract String getOnViewChanged();
  234 +
  235 + public abstract void setOnViewChanged(String onViewChanged);
  236 +
  237 + public abstract String getOnViewChangedComplete();
210 238
211   - public abstract void setOnViewDisplay(String onViewDisplay);
  239 + public abstract void setOnViewChangedComplete(String onViewDisplayComplete);
212 240
213 241 public abstract String getOnDateSelected();
214 242
215 243 public abstract void setOnDateSelected(String onDaySelected);
216 244
  245 + public abstract String getOnDateSelectedComplete();
  246 +
  247 + public abstract void setOnDateSelectedComplete(String setOnDateSelectedComplete);
  248 +
217 249 public abstract String getOnDateRangeSelected();
218 250
219 251 public abstract void setOnDateRangeSelected(String onDateRangeSelected);
220 252
  253 + public abstract String getOnDateRangeSelectedComplete();
  254 +
  255 + public abstract void setOnDateRangeSelectedComplete(String onDateRangeSelectedComplete);
  256 +
  257 + public abstract String getOnDateRangeChanged();
  258 +
  259 + public abstract void setOnDateRangeChanged(String onDateRangeChanged);
  260 +
  261 + public abstract String getOnDateRangeChangedComplete();
  262 +
  263 + public abstract void setOnDateRangeChangedComplete(String onDateRangeChangedComplete);
  264 +
221 265 // TODO do we use MethodBinding or MethodExpression?
222 266
223 267 public abstract MethodBinding getItemMoveListener();
... ... @@ -248,10 +292,35 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
248 292
249 293 public abstract void setDateSelectedListener(MethodBinding listener);
250 294
  295 + public abstract String getWidgetVar();
  296 +
  297 + public abstract void setWidgetVar(String widgetVar);
  298 +
  299 + /**
  300 + * React on various events.
  301 + * Vetoable events are first broadcasted to listeners bound via EL to
  302 + * component attribtues and then if no veto is raised then to the rest of
  303 + * listeners.
  304 + * In case of non vetoable events the order of broadcast is reverse.
  305 + * Vetoable events are: ScheduleItemMoveEvent, ScheduleItemResizeEvent
  306 + * Non-vetoable events: ScheduleDateRangeChangedEvent, ScheduleItemSelectedEvent,
  307 + * ScheduleViewChangedEvent, ScheduleDateSelectedEvent,
  308 + * ScheduleDateRangeSelectedEvent
  309 + * In case of ScheduleDateRangeChangedEvent new items are returned
  310 + * via response data map of ajaxContext.
  311 + * In case of ScheduleItemMoveEvent and ScheduleItemResizeEvent, the
  312 + * decision if veto was raised is sent back to client via response data map
  313 + * of ajaxContext as boolean.
  314 + *
  315 + * @param event broadcasted event
  316 + * @throws AbortProcessingException if broadcasting of particular event
  317 + * should stop
  318 + */
251 319 @Override
252 320 public void broadcast(FacesEvent event) throws AbortProcessingException {
253 321 if (event instanceof ScheduleDateRangeChangedEvent) {
254 322 super.broadcast(event);
  323 + new AjaxEvent(this).queue();
255 324 ScheduleDateRangeChangedEvent calendarAjaxEvent = (ScheduleDateRangeChangedEvent) event;
256 325 FacesContext facesContext = getFacesContext();
257 326 AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext);
... ... @@ -273,8 +342,9 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
273 342 Object result = expression.invoke(facesContext, new Object[]{event});
274 343 allow = ((Boolean) result);
275 344 }
276   - ajaxContext.setResponseData(allow);
  345 + ajaxContext.getResponseDataMap().put("_ajax:scheduleData", allow);
277 346 super.broadcast(event);
  347 + new AjaxEvent(this).queue();
278 348 } else if (event instanceof ScheduleItemResizeEvent) {
279 349 FacesContext facesContext = getFacesContext();
280 350 AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext);
... ... @@ -284,10 +354,12 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
284 354 Object result = expression.invoke(facesContext, new Object[]{event});
285 355 allow = ((Boolean) result);
286 356 }
287   - ajaxContext.setResponseData(allow);
  357 + ajaxContext.getResponseDataMap().put("_ajax:scheduleData", allow);
288 358 super.broadcast(event);
  359 + new AjaxEvent(this).queue();
289 360 } else if (event instanceof ScheduleItemSelectedEvent) {
290 361 super.broadcast(event);
  362 + new AjaxEvent(this).queue();
291 363 FacesContext facesContext = getFacesContext();
292 364 MethodBinding expression = getItemSelectedListener();
293 365 if (expression != null) {
... ... @@ -295,6 +367,7 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
295 367 }
296 368 } else if (event instanceof ScheduleViewChangedEvent) {
297 369 super.broadcast(event);
  370 + new AjaxEvent(this).queue();
298 371 FacesContext facesContext = getFacesContext();
299 372 MethodBinding expression = getViewChangedListener();
300 373 if (expression != null) {
... ... @@ -302,6 +375,7 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
302 375 }
303 376 } else if (event instanceof ScheduleDateSelectedEvent) {
304 377 super.broadcast(event);
  378 + new AjaxEvent(this).queue();
305 379 FacesContext facesContext = getFacesContext();
306 380 MethodBinding expression = getDateSelectedListener();
307 381 if (expression != null) {
... ... @@ -309,11 +383,38 @@ public abstract class UISchedule extends UIComponentBase implements ScheduleComm
309 383 }
310 384 } else if (event instanceof ScheduleDateRangeSelectedEvent) {
311 385 super.broadcast(event);
  386 + new AjaxEvent(this).queue();
312 387 FacesContext facesContext = getFacesContext();
313 388 MethodBinding expression = getDateRangeSelectedListener();
314 389 if (expression != null) {
315 390 expression.invoke(facesContext, new Object[]{event});
316 391 }
  392 + } else if (event instanceof AjaxEvent) {
  393 + FacesContext context = getFacesContext();
  394 + // complete re-Render fields. AjaxEvent deliver before render
  395 + // response.
  396 + AjaxContext.getCurrentInstance(context).addRegionsFromComponent(this);
  397 + // Put data for send in response
  398 + Object data = getData();
  399 + AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
  400 + if (null != data) {
  401 + ajaxContext.setResponseData(data);
  402 + }
  403 + String focus = getFocus();
  404 + if (null != focus) {
  405 + // search for component in tree.
  406 + // XXX - use more pourful search, as in h:outputLabel
  407 + // component.
  408 + UIComponent focusComponent = RendererUtils.getInstance().
  409 + findComponentFor(this, focus);
  410 + if (null != focusComponent) {
  411 + focus = focusComponent.getClientId(context);
  412 + }
  413 + ajaxContext.getResponseDataMap().put(AjaxActionComponent.FOCUS_DATA_ID, focus);
  414 + }
  415 + ajaxContext.setOncomplete(getOncomplete());
  416 + } else {
  417 + super.broadcast(event);
317 418 }
318 419 }
319 420
... ...
... ... @@ -2,7 +2,7 @@ package org.richfaces.component;
2 2
3 3 import javax.faces.component.UIComponentBase;
4 4
5   -public abstract class UIScheduleBasicDayView extends UIComponentBase implements ScheduleCommonViewAttributes{
  5 +public abstract class UIScheduleBasicDayView extends UIComponentBase implements ScheduleCommonViewAttributes {
6 6
7 7 public static final String COMPONENT_TYPE = "org.richfaces.ScheduleBasicDayView";
8 8 public static final String COMPONENT_FAMILY = "org.richfaces.Schedule";
... ...
1 1 package org.richfaces.component.event;
2 2
3   -import java.util.Date;
4   -
5 3 import javax.faces.component.UIComponent;
6   -
7 4 import javax.faces.event.FacesEvent;
8 5 import javax.faces.event.FacesListener;
  6 +import java.util.Date;
9 7
10 8 public class ScheduleDateRangeChangedEvent extends FacesEvent {
11 9
... ...
1 1 package org.richfaces.component.event;
2 2
3   -import java.util.Date;
4 3 import javax.faces.component.UIComponent;
5 4 import javax.faces.event.FacesEvent;
6 5 import javax.faces.event.FacesListener;
  6 +import java.util.Date;
7 7
8 8 public class ScheduleDateSelectedEvent extends FacesEvent {
9 9
... ...
... ... @@ -2,7 +2,7 @@ package org.richfaces.component.event;
2 2
3 3 import javax.faces.event.FacesListener;
4 4
5   -public interface ScheduleItemMoveListener extends FacesListener{
  5 +public interface ScheduleItemMoveListener extends FacesListener {
6 6
7 7 void itemMove(ScheduleItemMoveEvent event);
8 8 }
... ...
... ... @@ -2,7 +2,7 @@ package org.richfaces.component.event;
2 2
3 3 import javax.faces.event.FacesListener;
4 4
5   -public interface ScheduleItemResizeListener extends FacesListener{
  5 +public interface ScheduleItemResizeListener extends FacesListener {
6 6
7 7 void itemResize(ScheduleItemResizeEvent event);
8 8 }
... ...
... ... @@ -2,7 +2,7 @@ package org.richfaces.component.event;
2 2
3 3 import javax.faces.event.FacesListener;
4 4
5   -public interface ScheduleViewChangedListener extends FacesListener{
  5 +public interface ScheduleViewChangedListener extends FacesListener {
6 6
7 7 void viewChanged(ScheduleViewChangedEvent event);
8 8 }
... ...
1 1 package org.richfaces.component.model;
2 2
3   -import java.util.Date;
4 3 import org.ajax4jsf.model.Range;
5 4
  5 +import java.util.Date;
  6 +
6 7 public class DateRange implements Range {
7 8
8 9 private Date startDate;
... ...
... ... @@ -121,6 +121,10 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
121 121 ResponseWriter writer = context.getResponseWriter();
122 122 String clientId = component.getClientId(context);
123 123 Locale locale = context.getViewRoot().getLocale();
  124 + String widgetVar = component.getWidgetVar();
  125 + if (widgetVar != null) {
  126 + writer.writeText("var " + widgetVar + " = ", null);
  127 + }
124 128 writer.writeText(new JSObject("RichFaces.Schedule", clientId, locale.toString(),
125 129 getOptions(component),
126 130 DATE_RANGE_CHANGED_EVENT,
... ... @@ -205,18 +209,27 @@ public abstract class ScheduleRendererBase extends AjaxComponentRendererBase {
205 209 options.put("header", headerOptions);
206 210 }
207 211 addOptionIfSet("allDayDefault", schedule.getAllDayByDefault(), options);
  212 +
208 213 addOptionIfSet("onItemSelected", schedule.getOnItemSelected(), options);
  214 + addOptionIfSet("onItemSelectedComplete", schedule.getOnItemSelectedComplete(), options);
209 215 addOptionIfSet("onItemDrop", schedule.getOnItemDrop(), options);
  216 + addOptionIfSet("onItemDropComplete", schedule.getOnItemDropComplete(), options);
210 217 addOptionIfSet("onItemResized", schedule.getOnItemResized(), options);
  218 + addOptionIfSet("onItemResizedComplete", schedule.getOnItemResizedComplete(), options);
211 219 addOptionIfSet("onItemResizeStart", schedule.getOnItemResizeStart(), options);
212 220 addOptionIfSet("onItemResizeStop", schedule.getOnItemResizeStop(), options);
213 221 addOptionIfSet("onItemDragStart", schedule.getOnItemDragStart(), options);
214 222 addOptionIfSet("onItemDragStop", schedule.getOnItemDragStop(), options);
215 223 addOptionIfSet("onItemMouseover", schedule.getOnItemMouseover(), options);
216 224 addOptionIfSet("onItemMouseout", schedule.getOnItemMouseout(), options);
217   - addOptionIfSet("onViewDisplay", schedule.getOnViewDisplay(), options);
  225 + addOptionIfSet("onViewChanged", schedule.getOnViewChanged(), options);
  226 + addOptionIfSet("onViewChangedComplete", schedule.getOnViewChangedComplete(), options);
218 227 addOptionIfSet("onDateSelected", schedule.getOnDateSelected(), options);
  228 + addOptionIfSet("onDateSelectedComplete", schedule.getOnDateSelectedComplete(), options);
219 229 addOptionIfSet("onDateRangeSelected", schedule.getOnDateRangeSelected(), options);
  230 + addOptionIfSet("onDateRangeSelectedComplete", schedule.getOnDateRangeSelectedComplete(), options);
  231 + addOptionIfSet("onDateRangeChanged", schedule.getOnDateRangeChanged(), options);
  232 + addOptionIfSet("onDateRangeChangedComplete", schedule.getOnDateRangeChangedComplete(), options);
220 233 if (schedule.getDate() != null) {
221 234 Calendar calendar = Calendar.getInstance();
222 235 calendar.setTime(schedule.getDate());
... ...
1 1 package org.richfaces.taglib;
2 2
3 3 import com.sun.facelets.FaceletContext;
4   -import com.sun.facelets.tag.MetaRule;
5   -import com.sun.facelets.tag.MetaRuleset;
6   -import com.sun.facelets.tag.Metadata;
7   -import com.sun.facelets.tag.MetadataTarget;
8   -import com.sun.facelets.tag.TagAttribute;
  4 +import com.sun.facelets.tag.*;
9 5 import com.sun.facelets.tag.jsf.ComponentConfig;
10 6 import com.sun.facelets.tag.jsf.ComponentHandler;
11   -import javax.faces.component.UIComponent;
12   -import javax.faces.el.MethodBinding;
13 7 import org.richfaces.event.NodeExpandedEvent;
14 8 import org.richfaces.event.NodeSelectedEvent;
15 9
  10 +import javax.faces.component.UIComponent;
  11 +import javax.faces.el.MethodBinding;
  12 +
16 13 public class ScheduleTagHandlerBase extends ComponentHandler {
17 14
18 15 private final static String DATE_RANGE_CHANGED_LISTENER = "dateRangeChangedListener";
... ...
... ... @@ -37,10 +37,10 @@ org.richfaces.component.UISchedule.dayNamesShort.WEDNESDAY=Wed
37 37 org.richfaces.component.UISchedule.dayNamesShort.THURSDAY=Thu
38 38 org.richfaces.component.UISchedule.dayNamesShort.FRIDAY=Fri
39 39 org.richfaces.component.UISchedule.dayNamesShort.SATURDAY=Sat
40   -org.richfaces.component.UISchedule.buttonTexts.prev=&nbsp;&#9668;&nbsp;
41   -org.richfaces.component.UISchedule.buttonTexts.next=&nbsp;&#9658;&nbsp;
42   -org.richfaces.component.UISchedule.buttonTexts.prevYear=&nbsp;&lt;&lt;&nbsp;
43   -org.richfaces.component.UISchedule.buttonTexts.nextYear=&nbsp;&gt;&gt;&nbsp;
  40 +org.richfaces.component.UISchedule.buttonTexts.prev=&#160;&#9668;&#160;
  41 +org.richfaces.component.UISchedule.buttonTexts.next=&#160;&#9658;&#160;
  42 +org.richfaces.component.UISchedule.buttonTexts.prevYear=&#160;&#60;&#60;&#160;
  43 +org.richfaces.component.UISchedule.buttonTexts.nextYear=&#160;&#62;&#62;&#160;
44 44 org.richfaces.component.UISchedule.buttonTexts.today=today
45 45 org.richfaces.component.UISchedule.buttonTexts.month=month
46 46 org.richfaces.component.UISchedule.buttonTexts.week=week
... ...
... ... @@ -37,10 +37,10 @@ org.richfaces.component.UISchedule.dayNamesShort.WEDNESDAY=\u015Aro
37 37 org.richfaces.component.UISchedule.dayNamesShort.THURSDAY=Czw
38 38 org.richfaces.component.UISchedule.dayNamesShort.FRIDAY=Pi\u0105
39 39 org.richfaces.component.UISchedule.dayNamesShort.SATURDAY=Sob
40   -org.richfaces.component.UISchedule.buttonTexts.prev=&nbsp;&#9668;&nbsp;
41   -org.richfaces.component.UISchedule.buttonTexts.next=&nbsp;&#9658;&nbsp;
42   -org.richfaces.component.UISchedule.buttonTexts.prevYear=&nbsp;&lt;&lt;&nbsp;
43   -org.richfaces.component.UISchedule.buttonTexts.nextYear=&nbsp;&gt;&gt;&nbsp;
  40 +org.richfaces.component.UISchedule.buttonTexts.prev=&#160;&#9668;&#160;
  41 +org.richfaces.component.UISchedule.buttonTexts.next=&#160;&#9658;&#160;
  42 +org.richfaces.component.UISchedule.buttonTexts.prevYear=&#160;&#60;&#60;&#160;
  43 +org.richfaces.component.UISchedule.buttonTexts.nextYear=&#160;&#62;&#62;&#160;
44 44 org.richfaces.component.UISchedule.buttonTexts.today=Dzi\u015B
45 45 org.richfaces.component.UISchedule.buttonTexts.month=Miesi\u0105c
46 46 org.richfaces.component.UISchedule.buttonTexts.week=Tydzie\u0144
... ...
... ... @@ -10,566 +10,555 @@
10 10 * TODO adjust class names to richfaces naming conventions
11 11 */
12 12
13   -
14 13 .fc,
15 14 .fc .fc-header,
16 15 .fc .fc-content {
17   - font-size: 1em;
18   - }
19   -
  16 + font-size: 1em;
  17 +}
  18 +
20 19 .fc {
21   - direction: ltr;
22   - text-align: left;
23   - }
24   -
25   -.fc table {
26   - border-collapse: collapse;
27   - border-spacing: 0;
28   - }
29   -
30   -.fc td, .fc th {
31   - padding: 0;
32   - vertical-align: top;
33   - }
  20 + direction: ltr;
  21 + text-align: left;
  22 +}
34 23
  24 +.fc table {
  25 + border-collapse: collapse;
  26 + border-spacing: 0;
  27 +}
35 28
  29 +.fc td, .fc th {
  30 + padding: 0;
  31 + vertical-align: top;
  32 +}
36 33
37 34 /* Header
38 35 ------------------------------------------------------------------------*/
39   -
  36 +
40 37 table.fc-header {
41   - width: 100%;
42   - }
43   -
  38 + width: 100%;
  39 +}
  40 +
44 41 .fc-header-left {
45   - width: 25%;
46   - }
47   -
  42 + width: 25%;
  43 +}
  44 +
48 45 .fc-header-left table {
49   - float: left;
50   - }
51   -
  46 + float: left;
  47 +}
  48 +
52 49 .fc-header-center {
53   - width: 50%;
54   - text-align: center;
55   - }
56   -
  50 + width: 50%;
  51 + text-align: center;
  52 +}
  53 +
57 54 .fc-header-center table {
58   - margin: 0 auto;
59   - }
60   -
  55 + margin: 0 auto;
  56 +}
  57 +
61 58 .fc-header-right {
62   - width: 25%;
63   - }
64   -
  59 + width: 25%;
  60 +}
  61 +
65 62 .fc-header-right table {
66   - float: right;
67   - }
68   -
  63 + float: right;
  64 +}
  65 +
69 66 .fc-header-title {
70   - margin-top: 0;
71   - white-space: nowrap;
72   - }
73   -
  67 + margin-top: 0;
  68 + white-space: nowrap;
  69 +}
  70 +
74 71 .fc-header-space {
75   - padding-left: 10px;
76   - }
77   -
  72 + padding-left: 10px;
  73 +}
  74 +
78 75 /* right-to-left */
79 76
80 77 .fc-rtl .fc-header-title {
81   - direction: rtl;
82   - }
83   -
84   -
  78 + direction: rtl;
  79 +}
85 80
86 81 /* Buttons
87 82 ------------------------------------------------------------------------*/
88 83
89 84 .fc-header .fc-state-default,
90 85 .fc-header .ui-state-default {
91   - margin-bottom: 1em;
92   - cursor: pointer;
93   - }
94   -
  86 + margin-bottom: 1em;
  87 + cursor: pointer;
  88 +}
  89 +
95 90 .fc-header .fc-state-default {
96   - border-width: 1px 0;
97   - padding: 0 1px;
98   - }
99   -
  91 + border-width: 1px 0;
  92 + padding: 0 1px;
  93 +}
  94 +
100 95 .fc-header .fc-state-default,
101 96 .fc-header .fc-state-default a {
102   - border-style: solid;
103   - }
104   -
  97 + border-style: solid;
  98 +}
  99 +
105 100 .fc-header .fc-state-default a {
106   - display: block;
107   - border-width: 0 1px;
108   - margin: 0 -1px;
109   - width: 100%;
110   - text-decoration: none;
111   - }
112   -
  101 + display: block;
  102 + border-width: 0 1px;
  103 + margin: 0 -1px;
  104 + width: 100%;
  105 + text-decoration: none;
  106 +}
  107 +
113 108 .fc-header .fc-state-default span {
114   - display: block;
115   - border-style: solid;
116   - border-width: 1px 0 1px 1px;
117   - padding: 3px 5px;
118   - }
119   -
  109 + display: block;
  110 + border-style: solid;
  111 + border-width: 1px 0 1px 1px;
  112 + padding: 3px 5px;
  113 +}
  114 +
120 115 .fc-header .ui-state-default {
121   - padding: 4px 6px;
122   - }
123   -
  116 + padding: 4px 6px;
  117 +}
  118 +
124 119 .fc-header .fc-state-default span,
125 120 .fc-header .ui-state-default span {
126   - white-space: nowrap;
127   - }
128   -
  121 + white-space: nowrap;
  122 +}
  123 +
129 124 /* for adjacent buttons */
130   -
  125 +
131 126 .fc-header .fc-no-right {
132   - padding-right: 0;
133   - }
134   -
  127 + padding-right: 0;
  128 +}
  129 +
135 130 .fc-header .fc-no-right a {
136   - margin-right: 0;
137   - border-right: 0;
138   - }
139   -
  131 + margin-right: 0;
  132 + border-right: 0;
  133 +}
  134 +
140 135 .fc-header .ui-no-right {
141   - border-right: 0;
142   - }
143   -
  136 + border-right: 0;
  137 +}
  138 +
144 139 /* for fake rounded corners */
145   -
  140 +
146 141 .fc-header .fc-corner-left {
147   - margin-left: 1px;
148   - padding-left: 0;
149   - }
150   -
  142 + margin-left: 1px;
  143 + padding-left: 0;
  144 +}
  145 +
151 146 .fc-header .fc-corner-right {
152   - margin-right: 1px;
153   - padding-right: 0;
154   - }
155   -
  147 + margin-right: 1px;
  148 + padding-right: 0;
  149 +}
  150 +
156 151 /* DEFAULT button COLORS */
157   -
  152 +
158 153 .fc-header .fc-state-default,
159 154 .fc-header .fc-state-default a {
160   - border-color: #777; /* outer border */
161   - color: #333;
162   - }
  155 + border-color: #777; /* outer border */
  156 + color: #333;
  157 +}
163 158
164 159 .fc-header .fc-state-default span {
165   - border-color: #fff #fff #d1d1d1; /* inner border */
166   - background: #e8e8e8;
167   - }
168   -
  160 + border-color: #fff #fff #d1d1d1; /* inner border */
  161 + background: #e8e8e8;
  162 +}
  163 +
169 164 /* PRESSED button COLORS (down and active) */
170   -
  165 +
171 166 .fc-header .fc-state-active a {
172   - color: #fff;
173   - }
174   -
  167 + color: #fff;
  168 +}
  169 +
175 170 .fc-header .fc-state-down span,
176 171 .fc-header .fc-state-active span {
177   - background: #888;
178   - border-color: #808080 #808080 #909090; /* inner border */
179   - }
180   -
  172 + background: #888;
  173 + border-color: #808080 #808080 #909090; /* inner border */
  174 +}
  175 +
181 176 /* DISABLED button COLORS */
182   -
  177 +
183 178 .fc-header .fc-state-disabled a {
184   - color: #999;
185   - }
186   -
  179 + color: #999;
  180 +}
  181 +
187 182 .fc-header .fc-state-disabled,
188 183 .fc-header .fc-state-disabled a {
189   - border-color: #ccc; /* outer border */
190   - }
191   -
  184 + border-color: #ccc; /* outer border */
  185 +}
  186 +
192 187 .fc-header .fc-state-disabled span {
193   - border-color: #fff #fff #f0f0f0; /* inner border */
194   - background: #f0f0f0;
195   - }
196   -
197   -
198   -
  188 + border-color: #fff #fff #f0f0f0; /* inner border */
  189 + background: #f0f0f0;
  190 +}
  191 +
199 192 /* Content Area & Global Cell Styles
200 193 ------------------------------------------------------------------------*/
201   -
  194 +
202 195 .fc-widget-content {
203   - border: 1px solid #ccc; /* outer border color */
204   - }
205   -
  196 + border: 1px solid #ccc; /* outer border color */
  197 +}
  198 +
206 199 .fc-content {
207   - clear: both;
208   - }
209   -
  200 + clear: both;
  201 +}
  202 +
210 203 .fc-content .fc-state-default {
211   - border-style: solid;
212   - border-color: #ccc; /* inner border color */
213   - }
214   -
215   -.fc-content .fc-state-highlight { /* today */
216   - background: #ffc;
217   - }
218   -
  204 + border-style: solid;
  205 + border-color: #ccc; /* inner border color */
  206 +}
  207 +
  208 +.fc-content .fc-state-highlight {
  209 +/* today */
  210 + background: #ffc;
  211 +}
  212 +
219 213 .fc-content .fc-not-today {
220   - background: none;
221   - }
222   -
223   -.fc-cell-overlay { /* semi-transparent rectangle while dragging */
224   - background: #9cf;
225   - opacity: .2;
226   - filter: alpha(opacity=20); /* for IE */
227   - }
228   -
229   -.fc-view { /* prevents dragging outside of widget */
230   - width: 100%;
231   - overflow: hidden;
232   - }
233   -
234   -
235   -
  214 + background: none;
  215 +}
  216 +
  217 +.fc-cell-overlay {
  218 +/* semi-transparent rectangle while dragging */
  219 + background: #9cf;
  220 + opacity: .2;
  221 + filter: alpha(opacity = 20); /* for IE */
  222 +}
  223 +
  224 +.fc-view {
  225 +/* prevents dragging outside of widget */
  226 + width: 100%;
  227 + overflow: hidden;
  228 +}
  229 +
236 230 /* Global Event Styles
237 231 ------------------------------------------------------------------------*/
238 232
239 233 .fc-event,
240 234 .fc-agenda .fc-event-time,
241 235 .fc-event a {
242   - border-style: solid;
243   - border-color: #36c; /* default BORDER color (probably the same as background-color) */
244   - background-color: #36c; /* default BACKGROUND color */
245   - color: #fff; /* default TEXT color */
246   - }
247   -
248   - /* Use the 'className' CalEvent property and the following
249   - * example CSS to change event color on a per-event basis:
250   - *
251   - * .myclass,
252   - * .fc-agenda .myclass .fc-event-time,
253   - * .myclass a {
254   - * background-color: black;
255   - * border-color: black;
256   - * color: red;
257   - * }
258   - */
259   -
  236 + border-style: solid;
  237 + border-color: #36c; /* default BORDER color (probably the same as background-color) */
  238 + background-color: #36c; /* default BACKGROUND color */
  239 + color: #fff; /* default TEXT color */
  240 +}
  241 +
  242 +/* Use the 'className' CalEvent property and the following
  243 + * example CSS to change event color on a per-event basis:
  244 + *
  245 + * .myclass,
  246 + * .fc-agenda .myclass .fc-event-time,
  247 + * .myclass a {
  248 + * background-color: black;
  249 + * border-color: black;
  250 + * color: red;
  251 + * }
  252 + */
  253 +
260 254 .fc-event {
261   - text-align: left;
262   - }
263   -
  255 + text-align: left;
  256 +}
  257 +
264 258 .fc-event a {
265   - overflow: hidden;
266   - font-size: .85em;
267   - text-decoration: none;
268   - cursor: pointer;
269   - }
270   -
  259 + overflow: hidden;
  260 + font-size: .85em;
  261 + text-decoration: none;
  262 + cursor: pointer;
  263 +}
  264 +
271 265 .fc-event-editable {
272   - cursor: pointer;
273   - }
274   -
  266 + cursor: pointer;
  267 +}
  268 +
275 269 .fc-event-time,
276 270 .fc-event-title {
277   - padding: 0 1px;
278   - }
279   -
  271 + padding: 0 1px;
  272 +}
  273 +
280 274 /* for fake rounded corners */
281 275
282 276 .fc-event a {
283   - display: block;
284   - position: relative;
285   - width: 100%;
286   - height: 100%;
287   - }
288   -
  277 + display: block;
  278 + position: relative;
  279 + width: 100%;
  280 + height: 100%;
  281 +}
  282 +
289 283 /* right-to-left */
290 284
291 285 .fc-rtl .fc-event a {
292   - text-align: right;
293   - }
294   -
  286 + text-align: right;
  287 +}
  288 +
295 289 /* resizable */
296   -
  290 +
297 291 .fc .ui-resizable-handle {
298   - display: block;
299   - position: absolute;
300   - z-index: 99999;
301   - border: 0 !important; /* important overrides pre jquery ui 1.7 styles */
302   - background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */
303   - }
304   -
305   -
306   -
  292 + display: block;
  293 + position: absolute;
  294 + z-index: 99999;
  295 + border: 0 !important; /* important overrides pre jquery ui 1.7 styles */
  296 + background: url(data:image/gif;base64,AAAA) !important; /* hover fix for IE */
  297 +}
  298 +
307 299 /* Horizontal Events
308 300 ------------------------------------------------------------------------*/
309 301
310 302 .fc-event-hori {
311   - border-width: 1px 0;
312   - margin-bottom: 1px;
313   - }
314   -
  303 + border-width: 1px 0;
  304 + margin-bottom: 1px;
  305 +}
  306 +
315 307 .fc-event-hori a {
316   - border-width: 0;
317   - }
318   -
  308 + border-width: 0;
  309 +}
  310 +
319 311 /* for fake rounded corners */
320   -
  312 +
321 313 .fc-content .fc-corner-left {
322   - margin-left: 1px;
323   - }
324   -
  314 + margin-left: 1px;
  315 +}
  316 +
325 317 .fc-content .fc-corner-left a {
326   - margin-left: -1px;
327   - border-left-width: 1px;
328   - }
329   -
  318 + margin-left: -1px;
  319 + border-left-width: 1px;
  320 +}
  321 +
330 322 .fc-content .fc-corner-right {
331   - margin-right: 1px;
332   - }
333   -
  323 + margin-right: 1px;
  324 +}
  325 +
334 326 .fc-content .fc-corner-right a {
335   - margin-right: -1px;
336   - border-right-width: 1px;
337   - }
338   -
  327 + margin-right: -1px;
  328 + border-right-width: 1px;
  329 +}
  330 +
339 331 /* resizable */
340   -
  332 +
341 333 .fc-event-hori .ui-resizable-e {
342   - top: 0 !important; /* importants override pre jquery ui 1.7 styles */
343   - right: -3px !important;
344   - width: 7px !important;
345   - height: 100% !important;
346   - cursor: e-resize;
347   - }
348   -
  334 + top: 0 !important; /* importants override pre jquery ui 1.7 styles */
  335 + right: -3px !important;
  336 + width: 7px !important;
  337 + height: 100% !important;
  338 + cursor: e-resize;
  339 +}
  340 +
349 341 .fc-event-hori .ui-resizable-w {
350   - top: 0 !important;
351   - left: -3px !important;
352   - width: 7px !important;
353   - height: 100% !important;
354   - cursor: w-resize;
355   - }
356   -
  342 + top: 0 !important;
  343 + left: -3px !important;
  344 + width: 7px !important;
  345 + height: 100% !important;
  346 + cursor: w-resize;
  347 +}
  348 +
357 349 .fc-event-hori .ui-resizable-handle {
358   - _padding-bottom: 14px; /* IE6 had 0 height */
359   - }
360   -
361   -
  350 + _padding-bottom: 14px; /* IE6 had 0 height */
  351 +}
362 352
363 353 /* Month View, Basic Week View, Basic Day View
364 354 ------------------------------------------------------------------------*/
365 355
366 356 .fc-grid table {
367   - width: 100%;
368   - }
369   -
  357 + width: 100%;
  358 +}
  359 +
370 360 .fc .fc-grid th {
371   - border-width: 0 0 0 1px;
372   - text-align: center;
373   - }
374   -
  361 + border-width: 0 0 0 1px;
  362 + text-align: center;
  363 +}
  364 +
375 365 .fc .fc-grid td {
376   - border-width: 1px 0 0 1px;
377   - }
378   -
  366 + border-width: 1px 0 0 1px;
  367 +}
  368 +
379 369 .fc-grid th.fc-leftmost,
380 370 .fc-grid td.fc-leftmost {
381   - border-left: 0;
382   - }
383   -
  371 + border-left: 0;
  372 +}
  373 +
384 374 .fc-grid .fc-day-number {
385   - float: right;
386   - padding: 0 2px;
387   - }
388   -
  375 + float: right;
  376 + padding: 0 2px;
  377 +}
  378 +
389 379 .fc-grid .fc-other-month .fc-day-number {
390   - opacity: 0.3;
391   - filter: alpha(opacity=30); /* for IE */
392   - /* opacity with small font can sometimes look too faded
393   - might want to set the 'color' property instead
394   - making day-numbers bold also fixes the problem */
395   - }
396   -
  380 + opacity: 0.3;
  381 + filter: alpha(opacity = 30); /* for IE */
  382 + /* opacity with small font can sometimes look too faded
  383 + might want to set the 'color' property instead
  384 + making day-numbers bold also fixes the problem */
  385 +}
  386 +
397 387 .fc-grid .fc-day-content {
398   - clear: both;
399   - padding: 2px 2px 0; /* distance between events and day edges */
400   - }
401   -
  388 + clear: both;
  389 + padding: 2px 2px 0; /* distance between events and day edges */
  390 +}
  391 +
402 392 /* event styles */
403   -
  393 +
404 394 .fc-grid .fc-event-time {
405   - font-weight: bold;
406   - }
407   -
  395 + font-weight: bold;
  396 +}
  397 +
408 398 /* right-to-left */
409 399
410 400 .fc-rtl .fc-grid {
411   - direction: rtl;
412   - }
413   -
  401 + direction: rtl;
  402 +}
  403 +
414 404 .fc-rtl .fc-grid .fc-day-number {
415   - float: left;
416   - }
417   -
  405 + float: left;
  406 +}
  407 +
418 408 .fc-rtl .fc-grid .fc-event-time {
419   - float: right;
420   - }
421   -
  409 + float: right;
  410 +}
  411 +
422 412 /* Agenda Week View, Agenda Day View
423 413 ------------------------------------------------------------------------*/
424 414
425 415 .fc .fc-agenda th,
426 416 .fc .fc-agenda td {
427   - border-width: 1px 0 0 1px;
428   - }
429   -
  417 + border-width: 1px 0 0 1px;
  418 +}
  419 +
430 420 .fc .fc-agenda .fc-leftmost {
431   - border-left: 0;
432   - }
433   -
  421 + border-left: 0;
  422 +}
  423 +
434 424 .fc-agenda tr.fc-first th,
435 425 .fc-agenda tr.fc-first td {
436   - border-top: 0;
437   - }
438   -
  426 + border-top: 0;
  427 +}
  428 +
439 429 .fc-agenda-head tr.fc-last th {
440   - border-bottom-width: 1px;
441   - }
442   -
  430 + border-bottom-width: 1px;
  431 +}
  432 +
443 433 .fc .fc-agenda-head td,
444 434 .fc .fc-agenda-body td {
445   - background: none;
446   - }
447   -
  435 + background: none;
  436 +}
  437 +
448 438 .fc-agenda-head th {
449   - text-align: center;
450   - }
451   -
  439 + text-align: center;
  440 +}
  441 +
452 442 /* the time axis running down the left side */
453   -
  443 +
454 444 .fc-agenda .fc-axis {
455   - width: 50px;
456   - padding: 0 4px;
457   - vertical-align: middle;
458   - white-space: nowrap;
459   - text-align: right;
460   - font-weight: normal;
461   - }
462   -
  445 + width: 50px;
  446 + padding: 0 4px;
  447 + vertical-align: middle;
  448 + white-space: nowrap;
  449 + text-align: right;
  450 + font-weight: normal;
  451 +}
  452 +
463 453 /* all-day event cells at top */
464   -
  454 +
465 455 .fc-agenda-head tr.fc-all-day th {
466   - height: 35px;
467   - }
468   -
  456 + height: 35px;
  457 +}
  458 +
469 459 .fc-agenda-head td {
470   - padding-bottom: 10px;
471   - }
472   -
  460 + padding-bottom: 10px;
  461 +}
  462 +
473 463 .fc .fc-divider div {
474   - font-size: 1px; /* for IE6/7 */
475   - height: 2px;
476   - }
477   -
  464 + font-size: 1px; /* for IE6/7 */
  465 + height: 2px;
  466 +}
  467 +
478 468 .fc .fc-divider .fc-state-default {
479   - background: #eee; /* color for divider between all-day and time-slot events */
480   - }
  469 + background: #eee; /* color for divider between all-day and time-slot events */
  470 +}
481 471
482 472 /* body styles */
483   -
  473 +
484 474 .fc .fc-agenda-body td div {
485   - height: 20px; /* slot height */
486   - }
487   -
  475 + height: 20px; /* slot height */
  476 +}
  477 +
488 478 .fc .fc-agenda-body tr.fc-minor th,
489 479 .fc .fc-agenda-body tr.fc-minor td {
490   - border-top-style: dotted;
491   - }
492   -
493   -.fc-agenda .fc-day-content {
494   - padding: 2px 2px 0; /* distance between events and day edges */
495   - }
496   -
  480 + border-top-style: dotted;
  481 +}
497 482
  483 +.fc-agenda .fc-day-content {
  484 + padding: 2px 2px 0; /* distance between events and day edges */
  485 +}
498 486
499 487 /* Vertical Events
500 488 ------------------------------------------------------------------------*/
501 489
502 490 .fc-event-vert {
503   - border-width: 0 1px;
504   - }
505   -
  491 + border-width: 0 1px;
  492 +}
  493 +
506 494 .fc-event-vert a {
507   - border-width: 0;
508   - }
509   -
  495 + border-width: 0;
  496 +}
  497 +
510 498 /* for fake rounded corners */
511   -
  499 +
512 500 .fc-content .fc-corner-top {
513   - margin-top: 1px;
514   - }
515   -
  501 + margin-top: 1px;
  502 +}
  503 +
516 504 .fc-content .fc-corner-top a {
517   - margin-top: -1px;
518   - border-top-width: 1px;
519   - }
520   -
  505 + margin-top: -1px;
  506 + border-top-width: 1px;
  507 +}
  508 +
521 509 .fc-content .fc-corner-bottom {
522   - margin-bottom: 1px;
523   - }
524   -
  510 + margin-bottom: 1px;
  511 +}
  512 +
525 513 .fc-content .fc-corner-bottom a {
526   - margin-bottom: -1px;
527   - border-bottom-width: 1px;
528   - }
529   -
  514 + margin-bottom: -1px;
  515 + border-bottom-width: 1px;
  516 +}
  517 +
530 518 /* event content */
531   -
  519 +
532 520 .fc-event-vert span {
533   - display: block;
534   - position: relative;
535   - z-index: 2;
536   - }
537   -
  521 + display: block;
  522 + position: relative;
  523 + z-index: 2;
  524 +}
  525 +
538 526 .fc-event-vert span.fc-event-time {
539   - white-space: nowrap;
540   - _white-space: normal;
541   - overflow: hidden;
542   - border: 0;
543   - font-size: 10px;
544   - }
545   -
  527 + white-space: nowrap;
  528 + _white-space: normal;
  529 + overflow: hidden;
  530 + border: 0;
  531 + font-size: 10px;
  532 +}
  533 +
546 534 .fc-event-vert span.fc-event-title {
547   - line-height: 13px;
548   - }
549   -
550   -.fc-event-vert span.fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay */
551   - position: absolute;
552   - z-index: 1;
553   - top: 0;
554   - left: 0;
555   - width: 100%;
556   - height: 100%;
557   - background: #fff;
558   - opacity: .3;
559   - filter: alpha(opacity=30); /* for IE */
560   - }
561   -
  535 + line-height: 13px;
  536 +}
  537 +
  538 +.fc-event-vert span.fc-event-bg {
  539 +/* makes the event lighter w/ a semi-transparent overlay */
  540 + position: absolute;
  541 + z-index: 1;
  542 + top: 0;
  543 + left: 0;
  544 + width: 100%;
  545 + height: 100%;
  546 + background: #fff;
  547 + opacity: .3;
  548 + filter: alpha(opacity = 30); /* for IE */
  549 +}
  550 +
562 551 /* resizable */
563   -
  552 +
564 553 .fc-event-vert .ui-resizable-s {
565   - bottom: 0 !important; /* importants override pre jquery ui 1.7 styles */
566   - width: 100% !important;
567   - height: 8px !important;
568   - line-height: 8px !important;
569   - font-size: 11px !important;
570   - font-family: monospace;
571   - text-align: center;
572   - cursor: s-resize;
573   - }
  554 + bottom: 0 !important; /* importants override pre jquery ui 1.7 styles */
  555 + width: 100% !important;
  556 + height: 8px !important;
  557 + line-height: 8px !important;
  558 + font-size: 11px !important;
  559 + font-family: monospace;
  560 + text-align: center;
  561 + cursor: s-resize;
  562 +}
574 563
575 564
... ...
... ... @@ -12,60 +12,60 @@
12 12
13 13 (function($) {
14 14
15   - $.fullCalendar.gcalFeed = function(feedUrl, options) {
16   -
17   - feedUrl = feedUrl.replace(/\/basic$/, '/full');
18   - options = options || {};
19   -
20   - return function(start, end, callback) {
21   - var params = {
22   - 'start-min': $.fullCalendar.formatDate(start, 'u'),
23   - 'start-max': $.fullCalendar.formatDate(end, 'u'),
24   - 'singleevents': true,
25   - 'max-results': 9999
26   - };
27   - var ctz = options.currentTimezone;
28   - if (ctz) {
29   - params.ctz = ctz = ctz.replace(' ', '_');
30   - }
31   - $.getJSON(feedUrl + "?alt=json-in-script&callback=?", params, function(data) {
32   - var events = [];
33   - if (data.feed.entry) {
34   - $.each(data.feed.entry, function(i, entry) {
35   - var startStr = entry['gd$when'][0]['startTime'],
36   - start = $.fullCalendar.parseISO8601(startStr, true),
37   - end = $.fullCalendar.parseISO8601(entry['gd$when'][0]['endTime'], true),
38   - allDay = startStr.indexOf('T') == -1,
39   - url;
40   - $.each(entry.link, function() {
41   - if (this.type == 'text/html') {
42   - url = this.href;
43   - if (ctz) {
44   - url += (url.indexOf('?') == -1 ? '?' : '&') + 'ctz=' + ctz;
45   - }
46   - }
47   - });
48   - if (allDay) {
49   - $.fullCalendar.addDays(end, -1); // make inclusive
50   - }
51   - events.push({
52   - id: entry['gCal$uid']['value'],
53   - title: entry['title']['$t'],
54   - url: url,
55   - start: start,
56   - end: end,
57   - allDay: allDay,
58   - location: entry['gd$where'][0]['valueString'],
59   - description: entry['content']['$t'],
60   - className: options.className,
61   - editable: options.editable || false
62   - });
63   - });
64   - }
65   - callback(events);
66   - });
67   - }
68   -
69   - }
  15 + $.fullCalendar.gcalFeed = function(feedUrl, options) {
  16 +
  17 + feedUrl = feedUrl.replace(/\/basic$/, '/full');
  18 + options = options || {};
  19 +
  20 + return function(start, end, callback) {
  21 + var params = {
  22 + 'start-min': $.fullCalendar.formatDate(start, 'u'),
  23 + 'start-max': $.fullCalendar.formatDate(end, 'u'),
  24 + 'singleevents': true,
  25 + 'max-results': 9999
  26 + };
  27 + var ctz = options.currentTimezone;
  28 + if (ctz) {
  29 + params.ctz = ctz = ctz.replace(' ', '_');
  30 + }
  31 + $.getJSON(feedUrl + "?alt=json-in-script&callback=?", params, function(data) {
  32 + var events = [];
  33 + if (data.feed.entry) {
  34 + $.each(data.feed.entry, function(i, entry) {
  35 + var startStr = entry['gd$when'][0]['startTime'],
  36 + start = $.fullCalendar.parseISO8601(startStr, true),
  37 + end = $.fullCalendar.parseISO8601(entry['gd$when'][0]['endTime'], true),
  38 + allDay = startStr.indexOf('T') == -1,
  39 + url;
  40 + $.each(entry.link, function() {
  41 + if (this.type == 'text/html') {
  42 + url = this.href;
  43 + if (ctz) {
  44 + url += (url.indexOf('?') == -1 ? '?' : '&') + 'ctz=' + ctz;
  45 + }
  46 + }
  47 + });
  48 + if (allDay) {
  49 + $.fullCalendar.addDays(end, -1); // make inclusive
  50 + }
  51 + events.push({
  52 + id: entry['gCal$uid']['value'],
  53 + title: entry['title']['$t'],
  54 + url: url,
  55 + start: start,
  56 + end: end,
  57 + allDay: allDay,
  58 + location: entry['gd$where'][0]['valueString'],
  59 + description: entry['content']['$t'],
  60 + className: options.className,
  61 + editable: options.editable || false
  62 + });
  63 + });
  64 + }
  65 + callback(events);
  66 + });
  67 + }
  68 +
  69 + }
70 70
71 71 })(jQuery);
... ...
... ... @@ -41,6 +41,12 @@ window.RichFaces.Schedule = (function() {
41 41 return;
42 42 }
43 43 }
  44 + if (options.onDateRangeChanged != null) {
  45 + RichFaces.Schedule.eval("(function(){" + options.onDateRangeChanged + "})()", {
  46 + 'startDate':startDate,
  47 + 'endDate':endDate
  48 + });
  49 + }
44 50 if (_this.submitEventFunction != null) {
45 51 _this.submitEventFunction({} /* stub event */,
46 52 null,
... ... @@ -54,32 +60,58 @@ window.RichFaces.Schedule = (function() {
54 60 if (scheduleData != undefined) {
55 61 callback(scheduleData);
56 62 }
  63 + if (options.onDateRangeChangedComplete != null) {
  64 + RichFaces.Schedule.eval("(function(){" + options.onDateRangeChangedComplete + "})()", {
  65 + 'startDate':startDate,
  66 + 'endDate':endDate,
  67 + 'request':request,
  68 + 'data':data,
  69 + 'items':scheduleData
  70 + });
  71 + }
57 72 }
58 73 );
59 74 }
60 75 };
61   - var itemDragStart = function(item, event) {
  76 + var itemDragStart = function(item, event, ui, view) {
62 77 if (options.onItemDragStart != null) {
63   - eval("(function(){" + options.onItemDragStart + "})()");
  78 + RichFaces.Schedule.eval("(function(){" + options.onItemDragStart + "})()", {
  79 + 'item':item,
  80 + 'event':event,
  81 + 'ui':ui,
  82 + 'view':view
  83 + });
64 84 }
65 85 };
66   - var itemDragStop = function(item, event) {
  86 + var itemDragStop = function(item, event, ui, view) {
67 87 if (options.onItemDragStop != null) {
68   - eval("(function(){" + options.onItemDragStop + "})()");
  88 + RichFaces.Schedule.eval("(function(){" + options.onItemDragStop + "})()", {
  89 + 'item':item,
  90 + 'event':event,
  91 + 'ui':ui,
  92 + 'view':view
  93 + });
69 94 }
70 95 };
71   - var itemDrop = function(item, dayDelta, minuteDelta, allDay, revertFunc, event) {
  96 + var itemDrop = function(item, dayDelta, minuteDelta, allDay, revertFunc, event, ui, view) {
  97 + var result;
72 98 if (options.onItemDrop != null) {
73   - var result = eval("(function(){" + options.onItemDrop + "})()");
74   - if (result != null) {
75   - if (result === false) {
76   - revertFunc();
77   - }
  99 + result = RichFaces.Schedule.eval("(function(){" + options.onItemDrop + "})()", {
  100 + 'item':item,
  101 + 'dayDelta':dayDelta,
  102 + 'minuteDelta':minuteDelta,
  103 + 'allDay':allDay,
  104 + 'event':event,
  105 + 'ui':ui,
  106 + 'view':view
  107 + });
  108 + if (result === false) {
  109 + revertFunc();
78 110 return;
79 111 }
80 112 }
81 113 if (_this.submitEventFunction != null) {
82   - _this.submitEventFunction({} /* stub event */,
  114 + _this.submitEventFunction(event,
83 115 null,
84 116 itemMovedEventName,
85 117 item.id,
... ... @@ -87,25 +119,49 @@ window.RichFaces.Schedule = (function() {
87 119 null,
88 120 dayDelta, minuteDelta, allDay,
89 121 function(request, event, data) {
90   - if (data != undefined && data !== true) {
  122 + var decision = request.getJSON('_ajax:scheduleData');
  123 + var vetoed = false;
  124 + if (decision != undefined && decision !== true) {
91 125 revertFunc();
  126 + vetoed = true;
  127 + }
  128 + if (options.onItemDropComplete != null) {
  129 + RichFaces.Schedule.eval("(function(){" + options.onItemDropComplete + "})()", {
  130 + 'item':item,
  131 + 'dayDelta':dayDelta,
  132 + 'minuteDelta':minuteDelta,
  133 + 'allDay':allDay,
  134 + 'event':event,
  135 + 'ui':ui,
  136 + 'view':view,
  137 + 'request':request,
  138 + 'data':data,
  139 + 'vetoed':vetoed
  140 + });
92 141 }
93 142 }
94 143 );
95 144 }
  145 + return;
96 146 };
97   - var itemResized = function(item, dayDelta, minuteDelta, revertFunc, event) {
  147 + var itemResized = function(item, dayDelta, minuteDelta, revertFunc, event, ui, view) {
  148 + var result;
98 149 if (options.onItemResized != null) {
99   - var result = eval("(function(){" + options.onItemResized + "})()");
100   - if (result != null) {
101   - if (result === false) {
102   - revertFunc();
103   - }
  150 + result = RichFaces.Schedule.eval("(function(){" + options.onItemResized + "})()", {
  151 + 'item':item,
  152 + 'dayDelta':dayDelta,
  153 + 'minuteDelta':minuteDelta,
  154 + 'event':event,
  155 + 'ui':ui,
  156 + 'view':view
  157 + });
  158 + if (result === false) {
  159 + revertFunc();
104 160 return;
105 161 }
106 162 }
107 163 if (_this.submitEventFunction != null) {
108   - _this.submitEventFunction({} /* stub event */,
  164 + _this.submitEventFunction(event,
109 165 null,
110 166 itemResizedEventName,
111 167 item.id,
... ... @@ -113,93 +169,181 @@ window.RichFaces.Schedule = (function() {
113 169 null,
114 170 dayDelta, minuteDelta, null,
115 171 function(request, event, data) {
116   - if (data != undefined && data !== true) {
  172 + var decision = request.getJSON('_ajax:scheduleData');
  173 + var vetoed = false;
  174 + if (decision != undefined && decision !== true) {
117 175 revertFunc();
  176 + vetoed = true;
  177 + }
  178 + if (options.onItemResizedComplete != null) {
  179 + RichFaces.Schedule.eval("(function(){" + options.onItemResizedComplete + "})()", {
  180 + 'item':item,
  181 + 'dayDelta':dayDelta,
  182 + 'minuteDelta':minuteDelta,
  183 + 'event':event,
  184 + 'ui':ui,
  185 + 'view':view,
  186 + 'request':request,
  187 + 'data':data,
  188 + 'vetoed':vetoed
  189 + });
118 190 }
119 191 }
120 192 );
121 193 }
122 194 };
123   - var itemResizeStart = function(item, event) {
  195 + var itemResizeStart = function(item, event, ui, view) {
124 196 if (options.onItemResizeStart != null) {
125   - eval("(function(){" + options.onItemResizeStart + "})()");
  197 + RichFaces.Schedule.eval("(function(){" + options.onItemResizeStart + "})()", {
  198 + 'item':item,
  199 + 'event':event,
  200 + 'ui':ui,
  201 + 'view':view
  202 + });
126 203 }
127 204 };
128   - var itemResizeStop = function(item, event) {
  205 + var itemResizeStop = function(item, event, ui, view) {
129 206 if (options.onItemResizeStop != null) {
130   - eval("(function(){" + options.onItemResizeStop + "})()");
  207 + RichFaces.Schedule.eval("(function(){" + options.onItemResizeStop + "})()", {
  208 + 'item':item,
  209 + 'event':event,
  210 + 'ui':ui,
  211 + 'view':view
  212 + });
131 213 }
132 214 };
133   - var itemMouseover = function(item) {
  215 + var itemMouseover = function(item, event, view) {
134 216 if (options.onItemMouseover != null) {
135   - eval("(function(){" + options.onItemMouseover + "})()");
  217 + RichFaces.Schedule.eval("(function(){" + options.onItemMouseover + "})()", {
  218 + 'item':item,
  219 + 'event':event,
  220 + 'view':view
  221 + });
136 222 }
137 223 };
138   - var itemMouseout = function(item) {
  224 + var itemMouseout = function(item, event, view) {
139 225 if (options.onItemMouseout != null) {
140   - eval("(function(){" + options.onItemMouseout + "})()");
  226 + RichFaces.Schedule.eval("(function(){" + options.onItemMouseout + "})()", {
  227 + 'item':item,
  228 + 'event':event,
  229 + 'view':view
  230 + });
141 231 }
142 232 };
143   - var itemClick = function(item, event) {
  233 + var itemClick = function(item, event, view) {
  234 + var result;
144 235 if (options.onItemSelected != null) {
145   - var result = eval("(function(){" + options.onItemSelected + "})()");
146   - if (result != null) {
147   - return;
148   - }
  236 + result = RichFaces.Schedule.eval("(function(){" + options.onItemSelected + "})()", {
  237 + 'item':item,
  238 + 'event':event,
  239 + 'view':view
  240 + });
  241 + }
  242 + if (result === false) {
  243 + return false;
149 244 }
150 245 if (_this.submitEventFunction != null) {
151   - _this.submitEventFunction({},
  246 + _this.submitEventFunction(event,
152 247 null,
153 248 itemSelectedEventName,
154 249 item.id,
155   - null, null, null, null, null, null
  250 + null, null, null, null, null, function(request, event, data) {
  251 + if (options.onItemSelectedComplete != null) {
  252 + RichFaces.Schedule.eval("(function(){" + options.onItemSelectedComplete + "})()", {
  253 + 'item':item,
  254 + 'event':event,
  255 + 'view':view,
  256 + 'request':request,
  257 + 'data':data
  258 + });
  259 + }
  260 + }
156 261 );
157 262 }
  263 + return result;
158 264 };
159   - var dayClick = function(date, allDay, event) {
  265 + var dayClick = function(date, allDay, event, view) {
  266 + var result;
160 267 if (options.onDateSelected != null) {
161   - var result = eval("(function(){" + options.onDateSelected + "})()");
162   - if (result != null) {
163   - throw "return not allowed in onDaySelect";
164   - }
  268 + result = RichFaces.Schedule.eval("(function(){" + options.onDateSelected + "})()", {
  269 + 'date':date,
  270 + 'allDay':allDay,
  271 + 'event':event,
  272 + 'view':view
  273 + });
  274 + }
  275 + if (result === false) {
  276 + return false;
165 277 }
166 278 if (_this.submitEventFunction != null) {
167   - _this.submitEventFunction({},
  279 + _this.submitEventFunction(event,
168 280 null,
169 281 daySelectedEventName,
170   - null, formatDateParam(date), null, null, null, allDay, null
  282 + null, formatDateParam(date), null, null, null, allDay, function(request, event, data) {
  283 + if (options.onDateSelectedComplete != null) {
  284 + RichFaces.Schedule.eval("(function(){" + options.onDateSelectedComplete + "})()", {
  285 + 'date':date,
  286 + 'allDay':allDay,
  287 + 'request':request,
  288 + 'event':event,
  289 + 'view':view,
  290 + 'data':data
  291 + });
  292 + }
  293 + }
171 294 );
172 295 }
  296 + return result;
173 297 };
174 298 var selectedView;
175   - //TODO how to hide all (except for view param) scopeChain from code in options.onViewDisplay?
176   - var viewDisplay = function(view) {
177   - if (options.onViewDisplay != null) {
178   - var result = eval("(function(){" + options.onViewDisplay + "})()");
179   - if (result != null) {
180   - throw "return not allowed in onViewDisplay";
181   - }
182   - }
  299 + var viewChanged = function(view) {
183 300 if (selectedView != view && selectedView != undefined) {
  301 + if (options.onViewChanged != null) {
  302 + RichFaces.Schedule.eval("(function(){" + options.onViewChanged + "})()", {
  303 + 'view':view
  304 + });
  305 + }
184 306 if (_this.submitEventFunction != null) {
185 307 _this.submitEventFunction({},
186 308 view.name,
187 309 viewChangedEventName,
188   - null, null, null, null, null, null, null
  310 + null, null, null, null, null, null, function(request, event, data) {
  311 + if (options.onViewChangedComplete != null) {
  312 + RichFaces.Schedule.eval("(function(){" + options.onViewChangedComplete + "})()", {
  313 + 'view':view,
  314 + 'request':request,
  315 + 'data':data
  316 + });
  317 + }
  318 + }
189 319 );
190 320 }
191 321 }
192 322 selectedView = view;
193 323 };
194   - var onDateRangeSelected = function(startDate, endDate, allDay) {
  324 + var onDateRangeSelected = function(startDate, endDate, allDay, view) {
195 325 if (!component.fullCalendar('option', 'selectable')) {
196   - return;
  326 + return false;
197 327 }
  328 + var result;
198 329 if (options.onDateRangeSelected != null) {
199   - var result = eval("(function(){" + options.onDateRangeSelected + "})()");
200   - if (result != null) {
201   - return;
202   - }
  330 + result = RichFaces.Schedule.eval("(function(){" + options.onDateRangeSelected + "})()", {
  331 + 'startDate':startDate,
  332 + 'endDate':endDate,
  333 + 'allDay':allDay,
  334 + 'view':view
  335 + });
  336 + }
  337 + if (result === false) {
  338 + /**
  339 + * Unselect must be in all three places below in order to
  340 + * avoid situation where, while event is being sent via ajax
  341 + * to server, client side selection disapeares.
  342 + * Current implementation shortens delay between selection
  343 + * disapearing and potentialy created event appearing.
  344 + */
  345 + component.fullCalendar('unselect');
  346 + return false;
203 347 }
204 348 if (_this.submitEventFunction != null) {
205 349 _this.submitEventFunction({},
... ... @@ -209,11 +353,22 @@ window.RichFaces.Schedule = (function() {
209 353 function(request, event, data) {
210 354 component.fullCalendar('refetchEvents');
211 355 component.fullCalendar('unselect');
  356 + if (options.onDateRangeSelected != null) {
  357 + RichFaces.Schedule.eval("(function(){" + options.onDateRangeSelectedComplete + "})()", {
  358 + 'startDate':startDate,
  359 + 'endDate':endDate,
  360 + 'allDay':allDay,
  361 + 'view':view,
  362 + 'request':request,
  363 + 'data':data
  364 + });
  365 + }
212 366 }
213 367 );
214 368 } else {
215 369 component.fullCalendar('unselect');
216 370 }
  371 + return result;
217 372 };
218 373 options = jQuery.extend({
219 374 events: fillCalendarFunction,
... ... @@ -226,14 +381,26 @@ window.RichFaces.Schedule = (function() {
226 381 eventClick: itemClick,
227 382 eventMouseover: itemMouseover,
228 383 eventMouseout: itemMouseout,
229   - viewDisplay: viewDisplay,
  384 + viewDisplay: viewChanged,
230 385 dayClick: dayClick,
231 386 select: onDateRangeSelected
232 387 }, options);
233 388 jQuery(document).ready(function() {
234 389 component = jQuery(elt).fullCalendar(options);
  390 + elt.component = _this;
  391 + _this.component = component;
235 392 });
236 393 };
237 394
238 395 }());
239   -window.RichFaces.Schedule.prototype.messages = {};
\ No newline at end of file
  396 +window.RichFaces.Schedule.prototype.refetchItems = function() {
  397 + this.component.fullCalendar('refetchEvents');
  398 +};
  399 +window.RichFaces.Schedule.prototype.messages = {};
  400 +window.RichFaces.Schedule.eval = function(template, object) {
  401 + var value = '';
  402 + with (object) {
  403 + value = eval(template);
  404 + }
  405 + return value;
  406 +};
\ No newline at end of file
... ...
... ... @@ -7,513 +7,530 @@
7 7 *
8 8 * http://docs.jquery.com/UI
9 9 */
10   -;jQuery.ui || (function($) {
11   -
12   -var _remove = $.fn.remove,
13   - isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
14   -
15   -//Helper functions and ui object
16   -$.ui = {
17   - version: "1.7.2",
18   -
19   - // $.ui.plugin is deprecated. Use the proxy pattern instead.
20   - plugin: {
21   - add: function(module, option, set) {
22   - var proto = $.ui[module].prototype;
23   - for(var i in set) {
24   - proto.plugins[i] = proto.plugins[i] || [];
25   - proto.plugins[i].push([option, set[i]]);
26   - }
27   - },
28   - call: function(instance, name, args) {
29   - var set = instance.plugins[name];
30   - if(!set || !instance.element[0].parentNode) { return; }
31   -
32   - for (var i = 0; i < set.length; i++) {
33   - if (instance.options[set[i][0]]) {
34   - set[i][1].apply(instance.element, args);
35   - }
36   - }
37   - }
38   - },
39   -
40   - contains: function(a, b) {
41   - return document.compareDocumentPosition
42   - ? a.compareDocumentPosition(b) & 16
43   - : a !== b && a.contains(b);
44   - },
45   -
46   - hasScroll: function(el, a) {
47   -
48   - //If overflow is hidden, the element might have extra content, but the user wants to hide it
49   - if ($(el).css('overflow') == 'hidden') { return false; }
50   -
51   - var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
52   - has = false;
53   -
54   - if (el[scroll] > 0) { return true; }
55   -
56   - // TODO: determine which cases actually cause this to happen
57   - // if the element doesn't have the scroll set, see if it's possible to
58   - // set the scroll
59   - el[scroll] = 1;
60   - has = (el[scroll] > 0);
61   - el[scroll] = 0;
62   - return has;
63   - },
64   -
65   - isOverAxis: function(x, reference, size) {
66   - //Determines when x coordinate is over "b" element axis
67   - return (x > reference) && (x < (reference + size));
68   - },
69   -
70   - isOver: function(y, x, top, left, height, width) {
71   - //Determines when x, y coordinates is over "b" element
72   - return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
73   - },
74   -
75   - keyCode: {
76   - BACKSPACE: 8,
77   - CAPS_LOCK: 20,
78   - COMMA: 188,
79   - CONTROL: 17,
80   - DELETE: 46,
81   - DOWN: 40,
82   - END: 35,
83   - ENTER: 13,
84   - ESCAPE: 27,
85   - HOME: 36,
86   - INSERT: 45,
87   - LEFT: 37,
88   - NUMPAD_ADD: 107,
89   - NUMPAD_DECIMAL: 110,
90   - NUMPAD_DIVIDE: 111,
91   - NUMPAD_ENTER: 108,
92   - NUMPAD_MULTIPLY: 106,
93   - NUMPAD_SUBTRACT: 109,
94   - PAGE_DOWN: 34,
95   - PAGE_UP: 33,
96   - PERIOD: 190,
97   - RIGHT: 39,
98   - SHIFT: 16,
99   - SPACE: 32,
100   - TAB: 9,
101   - UP: 38
102   - }
103   -};
104   -
105   -// WAI-ARIA normalization
106   -if (isFF2) {
107   - var attr = $.attr,
108   - removeAttr = $.fn.removeAttr,
109   - ariaNS = "http://www.w3.org/2005/07/aaa",
110   - ariaState = /^aria-/,
111   - ariaRole = /^wairole:/;
112   -
113   - $.attr = function(elem, name, value) {
114   - var set = value !== undefined;
115   -
116   - return (name == 'role'
117   - ? (set
118   - ? attr.call(this, elem, name, "wairole:" + value)
119   - : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
120   - : (ariaState.test(name)
121   - ? (set
122   - ? elem.setAttributeNS(ariaNS,
123   - name.replace(ariaState, "aaa:"), value)
124   - : attr.call(this, elem, name.replace(ariaState, "aaa:")))
125   - : attr.apply(this, arguments)));
126   - };
127   -
128   - $.fn.removeAttr = function(name) {
129   - return (ariaState.test(name)
130   - ? this.each(function() {
131   - this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
132   - }) : removeAttr.call(this, name));
133   - };
134   -}
135   -
136   -//jQuery plugins
137   -$.fn.extend({
138   - remove: function() {
139   - // Safari has a native remove event which actually removes DOM elements,
140   - // so we have to use triggerHandler instead of trigger (#3037).
141   - $("*", this).add(this).each(function() {
142   - $(this).triggerHandler("remove");
143   - });
144   - return _remove.apply(this, arguments );
145   - },
146   -
147   - enableSelection: function() {
148   - return this
149   - .attr('unselectable', 'off')
150   - .css('MozUserSelect', '')
151   - .unbind('selectstart.ui');
152   - },
153   -
154   - disableSelection: function() {
155   - return this
156   - .attr('unselectable', 'on')
157   - .css('MozUserSelect', 'none')
158   - .bind('selectstart.ui', function() { return false; });
159   - },
160   -
161   - scrollParent: function() {
162   - var scrollParent;
163   - if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
164   - scrollParent = this.parents().filter(function() {
165   - 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));
166   - }).eq(0);
167   - } else {
168   - scrollParent = this.parents().filter(function() {
169   - return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
170   - }).eq(0);
171   - }
172   -
173   - return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
174   - }
175   -});
176   -
177   -
178   -//Additional selectors
179   -$.extend($.expr[':'], {
180   - data: function(elem, i, match) {
181   - return !!$.data(elem, match[3]);
182   - },
183   -
184   - focusable: function(element) {
185   - var nodeName = element.nodeName.toLowerCase(),
186   - tabIndex = $.attr(element, 'tabindex');
187   - return (/input|select|textarea|button|object/.test(nodeName)
188   - ? !element.disabled
189   - : 'a' == nodeName || 'area' == nodeName
190   - ? element.href || !isNaN(tabIndex)
191   - : !isNaN(tabIndex))
192   - // the element and all of its ancestors must be visible
193   - // the browser may report that the area is hidden
194   - && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
195   - },
196   -
197   - tabbable: function(element) {
198   - var tabIndex = $.attr(element, 'tabindex');
199   - return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
200   - }
201   -});
202   -
203   -
204   -// $.widget is a factory to create jQuery plugins
205   -// taking some boilerplate code out of the plugin code
206   -function getter(namespace, plugin, method, args) {
207   - function getMethods(type) {
208   - var methods = $[namespace][plugin][type] || [];
209   - return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
210   - }
211   -
212   - var methods = getMethods('getter');
213   - if (args.length == 1 && typeof args[0] == 'string') {
214   - methods = methods.concat(getMethods('getterSetter'));
215   - }
216   - return ($.inArray(method, methods) != -1);
217   -}
218   -
219   -$.widget = function(name, prototype) {
220   - var namespace = name.split(".")[0];
221   - name = name.split(".")[1];
222   -
223   - // create plugin method
224   - $.fn[name] = function(options) {
225   - var isMethodCall = (typeof options == 'string'),
226   - args = Array.prototype.slice.call(arguments, 1);
227   -
228   - // prevent calls to internal methods
229   - if (isMethodCall && options.substring(0, 1) == '_') {
230   - return this;
231   - }
232   -
233   - // handle getter methods
234   - if (isMethodCall && getter(namespace, name, options, args)) {
235   - var instance = $.data(this[0], name);
236   - return (instance ? instance[options].apply(instance, args)
237   - : undefined);
238   - }
239   -
240   - // handle initialization and non-getter methods
241   - return this.each(function() {
242   - var instance = $.data(this, name);
243   -
244   - // constructor
245   - (!instance && !isMethodCall &&
246   - $.data(this, name, new $[namespace][name](this, options))._init());
247   -
248   - // method call
249   - (instance && isMethodCall && $.isFunction(instance[options]) &&
250   - instance[options].apply(instance, args));
251   - });
252   - };
253   -
254   - // create widget constructor
255   - $[namespace] = $[namespace] || {};
256   - $[namespace][name] = function(element, options) {
257   - var self = this;
258   -
259   - this.namespace = namespace;
260   - this.widgetName = name;
261   - this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
262   - this.widgetBaseClass = namespace + '-' + name;
263   -
264   - this.options = $.extend({},
265   - $.widget.defaults,
266   - $[namespace][name].defaults,
267   - $.metadata && $.metadata.get(element)[name],
268   - options);
269   -
270   - this.element = $(element)
271   - .bind('setData.' + name, function(event, key, value) {
272   - if (event.target == element) {
273   - return self._setData(key, value);
274   - }
275   - })
276   - .bind('getData.' + name, function(event, key) {
277   - if (event.target == element) {
278   - return self._getData(key);
279   - }
280   - })
281   - .bind('remove', function() {
282   - return self.destroy();
283   - });
284   - };
285   -
286   - // add widget prototype
287   - $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
288   -
289   - // TODO: merge getter and getterSetter properties from widget prototype
290   - // and plugin prototype
291   - $[namespace][name].getterSetter = 'option';
292   -};
293   -
294   -$.widget.prototype = {
295   - _init: function() {},
296   - destroy: function() {
297   - this.element.removeData(this.widgetName)
298   - .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
299   - .removeAttr('aria-disabled');
300   - },
301   -
302   - option: function(key, value) {
303   - var options = key,
304   - self = this;
305   -
306   - if (typeof key == "string") {
307   - if (value === undefined) {
308   - return this._getData(key);
309   - }
310   - options = {};
311   - options[key] = value;
312   - }
313   -
314   - $.each(options, function(key, value) {
315   - self._setData(key, value);
316   - });
317   - },
318   - _getData: function(key) {
319   - return this.options[key];
320   - },
321   - _setData: function(key, value) {
322   - this.options[key] = value;
323   -
324   - if (key == 'disabled') {
325   - this.element
326   - [value ? 'addClass' : 'removeClass'](
327   - this.widgetBaseClass + '-disabled' + ' ' +
328   - this.namespace + '-state-disabled')
329   - .attr("aria-disabled", value);
330   - }
331   - },
332   -
333   - enable: function() {
334   - this._setData('disabled', false);
335   - },
336   - disable: function() {
337   - this._setData('disabled', true);
338   - },
339   -
340   - _trigger: function(type, event, data) {
341   - var callback = this.options[type],
342   - eventName = (type == this.widgetEventPrefix
343   - ? type : this.widgetEventPrefix + type);
344   -
345   - event = $.Event(event);
346   - event.type = eventName;
347   -
348   - // copy original event properties over to the new event
349   - // this would happen if we could call $.event.fix instead of $.Event
350   - // but we don't have a way to force an event to be fixed multiple times
351   - if (event.originalEvent) {
352   - for (var i = $.event.props.length, prop; i;) {
353   - prop = $.event.props[--i];
354   - event[prop] = event.originalEvent[prop];
355   - }
356   - }
357   -
358   - this.element.trigger(event, data);
359   -
360   - return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
361   - || event.isDefaultPrevented());
362   - }
363   -};
364   -
365   -$.widget.defaults = {
366   - disabled: false
367   -};
368   -
369   -
370   -/** Mouse Interaction Plugin **/
371   -
372   -$.ui.mouse = {
373   - _mouseInit: function() {
374   - var self = this;
375   -
376   - this.element
377   - .bind('mousedown.'+this.widgetName, function(event) {
378   - return self._mouseDown(event);
379   - })
380   - .bind('click.'+this.widgetName, function(event) {
381   - if(self._preventClickEvent) {
382   - self._preventClickEvent = false;
383   - event.stopImmediatePropagation();
384   - return false;
385   - }
386   - });
387   -
388   - // Prevent text selection in IE
389   - if ($.browser.msie) {
390   - this._mouseUnselectable = this.element.attr('unselectable');
391   - this.element.attr('unselectable', 'on');
392   - }
393   -
394   - this.started = false;
395   - },
396   -
397   - // TODO: make sure destroying one instance of mouse doesn't mess with
398   - // other instances of mouse
399   - _mouseDestroy: function() {
400   - this.element.unbind('.'+this.widgetName);
401   -
402   - // Restore text selection in IE
403   - ($.browser.msie
404   - && this.element.attr('unselectable', this._mouseUnselectable));
405   - },
406   -
407   - _mouseDown: function(event) {
408   - // don't let more than one widget handle mouseStart
409   - // TODO: figure out why we have to use originalEvent
410   - event.originalEvent = event.originalEvent || {};
411   - if (event.originalEvent.mouseHandled) { return; }
412   -
413   - // we may have missed mouseup (out of window)
414   - (this._mouseStarted && this._mouseUp(event));
415   -
416   - this._mouseDownEvent = event;
417   -
418   - var self = this,
419   - btnIsLeft = (event.which == 1),
420   - elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
421   - if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
422   - return true;
423   - }
424   -
425   - this.mouseDelayMet = !this.options.delay;
426   - if (!this.mouseDelayMet) {
427   - this._mouseDelayTimer = setTimeout(function() {
428   - self.mouseDelayMet = true;
429   - }, this.options.delay);
430   - }
431   -
432   - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
433   - this._mouseStarted = (this._mouseStart(event) !== false);
434   - if (!this._mouseStarted) {
435   - event.preventDefault();
436   - return true;
437   - }
438   - }
439   -
440   - // these delegates are required to keep context
441   - this._mouseMoveDelegate = function(event) {
442   - return self._mouseMove(event);
443   - };
444   - this._mouseUpDelegate = function(event) {
445   - return self._mouseUp(event);
446   - };
447   - $(document)
448   - .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
449   - .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
450   -
451   - // preventDefault() is used to prevent the selection of text here -
452   - // however, in Safari, this causes select boxes not to be selectable
453   - // anymore, so this fix is needed
454   - ($.browser.safari || event.preventDefault());
455   -
456   - event.originalEvent.mouseHandled = true;
457   - return true;
458   - },
459   -
460   - _mouseMove: function(event) {
461   - // IE mouseup check - mouseup happened when mouse was out of window
462   - if ($.browser.msie && !event.button) {
463   - return this._mouseUp(event);
464   - }
465   -
466   - if (this._mouseStarted) {
467   - this._mouseDrag(event);
468   - return event.preventDefault();
469   - }
470   -
471   - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
472   - this._mouseStarted =
473   - (this._mouseStart(this._mouseDownEvent, event) !== false);
474   - (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
475   - }
476   -
477   - return !this._mouseStarted;
478   - },
479   -
480   - _mouseUp: function(event) {
481   - $(document)
482   - .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
483   - .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
484   -
485   - if (this._mouseStarted) {
486   - this._mouseStarted = false;
487   - this._preventClickEvent = (event.target == this._mouseDownEvent.target);
488   - this._mouseStop(event);
489   - }
490   -
491   - return false;
492   - },
493   -
494   - _mouseDistanceMet: function(event) {
495   - return (Math.max(
496   - Math.abs(this._mouseDownEvent.pageX - event.pageX),
497   - Math.abs(this._mouseDownEvent.pageY - event.pageY)
498   - ) >= this.options.distance
499   - );
500   - },
501   -
502   - _mouseDelayMet: function(event) {
503   - return this.mouseDelayMet;
504   - },
505   -
506   - // These are placeholder methods, to be overriden by extending plugin
507   - _mouseStart: function(event) {},
508   - _mouseDrag: function(event) {},
509   - _mouseStop: function(event) {},
510   - _mouseCapture: function(event) { return true; }
511   -};
512   -
513   -$.ui.mouse.defaults = {
514   - cancel: null,
515   - distance: 1,
516   - delay: 0
517   -};
  10 +;
  11 +jQuery.ui || (function($) {
  12 +
  13 + var _remove = $.fn.remove,
  14 + isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
  15 +
  16 + //Helper functions and ui object
  17 + $.ui = {
  18 + version: "1.7.2",
  19 +
  20 + // $.ui.plugin is deprecated. Use the proxy pattern instead.
  21 + plugin: {
  22 + add: function(module, option, set) {
  23 + var proto = $.ui[module].prototype;
  24 + for (var i in set) {
  25 + proto.plugins[i] = proto.plugins[i] || [];
  26 + proto.plugins[i].push([option, set[i]]);
  27 + }
  28 + },
  29 + call: function(instance, name, args) {
  30 + var set = instance.plugins[name];
  31 + if (!set || !instance.element[0].parentNode) {
  32 + return;
  33 + }
  34 +
  35 + for (var i = 0; i < set.length; i++) {
  36 + if (instance.options[set[i][0]]) {
  37 + set[i][1].apply(instance.element, args);
  38 + }
  39 + }
  40 + }
  41 + },
  42 +
  43 + contains: function(a, b) {
  44 + return document.compareDocumentPosition
  45 + ? a.compareDocumentPosition(b) & 16
  46 + : a !== b && a.contains(b);
  47 + },
  48 +
  49 + hasScroll: function(el, a) {
  50 +
  51 + //If overflow is hidden, the element might have extra content, but the user wants to hide it
  52 + if ($(el).css('overflow') == 'hidden') {
  53 + return false;
  54 + }
  55 +
  56 + var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
  57 + has = false;
  58 +
  59 + if (el[scroll] > 0) {
  60 + return true;
  61 + }
  62 +
  63 + // TODO: determine which cases actually cause this to happen
  64 + // if the element doesn't have the scroll set, see if it's possible to
  65 + // set the scroll
  66 + el[scroll] = 1;
  67 + has = (el[scroll] > 0);
  68 + el[scroll] = 0;
  69 + return has;
  70 + },
  71 +
  72 + isOverAxis: function(x, reference, size) {
  73 + //Determines when x coordinate is over "b" element axis
  74 + return (x > reference) && (x < (reference + size));
  75 + },
  76 +
  77 + isOver: function(y, x, top, left, height, width) {
  78 + //Determines when x, y coordinates is over "b" element
  79 + return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
  80 + },
  81 +
  82 + keyCode: {
  83 + BACKSPACE: 8,
  84 + CAPS_LOCK: 20,
  85 + COMMA: 188,
  86 + CONTROL: 17,
  87 + DELETE: 46,
  88 + DOWN: 40,
  89 + END: 35,
  90 + ENTER: 13,
  91 + ESCAPE: 27,
  92 + HOME: 36,
  93 + INSERT: 45,
  94 + LEFT: 37,
  95 + NUMPAD_ADD: 107,
  96 + NUMPAD_DECIMAL: 110,
  97 + NUMPAD_DIVIDE: 111,
  98 + NUMPAD_ENTER: 108,
  99 + NUMPAD_MULTIPLY: 106,
  100 + NUMPAD_SUBTRACT: 109,
  101 + PAGE_DOWN: 34,
  102 + PAGE_UP: 33,
  103 + PERIOD: 190,
  104 + RIGHT: 39,
  105 + SHIFT: 16,
  106 + SPACE: 32,
  107 + TAB: 9,
  108 + UP: 38
  109 + }
  110 + };
  111 +
  112 + // WAI-ARIA normalization
  113 + if (isFF2) {
  114 + var attr = $.attr,
  115 + removeAttr = $.fn.removeAttr,
  116 + ariaNS = "http://www.w3.org/2005/07/aaa",
  117 + ariaState = /^aria-/,
  118 + ariaRole = /^wairole:/;
  119 +
  120 + $.attr = function(elem, name, value) {
  121 + var set = value !== undefined;
  122 +
  123 + return (name == 'role'
  124 + ? (set
  125 + ? attr.call(this, elem, name, "wairole:" + value)
  126 + : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
  127 + : (ariaState.test(name)
  128 + ? (set
  129 + ? elem.setAttributeNS(ariaNS,
  130 + name.replace(ariaState, "aaa:"), value)
  131 + : attr.call(this, elem, name.replace(ariaState, "aaa:")))
  132 + : attr.apply(this, arguments)));
  133 + };
  134 +
  135 + $.fn.removeAttr = function(name) {
  136 + return (ariaState.test(name)
  137 + ? this.each(function() {
  138 + this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
  139 + }) : removeAttr.call(this, name));
  140 + };
  141 + }
  142 +
  143 + //jQuery plugins
  144 + $.fn.extend({
  145 + remove: function() {
  146 + // Safari has a native remove event which actually removes DOM elements,
  147 + // so we have to use triggerHandler instead of trigger (#3037).
  148 + $("*", this).add(this).each(function() {
  149 + $(this).triggerHandler("remove");
  150 + });
  151 + return _remove.apply(this, arguments);
  152 + },
  153 +
  154 + enableSelection: function() {
  155 + return this
  156 + .attr('unselectable', 'off')
  157 + .css('MozUserSelect', '')
  158 + .unbind('selectstart.ui');
  159 + },
  160 +
  161 + disableSelection: function() {
  162 + return this
  163 + .attr('unselectable', 'on')
  164 + .css('MozUserSelect', 'none')
  165 + .bind('selectstart.ui', function() {
  166 + return false;
  167 + });
  168 + },
  169 +
  170 + scrollParent: function() {
  171 + var scrollParent;
  172 + if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
  173 + scrollParent = this.parents().filter(function() {
  174 + 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));
  175 + }).eq(0);
  176 + } else {
  177 + scrollParent = this.parents().filter(function() {
  178 + return (/(auto|scroll)/).test($.curCSS(this, 'overflow', 1) + $.curCSS(this, 'overflow-y', 1) + $.curCSS(this, 'overflow-x', 1));
  179 + }).eq(0);
  180 + }
  181 +
  182 + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
  183 + }
  184 + });
  185 +
  186 +
  187 + //Additional selectors
  188 + $.extend($.expr[':'], {
  189 + data: function(elem, i, match) {
  190 + return !!$.data(elem, match[3]);
  191 + },
  192 +
  193 + focusable: function(element) {
  194 + var nodeName = element.nodeName.toLowerCase(),
  195 + tabIndex = $.attr(element, 'tabindex');
  196 + return (/input|select|textarea|button|object/.test(nodeName)
  197 + ? !element.disabled
  198 + : 'a' == nodeName || 'area' == nodeName
  199 + ? element.href || !isNaN(tabIndex)
  200 + : !isNaN(tabIndex))
  201 + // the element and all of its ancestors must be visible
  202 + // the browser may report that the area is hidden
  203 + && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
  204 + },
  205 +
  206 + tabbable: function(element) {
  207 + var tabIndex = $.attr(element, 'tabindex');
  208 + return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
  209 + }
  210 + });
  211 +
  212 +
  213 + // $.widget is a factory to create jQuery plugins
  214 + // taking some boilerplate code out of the plugin code
  215 + function getter(namespace, plugin, method, args) {
  216 + function getMethods(type) {
  217 + var methods = $[namespace][plugin][type] || [];
  218 + return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
  219 + }
  220 +
  221 + var methods = getMethods('getter');
  222 + if (args.length == 1 && typeof args[0] == 'string') {
  223 + methods = methods.concat(getMethods('getterSetter'));
  224 + }
  225 + return ($.inArray(method, methods) != -1);
  226 + }
  227 +
  228 + $.widget = function(name, prototype) {
  229 + var namespace = name.split(".")[0];
  230 + name = name.split(".")[1];
  231 +
  232 + // create plugin method
  233 + $.fn[name] = function(options) {
  234 + var isMethodCall = (typeof options == 'string'),
  235 + args = Array.prototype.slice.call(arguments, 1);
  236 +
  237 + // prevent calls to internal methods
  238 + if (isMethodCall && options.substring(0, 1) == '_') {
  239 + return this;
  240 + }
  241 +
  242 + // handle getter methods
  243 + if (isMethodCall && getter(namespace, name, options, args)) {
  244 + var instance = $.data(this[0], name);
  245 + return (instance ? instance[options].apply(instance, args)
  246 + : undefined);
  247 + }
  248 +
  249 + // handle initialization and non-getter methods
  250 + return this.each(function() {
  251 + var instance = $.data(this, name);
  252 +
  253 + // constructor
  254 + (!instance && !isMethodCall &&
  255 + $.data(this, name, new $[namespace][name](this, options))._init());
  256 +
  257 + // method call
  258 + (instance && isMethodCall && $.isFunction(instance[options]) &&
  259 + instance[options].apply(instance, args));
  260 + });
  261 + };
  262 +
  263 + // create widget constructor
  264 + $[namespace] = $[namespace] || {};
  265 + $[namespace][name] = function(element, options) {
  266 + var self = this;
  267 +
  268 + this.namespace = namespace;
  269 + this.widgetName = name;
  270 + this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
  271 + this.widgetBaseClass = namespace + '-' + name;
  272 +
  273 + this.options = $.extend({},
  274 + $.widget.defaults,
  275 + $[namespace][name].defaults,
  276 + $.metadata && $.metadata.get(element)[name],
  277 + options);
  278 +
  279 + this.element = $(element)
  280 + .bind('setData.' + name, function(event, key, value) {
  281 + if (event.target == element) {
  282 + return self._setData(key, value);
  283 + }
  284 + })
  285 + .bind('getData.' + name, function(event, key) {
  286 + if (event.target == element) {
  287 + return self._getData(key);
  288 + }
  289 + })
  290 + .bind('remove', function() {
  291 + return self.destroy();
  292 + });
  293 + };
  294 +
  295 + // add widget prototype
  296 + $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
  297 +
  298 + // TODO: merge getter and getterSetter properties from widget prototype
  299 + // and plugin prototype
  300 + $[namespace][name].getterSetter = 'option';
  301 + };
  302 +
  303 + $.widget.prototype = {
  304 + _init: function() {
  305 + },
  306 + destroy: function() {
  307 + this.element.removeData(this.widgetName)
  308 + .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
  309 + .removeAttr('aria-disabled');
  310 + },
  311 +
  312 + option: function(key, value) {
  313 + var options = key,
  314 + self = this;
  315 +
  316 + if (typeof key == "string") {
  317 + if (value === undefined) {
  318 + return this._getData(key);
  319 + }
  320 + options = {};
  321 + options[key] = value;
  322 + }
  323 +
  324 + $.each(options, function(key, value) {
  325 + self._setData(key, value);
  326 + });
  327 + },
  328 + _getData: function(key) {
  329 + return this.options[key];
  330 + },
  331 + _setData: function(key, value) {
  332 + this.options[key] = value;
  333 +
  334 + if (key == 'disabled') {
  335 + this.element
  336 + [value ? 'addClass' : 'removeClass'](
  337 + this.widgetBaseClass + '-disabled' + ' ' +
  338 + this.namespace + '-state-disabled')
  339 + .attr("aria-disabled", value);
  340 + }
  341 + },
  342 +
  343 + enable: function() {
  344 + this._setData('disabled', false);
  345 + },
  346 + disable: function() {
  347 + this._setData('disabled', true);
  348 + },
  349 +
  350 + _trigger: function(type, event, data) {
  351 + var callback = this.options[type],
  352 + eventName = (type == this.widgetEventPrefix
  353 + ? type : this.widgetEventPrefix + type);
  354 +
  355 + event = $.Event(event);
  356 + event.type = eventName;
  357 +
  358 + // copy original event properties over to the new event
  359 + // this would happen if we could call $.event.fix instead of $.Event
  360 + // but we don't have a way to force an event to be fixed multiple times
  361 + if (event.originalEvent) {
  362 + for (var i = $.event.props.length, prop; i;) {
  363 + prop = $.event.props[--i];
  364 + event[prop] = event.originalEvent[prop];
  365 + }
  366 + }
  367 +
  368 + this.element.trigger(event, data);
  369 +
  370 + return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
  371 + || event.isDefaultPrevented());
  372 + }
  373 + };
  374 +
  375 + $.widget.defaults = {
  376 + disabled: false
  377 + };
  378 +
  379 +
  380 + /** Mouse Interaction Plugin **/
  381 +
  382 + $.ui.mouse = {
  383 + _mouseInit: function() {
  384 + var self = this;
  385 +
  386 + this.element
  387 + .bind('mousedown.' + this.widgetName, function(event) {
  388 + return self._mouseDown(event);
  389 + })
  390 + .bind('click.' + this.widgetName, function(event) {
  391 + if (self._preventClickEvent) {
  392 + self._preventClickEvent = false;
  393 + event.stopImmediatePropagation();
  394 + return false;
  395 + }
  396 + });
  397 +
  398 + // Prevent text selection in IE
  399 + if ($.browser.msie) {
  400 + this._mouseUnselectable = this.element.attr('unselectable');
  401 + this.element.attr('unselectable', 'on');
  402 + }
  403 +
  404 + this.started = false;
  405 + },
  406 +
  407 + // TODO: make sure destroying one instance of mouse doesn't mess with
  408 + // other instances of mouse
  409 + _mouseDestroy: function() {
  410 + this.element.unbind('.' + this.widgetName);
  411 +
  412 + // Restore text selection in IE
  413 + ($.browser.msie
  414 + && this.element.attr('unselectable', this._mouseUnselectable));
  415 + },
  416 +
  417 + _mouseDown: function(event) {
  418 + // don't let more than one widget handle mouseStart
  419 + // TODO: figure out why we have to use originalEvent
  420 + event.originalEvent = event.originalEvent || {};
  421 + if (event.originalEvent.mouseHandled) {
  422 + return;
  423 + }
  424 +
  425 + // we may have missed mouseup (out of window)
  426 + (this._mouseStarted && this._mouseUp(event));
  427 +
  428 + this._mouseDownEvent = event;
  429 +
  430 + var self = this,
  431 + btnIsLeft = (event.which == 1),
  432 + elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
  433 + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
  434 + return true;
  435 + }
  436 +
  437 + this.mouseDelayMet = !this.options.delay;
  438 + if (!this.mouseDelayMet) {
  439 + this._mouseDelayTimer = setTimeout(function() {
  440 + self.mouseDelayMet = true;
  441 + }, this.options.delay);
  442 + }
  443 +
  444 + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
  445 + this._mouseStarted = (this._mouseStart(event) !== false);
  446 + if (!this._mouseStarted) {
  447 + event.preventDefault();
  448 + return true;
  449 + }
  450 + }
  451 +
  452 + // these delegates are required to keep context
  453 + this._mouseMoveDelegate = function(event) {
  454 + return self._mouseMove(event);
  455 + };
  456 + this._mouseUpDelegate = function(event) {
  457 + return self._mouseUp(event);
  458 + };
  459 + $(document)
  460 + .bind('mousemove.' + this.widgetName, this._mouseMoveDelegate)
  461 + .bind('mouseup.' + this.widgetName, this._mouseUpDelegate);
  462 +
  463 + // preventDefault() is used to prevent the selection of text here -
  464 + // however, in Safari, this causes select boxes not to be selectable
  465 + // anymore, so this fix is needed
  466 + ($.browser.safari || event.preventDefault());
  467 +
  468 + event.originalEvent.mouseHandled = true;
  469 + return true;
  470 + },
  471 +
  472 + _mouseMove: function(event) {
  473 + // IE mouseup check - mouseup happened when mouse was out of window
  474 + if ($.browser.msie && !event.button) {
  475 + return this._mouseUp(event);
  476 + }
  477 +
  478 + if (this._mouseStarted) {
  479 + this._mouseDrag(event);
  480 + return event.preventDefault();
  481 + }
  482 +
  483 + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
  484 + this._mouseStarted =
  485 + (this._mouseStart(this._mouseDownEvent, event) !== false);
  486 + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
  487 + }
  488 +
  489 + return !this._mouseStarted;
  490 + },
  491 +
  492 + _mouseUp: function(event) {
  493 + $(document)
  494 + .unbind('mousemove.' + this.widgetName, this._mouseMoveDelegate)
  495 + .unbind('mouseup.' + this.widgetName, this._mouseUpDelegate);
  496 +
  497 + if (this._mouseStarted) {
  498 + this._mouseStarted = false;
  499 + this._preventClickEvent = (event.target == this._mouseDownEvent.target);
  500 + this._mouseStop(event);
  501 + }
  502 +
  503 + return false;
  504 + },
  505 +
  506 + _mouseDistanceMet: function(event) {
  507 + return (Math.max(
  508 + Math.abs(this._mouseDownEvent.pageX - event.pageX),
  509 + Math.abs(this._mouseDownEvent.pageY - event.pageY)
  510 + ) >= this.options.distance
  511 + );
  512 + },
  513 +
  514 + _mouseDelayMet: function(event) {
  515 + return this.mouseDelayMet;
  516 + },
  517 +
  518 + // These are placeholder methods, to be overriden by extending plugin
  519 + _mouseStart: function(event) {
  520 + },
  521 + _mouseDrag: function(event) {
  522 + },
  523 + _mouseStop: function(event) {
  524 + },
  525 + _mouseCapture: function(event) {
  526 + return true;
  527 + }
  528 + };
  529 +
  530 + $.ui.mouse.defaults = {
  531 + cancel: null,
  532 + distance: 1,
  533 + delay: 0
  534 + };
518 535
519 536 })(jQuery);
... ...
... ... @@ -12,755 +12,763 @@
12 12 */
13 13 (function($) {
14 14
15   -$.widget("ui.draggable", $.extend({}, $.ui.mouse, {
  15 + $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
16 16
17   - _init: function() {
  17 + _init: function() {
18 18
19   - if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
20   - this.element[0].style.position = 'relative';
  19 + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
  20 + this.element[0].style.position = 'relative';
21 21
22   - (this.options.addClasses && this.element.addClass("ui-draggable"));
23   - (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
  22 + (this.options.addClasses && this.element.addClass("ui-draggable"));
  23 + (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
24 24
25   - this._mouseInit();
  25 + this._mouseInit();
26 26
27   - },
  27 + },
28 28
29   - destroy: function() {
30   - if(!this.element.data('draggable')) return;
31   - this.element
32   - .removeData("draggable")
33   - .unbind(".draggable")
34   - .removeClass("ui-draggable"
35   - + " ui-draggable-dragging"
36   - + " ui-draggable-disabled");
37   - this._mouseDestroy();
38   - },
  29 + destroy: function() {
  30 + if (!this.element.data('draggable')) return;
  31 + this.element
  32 + .removeData("draggable")
  33 + .unbind(".draggable")
  34 + .removeClass("ui-draggable"
  35 + + " ui-draggable-dragging"
  36 + + " ui-draggable-disabled");
  37 + this._mouseDestroy();
  38 + },
39 39
40   - _mouseCapture: function(event) {
  40 + _mouseCapture: function(event) {
41 41
42   - var o = this.options;
  42 + var o = this.options;
43 43
44   - if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
45   - return false;
  44 + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
  45 + return false;
46 46
47   - //Quit if we're not on a valid handle
48   - this.handle = this._getHandle(event);
49   - if (!this.handle)
50   - return false;
  47 + //Quit if we're not on a valid handle
  48 + this.handle = this._getHandle(event);
  49 + if (!this.handle)
  50 + return false;
51 51
52   - return true;
  52 + return true;
53 53
54   - },
  54 + },
55 55
56   - _mouseStart: function(event) {
  56 + _mouseStart: function(event) {
57 57
58   - var o = this.options;
  58 + var o = this.options;
59 59
60   - //Create and append the visible helper
61   - this.helper = this._createHelper(event);
  60 + //Create and append the visible helper
  61 + this.helper = this._createHelper(event);
62 62
63   - //Cache the helper size
64   - this._cacheHelperProportions();
  63 + //Cache the helper size
  64 + this._cacheHelperProportions();
65 65
66   - //If ddmanager is used for droppables, set the global draggable
67   - if($.ui.ddmanager)
68   - $.ui.ddmanager.current = this;
  66 + //If ddmanager is used for droppables, set the global draggable
  67 + if ($.ui.ddmanager)
  68 + $.ui.ddmanager.current = this;
69 69
70   - /*
71   - * - Position generation -
72   - * This block generates everything position related - it's the core of draggables.
73   - */
  70 + /*
  71 + * - Position generation -
  72 + * This block generates everything position related - it's the core of draggables.
  73 + */
74 74
75   - //Cache the margins of the original element
76   - this._cacheMargins();
  75 + //Cache the margins of the original element
  76 + this._cacheMargins();
77 77
78   - //Store the helper's css position
79   - this.cssPosition = this.helper.css("position");
80   - this.scrollParent = this.helper.scrollParent();
  78 + //Store the helper's css position
  79 + this.cssPosition = this.helper.css("position");
  80 + this.scrollParent = this.helper.scrollParent();
81 81
82   - //The element's absolute position on the page minus margins
83   - this.offset = this.element.offset();
84   - this.offset = {
85   - top: this.offset.top - this.margins.top,
86   - left: this.offset.left - this.margins.left
87   - };
  82 + //The element's absolute position on the page minus margins
  83 + this.offset = this.element.offset();
  84 + this.offset = {
  85 + top: this.offset.top - this.margins.top,
  86 + left: this.offset.left - this.margins.left
  87 + };
88 88
89   - $.extend(this.offset, {
90   - click: { //Where the click happened, relative to the element
91   - left: event.pageX - this.offset.left,
92   - top: event.pageY - this.offset.top
93   - },
94   - parent: this._getParentOffset(),
95   - relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
96   - });
  89 + $.extend(this.offset, {
  90 + click: { //Where the click happened, relative to the element
  91 + left: event.pageX - this.offset.left,
  92 + top: event.pageY - this.offset.top
  93 + },
  94 + parent: this._getParentOffset(),
  95 + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
  96 + });
97 97
98   - //Generate the original position
99   - this.originalPosition = this._generatePosition(event);
100   - this.originalPageX = event.pageX;
101   - this.originalPageY = event.pageY;
  98 + //Generate the original position
  99 + this.originalPosition = this._generatePosition(event);
  100 + this.originalPageX = event.pageX;
  101 + this.originalPageY = event.pageY;
102 102
103   - //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
104   - if(o.cursorAt)
105   - this._adjustOffsetFromHelper(o.cursorAt);
  103 + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
  104 + if (o.cursorAt)
  105 + this._adjustOffsetFromHelper(o.cursorAt);
106 106
107   - //Set a containment if given in the options
108   - if(o.containment)
109   - this._setContainment();
  107 + //Set a containment if given in the options
  108 + if (o.containment)
  109 + this._setContainment();
110 110
111   - //Call plugins and callbacks
112   - this._trigger("start", event);
  111 + //Call plugins and callbacks
  112 + this._trigger("start", event);
113 113
114   - //Recache the helper size
115   - this._cacheHelperProportions();
  114 + //Recache the helper size
  115 + this._cacheHelperProportions();
116 116
117   - //Prepare the droppable offsets
118   - if ($.ui.ddmanager && !o.dropBehaviour)
119   - $.ui.ddmanager.prepareOffsets(this, event);
  117 + //Prepare the droppable offsets
  118 + if ($.ui.ddmanager && !o.dropBehaviour)
  119 + $.ui.ddmanager.prepareOffsets(this, event);
120 120
121   - this.helper.addClass("ui-draggable-dragging");
122   - this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
123   - return true;
124   - },
  121 + this.helper.addClass("ui-draggable-dragging");
  122 + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
  123 + return true;
  124 + },
125 125
126   - _mouseDrag: function(event, noPropagation) {
  126 + _mouseDrag: function(event, noPropagation) {
127 127
128   - //Compute the helpers position
129   - this.position = this._generatePosition(event);
130   - this.positionAbs = this._convertPositionTo("absolute");
131   -
132   - //Call plugins and callbacks and use the resulting position if something is returned
133   - if (!noPropagation) {
134   - var ui = this._uiHash();
135   - this._trigger('drag', event, ui);
136   - this.position = ui.position;
137   - }
  128 + //Compute the helpers position
  129 + this.position = this._generatePosition(event);
  130 + this.positionAbs = this._convertPositionTo("absolute");
  131 +
  132 + //Call plugins and callbacks and use the resulting position if something is returned
  133 + if (!noPropagation) {
  134 + var ui = this._uiHash();
  135 + this._trigger('drag', event, ui);
  136 + this.position = ui.position;
  137 + }
138 138
139   - if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
140   - if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
141   - if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
  139 + if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left + 'px';
  140 + if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top + 'px';
  141 + if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
142 142
143   - return false;
144   - },
145   -
146   - _mouseStop: function(event) {
147   -
148   - //If we are using droppables, inform the manager about the drop
149   - var dropped = false;
150   - if ($.ui.ddmanager && !this.options.dropBehaviour)
151   - dropped = $.ui.ddmanager.drop(this, event);
152   -
153   - //if a drop comes from outside (a sortable)
154   - if(this.dropped) {
155   - dropped = this.dropped;
156   - this.dropped = false;
157   - }
158   -
159   - 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))) {
160   - var self = this;
161   - $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
162   - self._trigger("stop", event);
163   - self._clear();
164   - });
165   - } else {
166   - this._trigger("stop", event);
167   - this._clear();
168   - }
169   -
170   - return false;
171   - },
172   -
173   - _getHandle: function(event) {
174   -
175   - var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
176   - $(this.options.handle, this.element)
177   - .find("*")
178   - .andSelf()
179   - .each(function() {
180   - if(this == event.target) handle = true;
181   - });
182   -
183   - return handle;
184   -
185   - },
186   -
187   - _createHelper: function(event) {
188   -
189   - var o = this.options;
190   - var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
191   -
192   - if(!helper.parents('body').length)
193   - helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
194   -
195   - if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
196   - helper.css("position", "absolute");
197   -
198   - return helper;
199   -
200   - },
201   -
202   - _adjustOffsetFromHelper: function(obj) {
203   - if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
204   - if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
205   - if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
206   - if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
207   - },
208   -
209   - _getParentOffset: function() {
210   -
211   - //Get the offsetParent and cache its position
212   - this.offsetParent = this.helper.offsetParent();
213   - var po = this.offsetParent.offset();
214   -
215   - // This is a special case where we need to modify a offset calculated on start, since the following happened:
216   - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
217   - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
218   - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
219   - if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
220   - po.left += this.scrollParent.scrollLeft();
221   - po.top += this.scrollParent.scrollTop();
222   - }
223   -
224   - if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
225   - || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
226   - po = { top: 0, left: 0 };
227   -
228   - return {
229   - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
230   - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
231   - };
232   -
233   - },
234   -
235   - _getRelativeOffset: function() {
236   -
237   - if(this.cssPosition == "relative") {
238   - var p = this.element.position();
239   - return {
240   - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
241   - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
242   - };
243   - } else {
244   - return { top: 0, left: 0 };
245   - }
246   -
247   - },
248   -
249   - _cacheMargins: function() {
250   - this.margins = {
251   - left: (parseInt(this.element.css("marginLeft"),10) || 0),
252   - top: (parseInt(this.element.css("marginTop"),10) || 0)
253   - };
254   - },
255   -
256   - _cacheHelperProportions: function() {
257   - this.helperProportions = {
258   - width: this.helper.outerWidth(),
259   - height: this.helper.outerHeight()
260   - };
261   - },
262   -
263   - _setContainment: function() {
264   -
265   - var o = this.options;
266   - if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
267   - if(o.containment == 'document' || o.containment == 'window') this.containment = [
268   - 0 - this.offset.relative.left - this.offset.parent.left,
269   - 0 - this.offset.relative.top - this.offset.parent.top,
270   - $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
271   - ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
272   - ];
273   -
274   - if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
275   - var ce = $(o.containment)[0]; if(!ce) return;
276   - var co = $(o.containment).offset();
277   - var over = ($(ce).css("overflow") != 'hidden');
278   -
279   - this.containment = [
280   - co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
281   - co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
282   - 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,
283   - 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
284   - ];
285   - } else if(o.containment.constructor == Array) {
286   - this.containment = o.containment;
287   - }
288   -
289   - },
290   -
291   - _convertPositionTo: function(d, pos) {
292   -
293   - if(!pos) pos = this.position;
294   - var mod = d == "absolute" ? 1 : -1;
295   - 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);
296   -
297   - return {
298   - top: (
299   - pos.top // The absolute mouse position
300   - + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
301   - + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
302   - - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
303   - ),
304   - left: (
305   - pos.left // The absolute mouse position
306   - + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
307   - + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
308   - - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
309   - )
310   - };
311   -
312   - },
313   -
314   - _generatePosition: function(event) {
315   -
316   - 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);
317   -
318   - // This is another very weird special case that only happens for relative elements:
319   - // 1. If the css position is relative
320   - // 2. and the scroll parent is the document or similar to the offset parent
321   - // we have to refresh the relative offset during the scroll so there are no jumps
322   - if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
323   - this.offset.relative = this._getRelativeOffset();
324   - }
325   -
326   - var pageX = event.pageX;
327   - var pageY = event.pageY;
328   -
329   - /*
330   - * - Position constraining -
331   - * Constrain the position to a mix of grid, containment.
332   - */
333   -
334   - if(this.originalPosition) { //If we are not dragging yet, we won't check for options
335   -
336   - if(this.containment) {
337   - if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
338   - if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
339   - if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
340   - if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
341   - }
342   -
343   - if(o.grid) {
344   - var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
345   - 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;
346   -
347   - var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
348   - 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;
349   - }
350   -
351   - }
352   -
353   - return {
354   - top: (
355   - pageY // The absolute mouse position
356   - - this.offset.click.top // Click offset (relative to the element)
357   - - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
358   - - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
359   - + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
360   - ),
361   - left: (
362   - pageX // The absolute mouse position
363   - - this.offset.click.left // Click offset (relative to the element)
364   - - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
365   - - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
366   - + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
367   - )
368   - };
369   -
370   - },
371   -
372   - _clear: function() {
373   - this.helper.removeClass("ui-draggable-dragging");
374   - if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
375   - //if($.ui.ddmanager) $.ui.ddmanager.current = null;
376   - this.helper = null;
377   - this.cancelHelperRemoval = false;
378   - },
379   -
380   - // From now on bulk stuff - mainly helpers
381   -
382   - _trigger: function(type, event, ui) {
383   - ui = ui || this._uiHash();
384   - $.ui.plugin.call(this, type, [event, ui]);
385   - if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
386   - return $.widget.prototype._trigger.call(this, type, event, ui);
387   - },
388   -
389   - plugins: {},
390   -
391   - _uiHash: function(event) {
392   - return {
393   - helper: this.helper,
394   - position: this.position,
395   - absolutePosition: this.positionAbs, //deprecated
396   - offset: this.positionAbs
397   - };
398   - }
399   -
400   -}));
401   -
402   -$.extend($.ui.draggable, {
403   - version: "1.7.2",
404   - eventPrefix: "drag",
405   - defaults: {
406   - addClasses: true,
407   - appendTo: "parent",
408   - axis: false,
409   - cancel: ":input,option",
410   - connectToSortable: false,
411   - containment: false,
412   - cursor: "auto",
413   - cursorAt: false,
414   - delay: 0,
415   - distance: 1,
416   - grid: false,
417   - handle: false,
418   - helper: "original",
419   - iframeFix: false,
420   - opacity: false,
421   - refreshPositions: false,
422   - revert: false,
423   - revertDuration: 500,
424   - scope: "default",
425   - scroll: true,
426   - scrollSensitivity: 20,
427   - scrollSpeed: 20,
428   - snap: false,
429   - snapMode: "both",
430   - snapTolerance: 20,
431   - stack: false,
432   - zIndex: false
433   - }
434   -});
435   -
436   -$.ui.plugin.add("draggable", "connectToSortable", {
437   - start: function(event, ui) {
438   -
439   - var inst = $(this).data("draggable"), o = inst.options,
440   - uiSortable = $.extend({}, ui, { item: inst.element });
441   - inst.sortables = [];
442   - $(o.connectToSortable).each(function() {
443   - var sortable = $.data(this, 'sortable');
444   - if (sortable && !sortable.options.disabled) {
445   - inst.sortables.push({
446   - instance: sortable,
447   - shouldRevert: sortable.options.revert
448   - });
449   - sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
450   - sortable._trigger("activate", event, uiSortable);
451   - }
452   - });
453   -
454   - },
455   - stop: function(event, ui) {
456   -
457   - //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
458   - var inst = $(this).data("draggable"),
459   - uiSortable = $.extend({}, ui, { item: inst.element });
460   -
461   - $.each(inst.sortables, function() {
462   - if(this.instance.isOver) {
463   -
464   - this.instance.isOver = 0;
465   -
466   - inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
467   - this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
468   -
469   - //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
470   - if(this.shouldRevert) this.instance.options.revert = true;
471   -
472   - //Trigger the stop of the sortable
473   - this.instance._mouseStop(event);
474   -
475   - this.instance.options.helper = this.instance.options._helper;
476   -
477   - //If the helper has been the original item, restore properties in the sortable
478   - if(inst.options.helper == 'original')
479   - this.instance.currentItem.css({ top: 'auto', left: 'auto' });
480   -
481   - } else {
482   - this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
483   - this.instance._trigger("deactivate", event, uiSortable);
484   - }
485   -
486   - });
487   -
488   - },
489   - drag: function(event, ui) {
490   -
491   - var inst = $(this).data("draggable"), self = this;
492   -
493   - var checkPos = function(o) {
494   - var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
495   - var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
496   - var itemHeight = o.height, itemWidth = o.width;
497   - var itemTop = o.top, itemLeft = o.left;
498   -
499   - return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
500   - };
501   -
502   - $.each(inst.sortables, function(i) {
503   -
504   - //Copy over some variables to allow calling the sortable's native _intersectsWith
505   - this.instance.positionAbs = inst.positionAbs;
506   - this.instance.helperProportions = inst.helperProportions;
507   - this.instance.offset.click = inst.offset.click;
508   -
509   - if(this.instance._intersectsWith(this.instance.containerCache)) {
510   -
511   - //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
512   - if(!this.instance.isOver) {
513   -
514   - this.instance.isOver = 1;
515   - //Now we fake the start of dragging for the sortable instance,
516   - //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
517   - //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)
518   - this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
519   - this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
520   - this.instance.options.helper = function() { return ui.helper[0]; };
521   -
522   - event.target = this.instance.currentItem[0];
523   - this.instance._mouseCapture(event, true);
524   - this.instance._mouseStart(event, true, true);
525   -
526   - //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
527   - this.instance.offset.click.top = inst.offset.click.top;
528   - this.instance.offset.click.left = inst.offset.click.left;
529   - this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
530   - this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
531   -
532   - inst._trigger("toSortable", event);
533   - inst.dropped = this.instance.element; //draggable revert needs that
534   - //hack so receive/update callbacks work (mostly)
535   - inst.currentItem = inst.element;
536   - this.instance.fromOutside = inst;
537   -
538   - }
539   -
540   - //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
541   - if(this.instance.currentItem) this.instance._mouseDrag(event);
542   -
543   - } else {
544   -
545   - //If it doesn't intersect with the sortable, and it intersected before,
546   - //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
547   - if(this.instance.isOver) {
548   -
549   - this.instance.isOver = 0;
550   - this.instance.cancelHelperRemoval = true;
551   -
552   - //Prevent reverting on this forced stop
553   - this.instance.options.revert = false;
554   -
555   - // The out event needs to be triggered independently
556   - this.instance._trigger('out', event, this.instance._uiHash(this.instance));
557   -
558   - this.instance._mouseStop(event, true);
559   - this.instance.options.helper = this.instance.options._helper;
560   -
561   - //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
562   - this.instance.currentItem.remove();
563   - if(this.instance.placeholder) this.instance.placeholder.remove();
564   -
565   - inst._trigger("fromSortable", event);
566   - inst.dropped = false; //draggable revert needs that
567   - }
568   -
569   - };
570   -
571   - });
572   -
573   - }
574   -});
575   -
576   -$.ui.plugin.add("draggable", "cursor", {
577   - start: function(event, ui) {
578   - var t = $('body'), o = $(this).data('draggable').options;
579   - if (t.css("cursor")) o._cursor = t.css("cursor");
580   - t.css("cursor", o.cursor);
581   - },
582   - stop: function(event, ui) {
583   - var o = $(this).data('draggable').options;
584   - if (o._cursor) $('body').css("cursor", o._cursor);
585   - }
586   -});
587   -
588   -$.ui.plugin.add("draggable", "iframeFix", {
589   - start: function(event, ui) {
590   - var o = $(this).data('draggable').options;
591   - $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
592   - $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
593   - .css({
594   - width: this.offsetWidth+"px", height: this.offsetHeight+"px",
595   - position: "absolute", opacity: "0.001", zIndex: 1000
596   - })
597   - .css($(this).offset())
598   - .appendTo("body");
599   - });
600   - },
601   - stop: function(event, ui) {
602   - $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
603   - }
604   -});
605   -
606   -$.ui.plugin.add("draggable", "opacity", {
607   - start: function(event, ui) {
608   - var t = $(ui.helper), o = $(this).data('draggable').options;
609   - if(t.css("opacity")) o._opacity = t.css("opacity");
610   - t.css('opacity', o.opacity);
611   - },
612   - stop: function(event, ui) {
613   - var o = $(this).data('draggable').options;
614   - if(o._opacity) $(ui.helper).css('opacity', o._opacity);
615   - }
616   -});
617   -
618   -$.ui.plugin.add("draggable", "scroll", {
619   - start: function(event, ui) {
620   - var i = $(this).data("draggable");
621   - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
622   - },
623   - drag: function(event, ui) {
624   -
625   - var i = $(this).data("draggable"), o = i.options, scrolled = false;
626   -
627   - if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
628   -
629   - if(!o.axis || o.axis != 'x') {
630   - if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
631   - i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
632   - else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
633   - i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
634   - }
635   -
636   - if(!o.axis || o.axis != 'y') {
637   - if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
638   - i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
639   - else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
640   - i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
641   - }
642   -
643   - } else {
644   -
645   - if(!o.axis || o.axis != 'x') {
646   - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
647   - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
648   - else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
649   - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
650   - }
651   -
652   - if(!o.axis || o.axis != 'y') {
653   - if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
654   - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
655   - else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
656   - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
657   - }
658   -
659   - }
660   -
661   - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
662   - $.ui.ddmanager.prepareOffsets(i, event);
663   -
664   - }
665   -});
666   -
667   -$.ui.plugin.add("draggable", "snap", {
668   - start: function(event, ui) {
669   -
670   - var i = $(this).data("draggable"), o = i.options;
671   - i.snapElements = [];
672   -
673   - $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
674   - var $t = $(this); var $o = $t.offset();
675   - if(this != i.element[0]) i.snapElements.push({
676   - item: this,
677   - width: $t.outerWidth(), height: $t.outerHeight(),
678   - top: $o.top, left: $o.left
679   - });
680   - });
681   -
682   - },
683   - drag: function(event, ui) {
684   -
685   - var inst = $(this).data("draggable"), o = inst.options;
686   - var d = o.snapTolerance;
687   -
688   - var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
689   - y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
690   -
691   - for (var i = inst.snapElements.length - 1; i >= 0; i--){
692   -
693   - var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
694   - t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
695   -
696   - //Yes, I know, this is insane ;)
697   - 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))) {
698   - 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 })));
699   - inst.snapElements[i].snapping = false;
700   - continue;
701   - }
702   -
703   - if(o.snapMode != 'inner') {
704   - var ts = Math.abs(t - y2) <= d;
705   - var bs = Math.abs(b - y1) <= d;
706   - var ls = Math.abs(l - x2) <= d;
707   - var rs = Math.abs(r - x1) <= d;
708   - if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
709   - if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
710   - if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
711   - if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
712   - }
713   -
714   - var first = (ts || bs || ls || rs);
715   -
716   - if(o.snapMode != 'outer') {
717   - var ts = Math.abs(t - y1) <= d;
718   - var bs = Math.abs(b - y2) <= d;
719   - var ls = Math.abs(l - x1) <= d;
720   - var rs = Math.abs(r - x2) <= d;
721   - if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
722   - if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
723   - if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
724   - if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
725   - }
726   -
727   - if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
728   - (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
729   - inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
730   -
731   - };
732   -
733   - }
734   -});
735   -
736   -$.ui.plugin.add("draggable", "stack", {
737   - start: function(event, ui) {
738   -
739   - var o = $(this).data("draggable").options;
740   -
741   - var group = $.makeArray($(o.stack.group)).sort(function(a,b) {
742   - return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
743   - });
744   -
745   - $(group).each(function(i) {
746   - this.style.zIndex = o.stack.min + i;
747   - });
748   -
749   - this[0].style.zIndex = o.stack.min + group.length;
750   -
751   - }
752   -});
753   -
754   -$.ui.plugin.add("draggable", "zIndex", {
755   - start: function(event, ui) {
756   - var t = $(ui.helper), o = $(this).data("draggable").options;
757   - if(t.css("zIndex")) o._zIndex = t.css("zIndex");
758   - t.css('zIndex', o.zIndex);
759   - },
760   - stop: function(event, ui) {
761   - var o = $(this).data("draggable").options;
762   - if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
763   - }
764   -});
  143 + return false;
  144 + },
  145 +
  146 + _mouseStop: function(event) {
  147 +
  148 + //If we are using droppables, inform the manager about the drop
  149 + var dropped = false;
  150 + if ($.ui.ddmanager && !this.options.dropBehaviour)
  151 + dropped = $.ui.ddmanager.drop(this, event);
  152 +
  153 + //if a drop comes from outside (a sortable)
  154 + if (this.dropped) {
  155 + dropped = this.dropped;
  156 + this.dropped = false;
  157 + }
  158 +
  159 + 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))) {
  160 + var self = this;
  161 + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
  162 + self._trigger("stop", event);
  163 + self._clear();
  164 + });
  165 + } else {
  166 + this._trigger("stop", event);
  167 + this._clear();
  168 + }
  169 +
  170 + return false;
  171 + },
  172 +
  173 + _getHandle: function(event) {
  174 +
  175 + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
  176 + $(this.options.handle, this.element)
  177 + .find("*")
  178 + .andSelf()
  179 + .each(function() {
  180 + if (this == event.target) handle = true;
  181 + });
  182 +
  183 + return handle;
  184 +
  185 + },
  186 +
  187 + _createHelper: function(event) {
  188 +
  189 + var o = this.options;
  190 + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
  191 +
  192 + if (!helper.parents('body').length)
  193 + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
  194 +
  195 + if (helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
  196 + helper.css("position", "absolute");
  197 +
  198 + return helper;
  199 +
  200 + },
  201 +
  202 + _adjustOffsetFromHelper: function(obj) {
  203 + if (obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
  204 + if (obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
  205 + if (obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
  206 + if (obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
  207 + },
  208 +
  209 + _getParentOffset: function() {
  210 +
  211 + //Get the offsetParent and cache its position
  212 + this.offsetParent = this.helper.offsetParent();
  213 + var po = this.offsetParent.offset();
  214 +
  215 + // This is a special case where we need to modify a offset calculated on start, since the following happened:
  216 + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
  217 + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
  218 + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
  219 + if (this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
  220 + po.left += this.scrollParent.scrollLeft();
  221 + po.top += this.scrollParent.scrollTop();
  222 + }
  223 +
  224 + if ((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
  225 + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
  226 + po = { top: 0, left: 0 };
  227 +
  228 + return {
  229 + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
  230 + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
  231 + };
  232 +
  233 + },
  234 +
  235 + _getRelativeOffset: function() {
  236 +
  237 + if (this.cssPosition == "relative") {
  238 + var p = this.element.position();
  239 + return {
  240 + top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(),
  241 + left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()
  242 + };
  243 + } else {
  244 + return { top: 0, left: 0 };
  245 + }
  246 +
  247 + },
  248 +
  249 + _cacheMargins: function() {
  250 + this.margins = {
  251 + left: (parseInt(this.element.css("marginLeft"), 10) || 0),
  252 + top: (parseInt(this.element.css("marginTop"), 10) || 0)
  253 + };
  254 + },
  255 +
  256 + _cacheHelperProportions: function() {
  257 + this.helperProportions = {
  258 + width: this.helper.outerWidth(),
  259 + height: this.helper.outerHeight()
  260 + };
  261 + },
  262 +
  263 + _setContainment: function() {
  264 +
  265 + var o = this.options;
  266 + if (o.containment == 'parent') o.containment = this.helper[0].parentNode;
  267 + if (o.containment == 'document' || o.containment == 'window') this.containment = [
  268 + 0 - this.offset.relative.left - this.offset.parent.left,
  269 + 0 - this.offset.relative.top - this.offset.parent.top,
  270 + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
  271 + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
  272 + ];
  273 +
  274 + if (!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
  275 + var ce = $(o.containment)[0];
  276 + if (!ce) return;
  277 + var co = $(o.containment).offset();
  278 + var over = ($(ce).css("overflow") != 'hidden');
  279 +
  280 + this.containment = [
  281 + co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left,
  282 + co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top,
  283 + 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,
  284 + 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
  285 + ];
  286 + } else if (o.containment.constructor == Array) {
  287 + this.containment = o.containment;
  288 + }
  289 +
  290 + },
  291 +
  292 + _convertPositionTo: function(d, pos) {
  293 +
  294 + if (!pos) pos = this.position;
  295 + var mod = d == "absolute" ? 1 : -1;
  296 + 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);
  297 +
  298 + return {
  299 + top: (
  300 + pos.top // The absolute mouse position
  301 + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
  302 + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
  303 + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
  304 + ),
  305 + left: (
  306 + pos.left // The absolute mouse position
  307 + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
  308 + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
  309 + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
  310 + )
  311 + };
  312 +
  313 + },
  314 +
  315 + _generatePosition: function(event) {
  316 +
  317 + 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);
  318 +
  319 + // This is another very weird special case that only happens for relative elements:
  320 + // 1. If the css position is relative
  321 + // 2. and the scroll parent is the document or similar to the offset parent
  322 + // we have to refresh the relative offset during the scroll so there are no jumps
  323 + if (this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
  324 + this.offset.relative = this._getRelativeOffset();
  325 + }
  326 +
  327 + var pageX = event.pageX;
  328 + var pageY = event.pageY;
  329 +
  330 + /*
  331 + * - Position constraining -
  332 + * Constrain the position to a mix of grid, containment.
  333 + */
  334 +
  335 + if (this.originalPosition) { //If we are not dragging yet, we won't check for options
  336 +
  337 + if (this.containment) {
  338 + if (event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
  339 + if (event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
  340 + if (event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
  341 + if (event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
  342 + }
  343 +
  344 + if (o.grid) {
  345 + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
  346 + 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;
  347 +
  348 + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
  349 + 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;
  350 + }
  351 +
  352 + }
  353 +
  354 + return {
  355 + top: (
  356 + pageY // The absolute mouse position
  357 + - this.offset.click.top // Click offset (relative to the element)
  358 + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
  359 + - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
  360 + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
  361 + ),
  362 + left: (
  363 + pageX // The absolute mouse position
  364 + - this.offset.click.left // Click offset (relative to the element)
  365 + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
  366 + - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
  367 + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
  368 + )
  369 + };
  370 +
  371 + },
  372 +
  373 + _clear: function() {
  374 + this.helper.removeClass("ui-draggable-dragging");
  375 + if (this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
  376 + //if($.ui.ddmanager) $.ui.ddmanager.current = null;
  377 + this.helper = null;
  378 + this.cancelHelperRemoval = false;
  379 + },
  380 +
  381 + // From now on bulk stuff - mainly helpers
  382 +
  383 + _trigger: function(type, event, ui) {
  384 + ui = ui || this._uiHash();
  385 + $.ui.plugin.call(this, type, [event, ui]);
  386 + if (type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
  387 + return $.widget.prototype._trigger.call(this, type, event, ui);
  388 + },
  389 +
  390 + plugins: {},
  391 +
  392 + _uiHash: function(event) {
  393 + return {
  394 + helper: this.helper,
  395 + position: this.position,
  396 + absolutePosition: this.positionAbs, //deprecated
  397 + offset: this.positionAbs
  398 + };
  399 + }
  400 +
  401 + }));
  402 +
  403 + $.extend($.ui.draggable, {
  404 + version: "1.7.2",
  405 + eventPrefix: "drag",
  406 + defaults: {
  407 + addClasses: true,
  408 + appendTo: "parent",
  409 + axis: false,
  410 + cancel: ":input,option",
  411 + connectToSortable: false,
  412 + containment: false,
  413 + cursor: "auto",
  414 + cursorAt: false,
  415 + delay: 0,
  416 + distance: 1,
  417 + grid: false,
  418 + handle: false,
  419 + helper: "original",
  420 + iframeFix: false,
  421 + opacity: false,
  422 + refreshPositions: false,
  423 + revert: false,
  424 + revertDuration: 500,
  425 + scope: "default",
  426 + scroll: true,
  427 + scrollSensitivity: 20,
  428 + scrollSpeed: 20,
  429 + snap: false,
  430 + snapMode: "both",
  431 + snapTolerance: 20,
  432 + stack: false,
  433 + zIndex: false
  434 + }
  435 + });
  436 +
  437 + $.ui.plugin.add("draggable", "connectToSortable", {
  438 + start: function(event, ui) {
  439 +
  440 + var inst = $(this).data("draggable"), o = inst.options,
  441 + uiSortable = $.extend({}, ui, { item: inst.element });
  442 + inst.sortables = [];
  443 + $(o.connectToSortable).each(function() {
  444 + var sortable = $.data(this, 'sortable');
  445 + if (sortable && !sortable.options.disabled) {
  446 + inst.sortables.push({
  447 + instance: sortable,
  448 + shouldRevert: sortable.options.revert
  449 + });
  450 + sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
  451 + sortable._trigger("activate", event, uiSortable);
  452 + }
  453 + });
  454 +
  455 + },
  456 + stop: function(event, ui) {
  457 +
  458 + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
  459 + var inst = $(this).data("draggable"),
  460 + uiSortable = $.extend({}, ui, { item: inst.element });
  461 +
  462 + $.each(inst.sortables, function() {
  463 + if (this.instance.isOver) {
  464 +
  465 + this.instance.isOver = 0;
  466 +
  467 + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
  468 + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
  469 +
  470 + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
  471 + if (this.shouldRevert) this.instance.options.revert = true;
  472 +
  473 + //Trigger the stop of the sortable
  474 + this.instance._mouseStop(event);
  475 +
  476 + this.instance.options.helper = this.instance.options._helper;
  477 +
  478 + //If the helper has been the original item, restore properties in the sortable
  479 + if (inst.options.helper == 'original')
  480 + this.instance.currentItem.css({ top: 'auto', left: 'auto' });
  481 +
  482 + } else {
  483 + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
  484 + this.instance._trigger("deactivate", event, uiSortable);
  485 + }
  486 +
  487 + });
  488 +
  489 + },
  490 + drag: function(event, ui) {
  491 +
  492 + var inst = $(this).data("draggable"), self = this;
  493 +
  494 + var checkPos = function(o) {
  495 + var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
  496 + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
  497 + var itemHeight = o.height, itemWidth = o.width;
  498 + var itemTop = o.top, itemLeft = o.left;
  499 +
  500 + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
  501 + };
  502 +
  503 + $.each(inst.sortables, function(i) {
  504 +
  505 + //Copy over some variables to allow calling the sortable's native _intersectsWith
  506 + this.instance.positionAbs = inst.positionAbs;
  507 + this.instance.helperProportions = inst.helperProportions;
  508 + this.instance.offset.click = inst.offset.click;
  509 +
  510 + if (this.instance._intersectsWith(this.instance.containerCache)) {
  511 +
  512 + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
  513 + if (!this.instance.isOver) {
  514 +
  515 + this.instance.isOver = 1;
  516 + //Now we fake the start of dragging for the sortable instance,
  517 + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
  518 + //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)
  519 + this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
  520 + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
  521 + this.instance.options.helper = function() {
  522 + return ui.helper[0];
  523 + };
  524 +
  525 + event.target = this.instance.currentItem[0];
  526 + this.instance._mouseCapture(event, true);
  527 + this.instance._mouseStart(event, true, true);
  528 +
  529 + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
  530 + this.instance.offset.click.top = inst.offset.click.top;
  531 + this.instance.offset.click.left = inst.offset.click.left;
  532 + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
  533 + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
  534 +
  535 + inst._trigger("toSortable", event);
  536 + inst.dropped = this.instance.element; //draggable revert needs that
  537 + //hack so receive/update callbacks work (mostly)
  538 + inst.currentItem = inst.element;
  539 + this.instance.fromOutside = inst;
  540 +
  541 + }
  542 +
  543 + //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
  544 + if (this.instance.currentItem) this.instance._mouseDrag(event);
  545 +
  546 + } else {
  547 +
  548 + //If it doesn't intersect with the sortable, and it intersected before,
  549 + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
  550 + if (this.instance.isOver) {
  551 +
  552 + this.instance.isOver = 0;
  553 + this.instance.cancelHelperRemoval = true;
  554 +
  555 + //Prevent reverting on this forced stop
  556 + this.instance.options.revert = false;
  557 +
  558 + // The out event needs to be triggered independently
  559 + this.instance._trigger('out', event, this.instance._uiHash(this.instance));
  560 +
  561 + this.instance._mouseStop(event, true);
  562 + this.instance.options.helper = this.instance.options._helper;
  563 +
  564 + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
  565 + this.instance.currentItem.remove();
  566 + if (this.instance.placeholder) this.instance.placeholder.remove();
  567 +
  568 + inst._trigger("fromSortable", event);
  569 + inst.dropped = false; //draggable revert needs that
  570 + }
  571 +
  572 + }
  573 + ;
  574 +
  575 + });
  576 +
  577 + }
  578 + });
  579 +
  580 + $.ui.plugin.add("draggable", "cursor", {
  581 + start: function(event, ui) {
  582 + var t = $('body'), o = $(this).data('draggable').options;
  583 + if (t.css("cursor")) o._cursor = t.css("cursor");
  584 + t.css("cursor", o.cursor);
  585 + },
  586 + stop: function(event, ui) {
  587 + var o = $(this).data('draggable').options;
  588 + if (o._cursor) $('body').css("cursor", o._cursor);
  589 + }
  590 + });
  591 +
  592 + $.ui.plugin.add("draggable", "iframeFix", {
  593 + start: function(event, ui) {
  594 + var o = $(this).data('draggable').options;
  595 + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
  596 + $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
  597 + .css({
  598 + width: this.offsetWidth + "px", height: this.offsetHeight + "px",
  599 + position: "absolute", opacity: "0.001", zIndex: 1000
  600 + })
  601 + .css($(this).offset())
  602 + .appendTo("body");
  603 + });
  604 + },
  605 + stop: function(event, ui) {
  606 + $("div.ui-draggable-iframeFix").each(function() {
  607 + this.parentNode.removeChild(this);
  608 + }); //Remove frame helpers
  609 + }
  610 + });
  611 +
  612 + $.ui.plugin.add("draggable", "opacity", {
  613 + start: function(event, ui) {
  614 + var t = $(ui.helper), o = $(this).data('draggable').options;
  615 + if (t.css("opacity")) o._opacity = t.css("opacity");
  616 + t.css('opacity', o.opacity);
  617 + },
  618 + stop: function(event, ui) {
  619 + var o = $(this).data('draggable').options;
  620 + if (o._opacity) $(ui.helper).css('opacity', o._opacity);
  621 + }
  622 + });
  623 +
  624 + $.ui.plugin.add("draggable", "scroll", {
  625 + start: function(event, ui) {
  626 + var i = $(this).data("draggable");
  627 + if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
  628 + },
  629 + drag: function(event, ui) {
  630 +
  631 + var i = $(this).data("draggable"), o = i.options, scrolled = false;
  632 +
  633 + if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
  634 +
  635 + if (!o.axis || o.axis != 'x') {
  636 + if ((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
  637 + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
  638 + else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity)
  639 + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
  640 + }
  641 +
  642 + if (!o.axis || o.axis != 'y') {
  643 + if ((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
  644 + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
  645 + else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity)
  646 + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
  647 + }
  648 +
  649 + } else {
  650 +
  651 + if (!o.axis || o.axis != 'x') {
  652 + if (event.pageY - $(document).scrollTop() < o.scrollSensitivity)
  653 + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
  654 + else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
  655 + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
  656 + }
  657 +
  658 + if (!o.axis || o.axis != 'y') {
  659 + if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
  660 + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
  661 + else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
  662 + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
  663 + }
  664 +
  665 + }
  666 +
  667 + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
  668 + $.ui.ddmanager.prepareOffsets(i, event);
  669 +
  670 + }
  671 + });
  672 +
  673 + $.ui.plugin.add("draggable", "snap", {
  674 + start: function(event, ui) {
  675 +
  676 + var i = $(this).data("draggable"), o = i.options;
  677 + i.snapElements = [];
  678 +
  679 + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
  680 + var $t = $(this);
  681 + var $o = $t.offset();
  682 + if (this != i.element[0]) i.snapElements.push({
  683 + item: this,
  684 + width: $t.outerWidth(), height: $t.outerHeight(),
  685 + top: $o.top, left: $o.left
  686 + });
  687 + });
  688 +
  689 + },
  690 + drag: function(event, ui) {
  691 +
  692 + var inst = $(this).data("draggable"), o = inst.options;
  693 + var d = o.snapTolerance;
  694 +
  695 + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
  696 + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
  697 +
  698 + for (var i = inst.snapElements.length - 1; i >= 0; i--) {
  699 +
  700 + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
  701 + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
  702 +
  703 + //Yes, I know, this is insane ;)
  704 + 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))) {
  705 + 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 })));
  706 + inst.snapElements[i].snapping = false;
  707 + continue;
  708 + }
  709 +
  710 + if (o.snapMode != 'inner') {
  711 + var ts = Math.abs(t - y2) <= d;
  712 + var bs = Math.abs(b - y1) <= d;
  713 + var ls = Math.abs(l - x2) <= d;
  714 + var rs = Math.abs(r - x1) <= d;
  715 + if (ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
  716 + if (bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
  717 + if (ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
  718 + if (rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
  719 + }
  720 +
  721 + var first = (ts || bs || ls || rs);
  722 +
  723 + if (o.snapMode != 'outer') {
  724 + var ts = Math.abs(t - y1) <= d;
  725 + var bs = Math.abs(b - y2) <= d;
  726 + var ls = Math.abs(l - x1) <= d;
  727 + var rs = Math.abs(r - x2) <= d;
  728 + if (ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
  729 + if (bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
  730 + if (ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
  731 + if (rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
  732 + }
  733 +
  734 + if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
  735 + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
  736 + inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
  737 +
  738 + }
  739 + ;
  740 +
  741 + }
  742 + });
  743 +
  744 + $.ui.plugin.add("draggable", "stack", {
  745 + start: function(event, ui) {
  746 +
  747 + var o = $(this).data("draggable").options;
  748 +
  749 + var group = $.makeArray($(o.stack.group)).sort(function(a, b) {
  750 + return (parseInt($(a).css("zIndex"), 10) || o.stack.min) - (parseInt($(b).css("zIndex"), 10) || o.stack.min);
  751 + });
  752 +
  753 + $(group).each(function(i) {
  754 + this.style.zIndex = o.stack.min + i;
  755 + });
  756 +
  757 + this[0].style.zIndex = o.stack.min + group.length;
  758 +
  759 + }
  760 + });
  761 +
  762 + $.ui.plugin.add("draggable", "zIndex", {
  763 + start: function(event, ui) {
  764 + var t = $(ui.helper), o = $(this).data("draggable").options;
  765 + if (t.css("zIndex")) o._zIndex = t.css("zIndex");
  766 + t.css('zIndex', o.zIndex);
  767 + },
  768 + stop: function(event, ui) {
  769 + var o = $(this).data("draggable").options;
  770 + if (o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
  771 + }
  772 + });
765 773
766 774 })(jQuery);
... ...
... ... @@ -12,789 +12,803 @@
12 12 */
13 13 (function($) {
14 14
15   -$.widget("ui.resizable", $.extend({}, $.ui.mouse, {
  15 + $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
16 16
17   - _init: function() {
  17 + _init: function() {
18 18
19   - var self = this, o = this.options;
20   - this.element.addClass("ui-resizable");
  19 + var self = this, o = this.options;
  20 + this.element.addClass("ui-resizable");
21 21
22   - $.extend(this, {
23   - _aspectRatio: !!(o.aspectRatio),
24   - aspectRatio: o.aspectRatio,
25   - originalElement: this.element,
26   - _proportionallyResizeElements: [],
27   - _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
28   - });
  22 + $.extend(this, {
  23 + _aspectRatio: !!(o.aspectRatio),
  24 + aspectRatio: o.aspectRatio,
  25 + originalElement: this.element,
  26 + _proportionallyResizeElements: [],
  27 + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
  28 + });
29 29
30   - //Wrap the element if it cannot hold child nodes
31   - if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
  30 + //Wrap the element if it cannot hold child nodes
  31 + if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
32 32
33   - //Opera fix for relative positioning
34   - if (/relative/.test(this.element.css('position')) && $.browser.opera)
35   - this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
  33 + //Opera fix for relative positioning
  34 + if (/relative/.test(this.element.css('position')) && $.browser.opera)
  35 + this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
36 36
37   - //Create a wrapper element and set the wrapper to the new current internal element
38   - this.element.wrap(
39   - $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
40   - position: this.element.css('position'),
41   - width: this.element.outerWidth(),
42   - height: this.element.outerHeight(),
43   - top: this.element.css('top'),
44   - left: this.element.css('left')
45   - })
46   - );
  37 + //Create a wrapper element and set the wrapper to the new current internal element
  38 + this.element.wrap(
  39 + $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
  40 + position: this.element.css('position'),
  41 + width: this.element.outerWidth(),
  42 + height: this.element.outerHeight(),
  43 + top: this.element.css('top'),
  44 + left: this.element.css('left')
  45 + })
  46 + );
47 47
48   - //Overwrite the original this.element
49   - this.element = this.element.parent().data(
50   - "resizable", this.element.data('resizable')
51   - );
  48 + //Overwrite the original this.element
  49 + this.element = this.element.parent().data(
  50 + "resizable", this.element.data('resizable')
  51 + );
52 52
53   - this.elementIsWrapper = true;
  53 + this.elementIsWrapper = true;
54 54
55   - //Move margins to the wrapper
56   - this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
57   - this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
  55 + //Move margins to the wrapper
  56 + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
  57 + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
58 58
59   - //Prevent Safari textarea resize
60   - this.originalResizeStyle = this.originalElement.css('resize');
61   - this.originalElement.css('resize', 'none');
  59 + //Prevent Safari textarea resize
  60 + this.originalResizeStyle = this.originalElement.css('resize');
  61 + this.originalElement.css('resize', 'none');
62 62
63   - //Push the actual element to our proportionallyResize internal array
64   - this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
  63 + //Push the actual element to our proportionallyResize internal array
  64 + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
65 65
66   - // avoid IE jump (hard set the margin)
67   - this.originalElement.css({ margin: this.originalElement.css('margin') });
  66 + // avoid IE jump (hard set the margin)
  67 + this.originalElement.css({ margin: this.originalElement.css('margin') });
68 68
69   - // fix handlers offset
70   - this._proportionallyResize();
  69 + // fix handlers offset
  70 + this._proportionallyResize();
71 71
72   - }
  72 + }
73 73
74   - 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' });
75   - if(this.handles.constructor == String) {
  74 + 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' });
  75 + if (this.handles.constructor == String) {
76 76
77   - if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
78   - var n = this.handles.split(","); this.handles = {};
  77 + if (this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
  78 + var n = this.handles.split(",");
  79 + this.handles = {};
79 80
80   - for(var i = 0; i < n.length; i++) {
  81 + for (var i = 0; i < n.length; i++) {
81 82
82   - var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
83   - var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
  83 + var handle = $.trim(n[i]), hname = 'ui-resizable-' + handle;
  84 + var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
84 85
85   - // increase zIndex of sw, se, ne, nw axis
86   - //TODO : this modifies original option
87   - if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
  86 + // increase zIndex of sw, se, ne, nw axis
  87 + //TODO : this modifies original option
  88 + if (/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
88 89
89   - //TODO : What's going on here?
90   - if ('se' == handle) {
91   - axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
92   - };
  90 + //TODO : What's going on here?
  91 + if ('se' == handle) {
  92 + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
  93 + }
  94 + ;
93 95
94   - //Insert into internal handles object and append to element
95   - this.handles[handle] = '.ui-resizable-'+handle;
96   - this.element.append(axis);
97   - }
  96 + //Insert into internal handles object and append to element
  97 + this.handles[handle] = '.ui-resizable-' + handle;
  98 + this.element.append(axis);
  99 + }
98 100
99   - }
  101 + }
  102 +
  103 + this._renderAxis = function(target) {
100 104
101   - this._renderAxis = function(target) {
  105 + target = target || this.element;
102 106
103   - target = target || this.element;
  107 + for (var i in this.handles) {
104 108
105   - for(var i in this.handles) {
  109 + if (this.handles[i].constructor == String)
  110 + this.handles[i] = $(this.handles[i], this.element).show();
106 111
107   - if(this.handles[i].constructor == String)
108   - this.handles[i] = $(this.handles[i], this.element).show();
  112 + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
  113 + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
109 114
110   - //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
111   - if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
  115 + var axis = $(this.handles[i], this.element), padWrapper = 0;
112 116
113   - var axis = $(this.handles[i], this.element), padWrapper = 0;
  117 + //Checking the correct pad and border
  118 + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
114 119
115   - //Checking the correct pad and border
116   - padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
  120 + //The padding type i have to apply...
  121 + var padPos = [ 'padding',
  122 + /ne|nw|n/.test(i) ? 'Top' :
  123 + /se|sw|s/.test(i) ? 'Bottom' :
  124 + /^e$/.test(i) ? 'Right' : 'Left' ].join("");
117 125
118   - //The padding type i have to apply...
119   - var padPos = [ 'padding',
120   - /ne|nw|n/.test(i) ? 'Top' :
121   - /se|sw|s/.test(i) ? 'Bottom' :
122   - /^e$/.test(i) ? 'Right' : 'Left' ].join("");
  126 + target.css(padPos, padWrapper);
123 127
124   - target.css(padPos, padWrapper);
  128 + this._proportionallyResize();
125 129
126   - this._proportionallyResize();
  130 + }
127 131
128   - }
  132 + //TODO: What's that good for? There's not anything to be executed left
  133 + if (!$(this.handles[i]).length)
  134 + continue;
129 135
130   - //TODO: What's that good for? There's not anything to be executed left
131   - if(!$(this.handles[i]).length)
132   - continue;
  136 + }
  137 + };
133 138
134   - }
135   - };
  139 + //TODO: make renderAxis a prototype function
  140 + this._renderAxis(this.element);
136 141
137   - //TODO: make renderAxis a prototype function
138   - this._renderAxis(this.element);
  142 + this._handles = $('.ui-resizable-handle', this.element)
  143 + .disableSelection();
139 144
140   - this._handles = $('.ui-resizable-handle', this.element)
141   - .disableSelection();
  145 + //Matching axis name
  146 + this._handles.mouseover(function() {
  147 + if (!self.resizing) {
  148 + if (this.className)
  149 + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
  150 + //Axis, default = se
  151 + self.axis = axis && axis[1] ? axis[1] : 'se';
  152 + }
  153 + });
142 154
143   - //Matching axis name
144   - this._handles.mouseover(function() {
145   - if (!self.resizing) {
146   - if (this.className)
147   - var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
148   - //Axis, default = se
149   - self.axis = axis && axis[1] ? axis[1] : 'se';
150   - }
151   - });
  155 + //If we want to auto hide the elements
  156 + if (o.autoHide) {
  157 + this._handles.hide();
  158 + $(this.element)
  159 + .addClass("ui-resizable-autohide")
  160 + .hover(function() {
  161 + $(this).removeClass("ui-resizable-autohide");
  162 + self._handles.show();
  163 + },
  164 + function() {
  165 + if (!self.resizing) {
  166 + $(this).addClass("ui-resizable-autohide");
  167 + self._handles.hide();
  168 + }
  169 + });
  170 + }
152 171
153   - //If we want to auto hide the elements
154   - if (o.autoHide) {
155   - this._handles.hide();
156   - $(this.element)
157   - .addClass("ui-resizable-autohide")
158   - .hover(function() {
159   - $(this).removeClass("ui-resizable-autohide");
160   - self._handles.show();
161   - },
162   - function(){
163   - if (!self.resizing) {
164   - $(this).addClass("ui-resizable-autohide");
165   - self._handles.hide();
166   - }
167   - });
168   - }
  172 + //Initialize the mouse interaction
  173 + this._mouseInit();
169 174
170   - //Initialize the mouse interaction
171   - this._mouseInit();
  175 + },
172 176
173   - },
  177 + destroy: function() {
174 178
175   - destroy: function() {
  179 + this._mouseDestroy();
176 180
177   - this._mouseDestroy();
  181 + var _destroy = function(exp) {
  182 + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
  183 + .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
  184 + };
178 185
179   - var _destroy = function(exp) {
180   - $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
181   - .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
182   - };
  186 + //TODO: Unwrap at same DOM position
  187 + if (this.elementIsWrapper) {
  188 + _destroy(this.element);
  189 + var wrapper = this.element;
  190 + wrapper.parent().append(
  191 + this.originalElement.css({
  192 + position: wrapper.css('position'),
  193 + width: wrapper.outerWidth(),
  194 + height: wrapper.outerHeight(),
  195 + top: wrapper.css('top'),
  196 + left: wrapper.css('left')
  197 + })
  198 + ).end().remove();
  199 + }
183 200
184   - //TODO: Unwrap at same DOM position
185   - if (this.elementIsWrapper) {
186   - _destroy(this.element);
187   - var wrapper = this.element;
188   - wrapper.parent().append(
189   - this.originalElement.css({
190   - position: wrapper.css('position'),
191   - width: wrapper.outerWidth(),
192   - height: wrapper.outerHeight(),
193   - top: wrapper.css('top'),
194   - left: wrapper.css('left')
195   - })
196   - ).end().remove();
197   - }
  201 + this.originalElement.css('resize', this.originalResizeStyle);
  202 + _destroy(this.originalElement);
198 203
199   - this.originalElement.css('resize', this.originalResizeStyle);
200   - _destroy(this.originalElement);
  204 + },
201 205
202   - },
  206 + _mouseCapture: function(event) {
203 207
204   - _mouseCapture: function(event) {
  208 + var handle = false;
  209 + for (var i in this.handles) {
  210 + if ($(this.handles[i])[0] == event.target) handle = true;
  211 + }
205 212
206   - var handle = false;
207   - for(var i in this.handles) {
208   - if($(this.handles[i])[0] == event.target) handle = true;
209   - }
  213 + return this.options.disabled || !!handle;
210 214
211   - return this.options.disabled || !!handle;
  215 + },
212 216
213   - },
  217 + _mouseStart: function(event) {
214 218
215   - _mouseStart: function(event) {
  219 + var o = this.options, iniPos = this.element.position(), el = this.element;
216 220
217   - var o = this.options, iniPos = this.element.position(), el = this.element;
  221 + this.resizing = true;
  222 + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
218 223
219   - this.resizing = true;
220   - this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
  224 + // bugfix for http://dev.jquery.com/ticket/1749
  225 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
  226 + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
  227 + }
221 228
222   - // bugfix for http://dev.jquery.com/ticket/1749
223   - if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
224   - el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
225   - }
  229 + //Opera fixing relative position
  230 + if ($.browser.opera && (/relative/).test(el.css('position')))
  231 + el.css({ position: 'relative', top: 'auto', left: 'auto' });
226 232
227   - //Opera fixing relative position
228   - if ($.browser.opera && (/relative/).test(el.css('position')))
229   - el.css({ position: 'relative', top: 'auto', left: 'auto' });
  233 + this._renderProxy();
230 234
231   - this._renderProxy();
  235 + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
232 236
233   - var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
  237 + if (o.containment) {
  238 + curleft += $(o.containment).scrollLeft() || 0;
  239 + curtop += $(o.containment).scrollTop() || 0;
  240 + }
234 241
235   - if (o.containment) {
236   - curleft += $(o.containment).scrollLeft() || 0;
237   - curtop += $(o.containment).scrollTop() || 0;
238   - }
  242 + //Store needed variables
  243 + this.offset = this.helper.offset();
  244 + this.position = { left: curleft, top: curtop };
  245 + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
  246 + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
  247 + this.originalPosition = { left: curleft, top: curtop };
  248 + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
  249 + this.originalMousePosition = { left: event.pageX, top: event.pageY };
239 250
240   - //Store needed variables
241   - this.offset = this.helper.offset();
242   - this.position = { left: curleft, top: curtop };
243   - this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
244   - this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
245   - this.originalPosition = { left: curleft, top: curtop };
246   - this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
247   - this.originalMousePosition = { left: event.pageX, top: event.pageY };
  251 + //Aspect Ratio
  252 + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
248 253
249   - //Aspect Ratio
250   - this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
  254 + var cursor = $('.ui-resizable-' + this.axis).css('cursor');
  255 + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
251 256
252   - var cursor = $('.ui-resizable-' + this.axis).css('cursor');
253   - $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
  257 + el.addClass("ui-resizable-resizing");
  258 + this._propagate("start", event);
  259 + return true;
  260 + },
254 261
255   - el.addClass("ui-resizable-resizing");
256   - this._propagate("start", event);
257   - return true;
258   - },
  262 + _mouseDrag: function(event) {
259 263
260   - _mouseDrag: function(event) {
  264 + //Increase performance, avoid regex
  265 + var el = this.helper, o = this.options, props = {},
  266 + self = this, smp = this.originalMousePosition, a = this.axis;
261 267
262   - //Increase performance, avoid regex
263   - var el = this.helper, o = this.options, props = {},
264   - self = this, smp = this.originalMousePosition, a = this.axis;
  268 + var dx = (event.pageX - smp.left) || 0, dy = (event.pageY - smp.top) || 0;
  269 + var trigger = this._change[a];
  270 + if (!trigger) return false;
265 271
266   - var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
267   - var trigger = this._change[a];
268   - if (!trigger) return false;
  272 + // Calculate the attrs that will be change
  273 + var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
269 274
270   - // Calculate the attrs that will be change
271   - var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
  275 + if (this._aspectRatio || event.shiftKey)
  276 + data = this._updateRatio(data, event);
272 277
273   - if (this._aspectRatio || event.shiftKey)
274   - data = this._updateRatio(data, event);
  278 + data = this._respectSize(data, event);
275 279
276   - data = this._respectSize(data, event);
  280 + // plugins callbacks need to be called first
  281 + this._propagate("resize", event);
277 282
278   - // plugins callbacks need to be called first
279   - this._propagate("resize", event);
  283 + el.css({
  284 + top: this.position.top + "px", left: this.position.left + "px",
  285 + width: this.size.width + "px", height: this.size.height + "px"
  286 + });
280 287
281   - el.css({
282   - top: this.position.top + "px", left: this.position.left + "px",
283   - width: this.size.width + "px", height: this.size.height + "px"
284   - });
  288 + if (!this._helper && this._proportionallyResizeElements.length)
  289 + this._proportionallyResize();
285 290
286   - if (!this._helper && this._proportionallyResizeElements.length)
287   - this._proportionallyResize();
  291 + this._updateCache(data);
288 292
289   - this._updateCache(data);
  293 + // calling the user callback at the end
  294 + this._trigger('resize', event, this.ui());
290 295
291   - // calling the user callback at the end
292   - this._trigger('resize', event, this.ui());
  296 + return false;
  297 + },
293 298
294   - return false;
295   - },
  299 + _mouseStop: function(event) {
296 300
297   - _mouseStop: function(event) {
  301 + this.resizing = false;
  302 + var o = this.options, self = this;
298 303
299   - this.resizing = false;
300   - var o = this.options, self = this;
  304 + if (this._helper) {
  305 + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
  306 + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
  307 + soffsetw = ista ? 0 : self.sizeDiff.width;
301 308
302   - if(this._helper) {
303   - var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
304   - soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
305   - soffsetw = ista ? 0 : self.sizeDiff.width;
  309 + var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
  310 + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
  311 + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
306 312
307   - var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
308   - left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
309   - top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
  313 + if (!o.animate)
  314 + this.element.css($.extend(s, { top: top, left: left }));
310 315
311   - if (!o.animate)
312   - this.element.css($.extend(s, { top: top, left: left }));
  316 + self.helper.height(self.size.height);
  317 + self.helper.width(self.size.width);
313 318
314   - self.helper.height(self.size.height);
315   - self.helper.width(self.size.width);
  319 + if (this._helper && !o.animate) this._proportionallyResize();
  320 + }
316 321
317   - if (this._helper && !o.animate) this._proportionallyResize();
318   - }
  322 + $('body').css('cursor', 'auto');
319 323
320   - $('body').css('cursor', 'auto');
  324 + this.element.removeClass("ui-resizable-resizing");
321 325
322   - this.element.removeClass("ui-resizable-resizing");
  326 + this._propagate("stop", event);
323 327
324   - this._propagate("stop", event);
  328 + if (this._helper) this.helper.remove();
  329 + return false;
325 330
326   - if (this._helper) this.helper.remove();
327   - return false;
  331 + },
328 332
329   - },
  333 + _updateCache: function(data) {
  334 + var o = this.options;
  335 + this.offset = this.helper.offset();
  336 + if (isNumber(data.left)) this.position.left = data.left;
  337 + if (isNumber(data.top)) this.position.top = data.top;
  338 + if (isNumber(data.height)) this.size.height = data.height;
  339 + if (isNumber(data.width)) this.size.width = data.width;
  340 + },
330 341
331   - _updateCache: function(data) {
332   - var o = this.options;
333   - this.offset = this.helper.offset();
334   - if (isNumber(data.left)) this.position.left = data.left;
335   - if (isNumber(data.top)) this.position.top = data.top;
336   - if (isNumber(data.height)) this.size.height = data.height;
337   - if (isNumber(data.width)) this.size.width = data.width;
338   - },
  342 + _updateRatio: function(data, event) {
339 343
340   - _updateRatio: function(data, event) {
  344 + var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
341 345
342   - var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
  346 + if (data.height) data.width = (csize.height * this.aspectRatio);
  347 + else if (data.width) data.height = (csize.width / this.aspectRatio);
343 348
344   - if (data.height) data.width = (csize.height * this.aspectRatio);
345   - else if (data.width) data.height = (csize.width / this.aspectRatio);
  349 + if (a == 'sw') {
  350 + data.left = cpos.left + (csize.width - data.width);
  351 + data.top = null;
  352 + }
  353 + if (a == 'nw') {
  354 + data.top = cpos.top + (csize.height - data.height);
  355 + data.left = cpos.left + (csize.width - data.width);
  356 + }
346 357
347   - if (a == 'sw') {
348   - data.left = cpos.left + (csize.width - data.width);
349   - data.top = null;
350   - }
351   - if (a == 'nw') {
352   - data.top = cpos.top + (csize.height - data.height);
353   - data.left = cpos.left + (csize.width - data.width);
354   - }
  358 + return data;
  359 + },
355 360
356   - return data;
357   - },
  361 + _respectSize: function(data, event) {
358 362
359   - _respectSize: function(data, event) {
  363 + var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
  364 + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
  365 + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
360 366
361   - var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
362   - ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
363   - isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
  367 + if (isminw) data.width = o.minWidth;
  368 + if (isminh) data.height = o.minHeight;
  369 + if (ismaxw) data.width = o.maxWidth;
  370 + if (ismaxh) data.height = o.maxHeight;
364 371
365   - if (isminw) data.width = o.minWidth;
366   - if (isminh) data.height = o.minHeight;
367   - if (ismaxw) data.width = o.maxWidth;
368   - if (ismaxh) data.height = o.maxHeight;
  372 + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
  373 + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
369 374
370   - var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
371   - var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
  375 + if (isminw && cw) data.left = dw - o.minWidth;
  376 + if (ismaxw && cw) data.left = dw - o.maxWidth;
  377 + if (isminh && ch) data.top = dh - o.minHeight;
  378 + if (ismaxh && ch) data.top = dh - o.maxHeight;
372 379
373   - if (isminw && cw) data.left = dw - o.minWidth;
374   - if (ismaxw && cw) data.left = dw - o.maxWidth;
375   - if (isminh && ch) data.top = dh - o.minHeight;
376   - if (ismaxh && ch) data.top = dh - o.maxHeight;
  380 + // fixing jump error on top/left - bug #2330
  381 + var isNotwh = !data.width && !data.height;
  382 + if (isNotwh && !data.left && data.top) data.top = null;
  383 + else if (isNotwh && !data.top && data.left) data.left = null;
377 384
378   - // fixing jump error on top/left - bug #2330
379   - var isNotwh = !data.width && !data.height;
380   - if (isNotwh && !data.left && data.top) data.top = null;
381   - else if (isNotwh && !data.top && data.left) data.left = null;
  385 + return data;
  386 + },
382 387
383   - return data;
384   - },
  388 + _proportionallyResize: function() {
385 389
386   - _proportionallyResize: function() {
  390 + var o = this.options;
  391 + if (!this._proportionallyResizeElements.length) return;
  392 + var element = this.helper || this.element;
  393 +
  394 + for (var i = 0; i < this._proportionallyResizeElements.length; i++) {
  395 +
  396 + var prel = this._proportionallyResizeElements[i];
  397 +
  398 + if (!this.borderDif) {
  399 + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
  400 + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
  401 +
  402 + this.borderDif = $.map(b, function(v, i) {
  403 + var border = parseInt(v, 10) || 0, padding = parseInt(p[i], 10) || 0;
  404 + return border + padding;
  405 + });
  406 + }
  407 +
  408 + if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
  409 + continue;
  410 +
  411 + prel.css({
  412 + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
  413 + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
  414 + });
  415 +
  416 + }
  417 + ;
  418 +
  419 + },
  420 +
  421 + _renderProxy: function() {
  422 +
  423 + var el = this.element, o = this.options;
  424 + this.elementOffset = el.offset();
  425 +
  426 + if (this._helper) {
  427 +
  428 + this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
  429 +
  430 + // fix ie6 offset TODO: This seems broken
  431 + var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
  432 + pxyoffset = ( ie6 ? 2 : -1 );
  433 +
  434 + this.helper.addClass(this._helper).css({
  435 + width: this.element.outerWidth() + pxyoffset,
  436 + height: this.element.outerHeight() + pxyoffset,
  437 + position: 'absolute',
  438 + left: this.elementOffset.left - ie6offset + 'px',
  439 + top: this.elementOffset.top - ie6offset + 'px',
  440 + zIndex: ++o.zIndex //TODO: Don't modify option
  441 + });
  442 +
  443 + this.helper
  444 + .appendTo("body")
  445 + .disableSelection();
  446 +
  447 + } else {
  448 + this.helper = this.element;
  449 + }
  450 +
  451 + },
  452 +
  453 + _change: {
  454 + e: function(event, dx, dy) {
  455 + return { width: this.originalSize.width + dx };
  456 + },
  457 + w: function(event, dx, dy) {
  458 + var o = this.options, cs = this.originalSize, sp = this.originalPosition;
  459 + return { left: sp.left + dx, width: cs.width - dx };
  460 + },
  461 + n: function(event, dx, dy) {
  462 + var o = this.options, cs = this.originalSize, sp = this.originalPosition;
  463 + return { top: sp.top + dy, height: cs.height - dy };
  464 + },
  465 + s: function(event, dx, dy) {
  466 + return { height: this.originalSize.height + dy };
  467 + },
  468 + se: function(event, dx, dy) {
  469 + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
  470 + },
  471 + sw: function(event, dx, dy) {
  472 + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
  473 + },
  474 + ne: function(event, dx, dy) {
  475 + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
  476 + },
  477 + nw: function(event, dx, dy) {
  478 + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
  479 + }
  480 + },
  481 +
  482 + _propagate: function(n, event) {
  483 + $.ui.plugin.call(this, n, [event, this.ui()]);
  484 + (n != "resize" && this._trigger(n, event, this.ui()));
  485 + },
  486 +
  487 + plugins: {},
  488 +
  489 + ui: function() {
  490 + return {
  491 + originalElement: this.originalElement,
  492 + element: this.element,
  493 + helper: this.helper,
  494 + position: this.position,
  495 + size: this.size,
  496 + originalSize: this.originalSize,
  497 + originalPosition: this.originalPosition
  498 + };
  499 + }
  500 +
  501 + }));
  502 +
  503 + $.extend($.ui.resizable, {
  504 + version: "1.7.2",
  505 + eventPrefix: "resize",
  506 + defaults: {
  507 + alsoResize: false,
  508 + animate: false,
  509 + animateDuration: "slow",
  510 + animateEasing: "swing",
  511 + aspectRatio: false,
  512 + autoHide: false,
  513 + cancel: ":input,option",
  514 + containment: false,
  515 + delay: 0,
  516 + distance: 1,
  517 + ghost: false,
  518 + grid: false,
  519 + handles: "e,s,se",
  520 + helper: false,
  521 + maxHeight: null,
  522 + maxWidth: null,
  523 + minHeight: 10,
  524 + minWidth: 10,
  525 + zIndex: 1000
  526 + }
  527 + });
  528 +
  529 + /*
  530 + * Resizable Extensions
  531 + */
  532 +
  533 + $.ui.plugin.add("resizable", "alsoResize", {
  534 +
  535 + start: function(event, ui) {
  536 +
  537 + var self = $(this).data("resizable"), o = self.options;
  538 +
  539 + _store = function(exp) {
  540 + $(exp).each(function() {
  541 + $(this).data("resizable-alsoresize", {
  542 + width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
  543 + left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
  544 + });
  545 + });
  546 + };
  547 +
  548 + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
  549 + if (o.alsoResize.length) {
  550 + o.alsoResize = o.alsoResize[0];
  551 + _store(o.alsoResize);
  552 + }
  553 + else {
  554 + $.each(o.alsoResize, function(exp, c) {
  555 + _store(exp);
  556 + });
  557 + }
  558 + } else {
  559 + _store(o.alsoResize);
  560 + }
  561 + },
  562 +
  563 + resize: function(event, ui) {
  564 + var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
  565 +
  566 + var delta = {
  567 + height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
  568 + top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
  569 + },
  570 +
  571 + _alsoResize = function(exp, c) {
  572 + $(exp).each(function() {
  573 + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
  574 +
  575 + $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
  576 + var sum = (start[prop] || 0) + (delta[prop] || 0);
  577 + if (sum && sum >= 0)
  578 + style[prop] = sum || null;
  579 + });
  580 +
  581 + //Opera fixing relative position
  582 + if (/relative/.test(el.css('position')) && $.browser.opera) {
  583 + self._revertToRelativePosition = true;
  584 + el.css({ position: 'absolute', top: 'auto', left: 'auto' });
  585 + }
  586 +
  587 + el.css(style);
  588 + });
  589 + };
  590 +
  591 + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
  592 + $.each(o.alsoResize, function(exp, c) {
  593 + _alsoResize(exp, c);
  594 + });
  595 + } else {
  596 + _alsoResize(o.alsoResize);
  597 + }
  598 + },
  599 +
  600 + stop: function(event, ui) {
  601 + var self = $(this).data("resizable");
  602 +
  603 + //Opera fixing relative position
  604 + if (self._revertToRelativePosition && $.browser.opera) {
  605 + self._revertToRelativePosition = false;
  606 + el.css({ position: 'relative' });
  607 + }
  608 +
  609 + $(this).removeData("resizable-alsoresize-start");
  610 + }
  611 + });
  612 +
  613 + $.ui.plugin.add("resizable", "animate", {
  614 +
  615 + stop: function(event, ui) {
  616 + var self = $(this).data("resizable"), o = self.options;
  617 +
  618 + var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
  619 + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
  620 + soffsetw = ista ? 0 : self.sizeDiff.width;
  621 +
  622 + var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
  623 + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
  624 + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
  625 +
  626 + self.element.animate(
  627 + $.extend(style, top && left ? { top: top, left: left } : {}), {
  628 + duration: o.animateDuration,
  629 + easing: o.animateEasing,
  630 + step: function() {
  631 +
  632 + var data = {
  633 + width: parseInt(self.element.css('width'), 10),
  634 + height: parseInt(self.element.css('height'), 10),
  635 + top: parseInt(self.element.css('top'), 10),
  636 + left: parseInt(self.element.css('left'), 10)
  637 + };
  638 +
  639 + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
  640 +
  641 + // propagating resize, and updating values for each animation step
  642 + self._updateCache(data);
  643 + self._propagate("resize", event);
  644 +
  645 + }
  646 + }
  647 + );
  648 + }
  649 +
  650 + });
  651 +
  652 + $.ui.plugin.add("resizable", "containment", {
  653 +
  654 + start: function(event, ui) {
  655 + var self = $(this).data("resizable"), o = self.options, el = self.element;
  656 + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
  657 + if (!ce) return;
  658 +
  659 + self.containerElement = $(ce);
387 660
388   - var o = this.options;
389   - if (!this._proportionallyResizeElements.length) return;
390   - var element = this.helper || this.element;
391   -
392   - for (var i=0; i < this._proportionallyResizeElements.length; i++) {
393   -
394   - var prel = this._proportionallyResizeElements[i];
395   -
396   - if (!this.borderDif) {
397   - var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
398   - p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
399   -
400   - this.borderDif = $.map(b, function(v, i) {
401   - var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
402   - return border + padding;
403   - });
404   - }
405   -
406   - if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
407   - continue;
408   -
409   - prel.css({
410   - height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
411   - width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
412   - });
413   -
414   - };
415   -
416   - },
417   -
418   - _renderProxy: function() {
419   -
420   - var el = this.element, o = this.options;
421   - this.elementOffset = el.offset();
422   -
423   - if(this._helper) {
424   -
425   - this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
426   -
427   - // fix ie6 offset TODO: This seems broken
428   - var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
429   - pxyoffset = ( ie6 ? 2 : -1 );
430   -
431   - this.helper.addClass(this._helper).css({
432   - width: this.element.outerWidth() + pxyoffset,
433   - height: this.element.outerHeight() + pxyoffset,
434   - position: 'absolute',
435   - left: this.elementOffset.left - ie6offset +'px',
436   - top: this.elementOffset.top - ie6offset +'px',
437   - zIndex: ++o.zIndex //TODO: Don't modify option
438   - });
439   -
440   - this.helper
441   - .appendTo("body")
442   - .disableSelection();
443   -
444   - } else {
445   - this.helper = this.element;
446   - }
447   -
448   - },
449   -
450   - _change: {
451   - e: function(event, dx, dy) {
452   - return { width: this.originalSize.width + dx };
453   - },
454   - w: function(event, dx, dy) {
455   - var o = this.options, cs = this.originalSize, sp = this.originalPosition;
456   - return { left: sp.left + dx, width: cs.width - dx };
457   - },
458   - n: function(event, dx, dy) {
459   - var o = this.options, cs = this.originalSize, sp = this.originalPosition;
460   - return { top: sp.top + dy, height: cs.height - dy };
461   - },
462   - s: function(event, dx, dy) {
463   - return { height: this.originalSize.height + dy };
464   - },
465   - se: function(event, dx, dy) {
466   - return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
467   - },
468   - sw: function(event, dx, dy) {
469   - return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
470   - },
471   - ne: function(event, dx, dy) {
472   - return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
473   - },
474   - nw: function(event, dx, dy) {
475   - return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
476   - }
477   - },
478   -
479   - _propagate: function(n, event) {
480   - $.ui.plugin.call(this, n, [event, this.ui()]);
481   - (n != "resize" && this._trigger(n, event, this.ui()));
482   - },
483   -
484   - plugins: {},
485   -
486   - ui: function() {
487   - return {
488   - originalElement: this.originalElement,
489   - element: this.element,
490   - helper: this.helper,
491   - position: this.position,
492   - size: this.size,
493   - originalSize: this.originalSize,
494   - originalPosition: this.originalPosition
495   - };
496   - }
497   -
498   -}));
499   -
500   -$.extend($.ui.resizable, {
501   - version: "1.7.2",
502   - eventPrefix: "resize",
503   - defaults: {
504   - alsoResize: false,
505   - animate: false,
506   - animateDuration: "slow",
507   - animateEasing: "swing",
508   - aspectRatio: false,
509   - autoHide: false,
510   - cancel: ":input,option",
511   - containment: false,
512   - delay: 0,
513   - distance: 1,
514   - ghost: false,
515   - grid: false,
516   - handles: "e,s,se",
517   - helper: false,
518   - maxHeight: null,
519   - maxWidth: null,
520   - minHeight: 10,
521   - minWidth: 10,
522   - zIndex: 1000
523   - }
524   -});
  661 + if (/document/.test(oc) || oc == document) {
  662 + self.containerOffset = { left: 0, top: 0 };
  663 + self.containerPosition = { left: 0, top: 0 };
525 664
526   -/*
527   - * Resizable Extensions
528   - */
529   -
530   -$.ui.plugin.add("resizable", "alsoResize", {
531   -
532   - start: function(event, ui) {
533   -
534   - var self = $(this).data("resizable"), o = self.options;
535   -
536   - _store = function(exp) {
537   - $(exp).each(function() {
538   - $(this).data("resizable-alsoresize", {
539   - width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
540   - left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
541   - });
542   - });
543   - };
544   -
545   - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
546   - if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
547   - else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
548   - }else{
549   - _store(o.alsoResize);
550   - }
551   - },
552   -
553   - resize: function(event, ui){
554   - var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
555   -
556   - var delta = {
557   - height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
558   - top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
559   - },
560   -
561   - _alsoResize = function(exp, c) {
562   - $(exp).each(function() {
563   - var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
564   -
565   - $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
566   - var sum = (start[prop]||0) + (delta[prop]||0);
567   - if (sum && sum >= 0)
568   - style[prop] = sum || null;
569   - });
570   -
571   - //Opera fixing relative position
572   - if (/relative/.test(el.css('position')) && $.browser.opera) {
573   - self._revertToRelativePosition = true;
574   - el.css({ position: 'absolute', top: 'auto', left: 'auto' });
575   - }
576   -
577   - el.css(style);
578   - });
579   - };
580   -
581   - if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
582   - $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
583   - }else{
584   - _alsoResize(o.alsoResize);
585   - }
586   - },
587   -
588   - stop: function(event, ui){
589   - var self = $(this).data("resizable");
590   -
591   - //Opera fixing relative position
592   - if (self._revertToRelativePosition && $.browser.opera) {
593   - self._revertToRelativePosition = false;
594   - el.css({ position: 'relative' });
595   - }
596   -
597   - $(this).removeData("resizable-alsoresize-start");
598   - }
599   -});
600   -
601   -$.ui.plugin.add("resizable", "animate", {
602   -
603   - stop: function(event, ui) {
604   - var self = $(this).data("resizable"), o = self.options;
605   -
606   - var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
607   - soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
608   - soffsetw = ista ? 0 : self.sizeDiff.width;
609   -
610   - var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
611   - left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
612   - top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
613   -
614   - self.element.animate(
615   - $.extend(style, top && left ? { top: top, left: left } : {}), {
616   - duration: o.animateDuration,
617   - easing: o.animateEasing,
618   - step: function() {
619   -
620   - var data = {
621   - width: parseInt(self.element.css('width'), 10),
622   - height: parseInt(self.element.css('height'), 10),
623   - top: parseInt(self.element.css('top'), 10),
624   - left: parseInt(self.element.css('left'), 10)
625   - };
626   -
627   - if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
628   -
629   - // propagating resize, and updating values for each animation step
630   - self._updateCache(data);
631   - self._propagate("resize", event);
632   -
633   - }
634   - }
635   - );
636   - }
637   -
638   -});
639   -
640   -$.ui.plugin.add("resizable", "containment", {
641   -
642   - start: function(event, ui) {
643   - var self = $(this).data("resizable"), o = self.options, el = self.element;
644   - var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
645   - if (!ce) return;
646   -
647   - self.containerElement = $(ce);
648   -
649   - if (/document/.test(oc) || oc == document) {
650   - self.containerOffset = { left: 0, top: 0 };
651   - self.containerPosition = { left: 0, top: 0 };
652   -
653   - self.parentData = {
654   - element: $(document), left: 0, top: 0,
655   - width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
656   - };
657   - }
658   -
659   - // i'm a node, so compute top, left, right, bottom
660   - else {
661   - var element = $(ce), p = [];
662   - $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
663   -
664   - self.containerOffset = element.offset();
665   - self.containerPosition = element.position();
666   - self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
667   -
668   - var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
669   - width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
670   -
671   - self.parentData = {
672   - element: ce, left: co.left, top: co.top, width: width, height: height
673   - };
674   - }
675   - },
  665 + self.parentData = {
  666 + element: $(document), left: 0, top: 0,
  667 + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
  668 + };
  669 + }
676 670
677   - resize: function(event, ui) {
678   - var self = $(this).data("resizable"), o = self.options,
679   - ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
680   - pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
681   -
682   - if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
683   -
684   - if (cp.left < (self._helper ? co.left : 0)) {
685   - self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
686   - if (pRatio) self.size.height = self.size.width / o.aspectRatio;
687   - self.position.left = o.helper ? co.left : 0;
688   - }
689   -
690   - if (cp.top < (self._helper ? co.top : 0)) {
691   - self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
692   - if (pRatio) self.size.width = self.size.height * o.aspectRatio;
693   - self.position.top = self._helper ? co.top : 0;
694   - }
  671 + // i'm a node, so compute top, left, right, bottom
  672 + else {
  673 + var element = $(ce), p = [];
  674 + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) {
  675 + p[i] = num(element.css("padding" + name));
  676 + });
695 677
696   - self.offset.left = self.parentData.left+self.position.left;
697   - self.offset.top = self.parentData.top+self.position.top;
698   -
699   - var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
700   - hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
701   -
702   - var isParent = self.containerElement.get(0) == self.element.parent().get(0),
703   - isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
704   -
705   - if(isParent && isOffsetRelative) woset -= self.parentData.left;
706   -
707   - if (woset + self.size.width >= self.parentData.width) {
708   - self.size.width = self.parentData.width - woset;
709   - if (pRatio) self.size.height = self.size.width / self.aspectRatio;
710   - }
711   -
712   - if (hoset + self.size.height >= self.parentData.height) {
713   - self.size.height = self.parentData.height - hoset;
714   - if (pRatio) self.size.width = self.size.height * self.aspectRatio;
715   - }
716   - },
717   -
718   - stop: function(event, ui){
719   - var self = $(this).data("resizable"), o = self.options, cp = self.position,
720   - co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
721   -
722   - var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
723   -
724   - if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
725   - $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
  678 + self.containerOffset = element.offset();
  679 + self.containerPosition = element.position();
  680 + self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
726 681
727   - if (self._helper && !o.animate && (/static/).test(ce.css('position')))
728   - $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
729   -
730   - }
731   -});
  682 + var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
  683 + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
732 684
733   -$.ui.plugin.add("resizable", "ghost", {
734   -
735   - start: function(event, ui) {
  685 + self.parentData = {
  686 + element: ce, left: co.left, top: co.top, width: width, height: height
  687 + };
  688 + }
  689 + },
736 690
737   - var self = $(this).data("resizable"), o = self.options, cs = self.size;
738   -
739   - self.ghost = self.originalElement.clone();
740   - self.ghost
741   - .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
742   - .addClass('ui-resizable-ghost')
743   - .addClass(typeof o.ghost == 'string' ? o.ghost : '');
744   -
745   - self.ghost.appendTo(self.helper);
746   -
747   - },
748   -
749   - resize: function(event, ui){
750   - var self = $(this).data("resizable"), o = self.options;
751   - if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
752   - },
753   -
754   - stop: function(event, ui){
755   - var self = $(this).data("resizable"), o = self.options;
756   - if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
757   - }
758   -
759   -});
760   -
761   -$.ui.plugin.add("resizable", "grid", {
762   -
763   - resize: function(event, ui) {
764   - 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;
765   - o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
766   - 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);
767   -
768   - if (/^(se|s|e)$/.test(a)) {
769   - self.size.width = os.width + ox;
770   - self.size.height = os.height + oy;
771   - }
772   - else if (/^(ne)$/.test(a)) {
773   - self.size.width = os.width + ox;
774   - self.size.height = os.height + oy;
775   - self.position.top = op.top - oy;
776   - }
777   - else if (/^(sw)$/.test(a)) {
778   - self.size.width = os.width + ox;
779   - self.size.height = os.height + oy;
780   - self.position.left = op.left - ox;
781   - }
782   - else {
783   - self.size.width = os.width + ox;
784   - self.size.height = os.height + oy;
785   - self.position.top = op.top - oy;
786   - self.position.left = op.left - ox;
787   - }
788   - }
  691 + resize: function(event, ui) {
  692 + var self = $(this).data("resizable"), o = self.options,
  693 + ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
  694 + pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
  695 +
  696 + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
  697 +
  698 + if (cp.left < (self._helper ? co.left : 0)) {
  699 + self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
  700 + if (pRatio) self.size.height = self.size.width / o.aspectRatio;
  701 + self.position.left = o.helper ? co.left : 0;
  702 + }
  703 +
  704 + if (cp.top < (self._helper ? co.top : 0)) {
  705 + self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
  706 + if (pRatio) self.size.width = self.size.height * o.aspectRatio;
  707 + self.position.top = self._helper ? co.top : 0;
  708 + }
  709 +
  710 + self.offset.left = self.parentData.left + self.position.left;
  711 + self.offset.top = self.parentData.top + self.position.top;
  712 +
  713 + var woset = Math.abs((self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width),
  714 + hoset = Math.abs((self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height);
  715 +
  716 + var isParent = self.containerElement.get(0) == self.element.parent().get(0),
  717 + isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
  718 +
  719 + if (isParent && isOffsetRelative) woset -= self.parentData.left;
  720 +
  721 + if (woset + self.size.width >= self.parentData.width) {
  722 + self.size.width = self.parentData.width - woset;
  723 + if (pRatio) self.size.height = self.size.width / self.aspectRatio;
  724 + }
  725 +
  726 + if (hoset + self.size.height >= self.parentData.height) {
  727 + self.size.height = self.parentData.height - hoset;
  728 + if (pRatio) self.size.width = self.size.height * self.aspectRatio;
  729 + }
  730 + },
  731 +
  732 + stop: function(event, ui) {
  733 + var self = $(this).data("resizable"), o = self.options, cp = self.position,
  734 + co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
  735 +
  736 + var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
  737 +
  738 + if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
  739 + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
  740 +
  741 + if (self._helper && !o.animate && (/static/).test(ce.css('position')))
  742 + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
  743 +
  744 + }
  745 + });
  746 +
  747 + $.ui.plugin.add("resizable", "ghost", {
  748 +
  749 + start: function(event, ui) {
  750 +
  751 + var self = $(this).data("resizable"), o = self.options, cs = self.size;
  752 +
  753 + self.ghost = self.originalElement.clone();
  754 + self.ghost
  755 + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
  756 + .addClass('ui-resizable-ghost')
  757 + .addClass(typeof o.ghost == 'string' ? o.ghost : '');
  758 +
  759 + self.ghost.appendTo(self.helper);
  760 +
  761 + },
  762 +
  763 + resize: function(event, ui) {
  764 + var self = $(this).data("resizable"), o = self.options;
  765 + if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
  766 + },
  767 +
  768 + stop: function(event, ui) {
  769 + var self = $(this).data("resizable"), o = self.options;
  770 + if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
  771 + }
  772 +
  773 + });
  774 +
  775 + $.ui.plugin.add("resizable", "grid", {
  776 +
  777 + resize: function(event, ui) {
  778 + 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;
  779 + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
  780 + 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);
  781 +
  782 + if (/^(se|s|e)$/.test(a)) {
  783 + self.size.width = os.width + ox;
  784 + self.size.height = os.height + oy;
  785 + }
  786 + else if (/^(ne)$/.test(a)) {
  787 + self.size.width = os.width + ox;
  788 + self.size.height = os.height + oy;
  789 + self.position.top = op.top - oy;
  790 + }
  791 + else if (/^(sw)$/.test(a)) {
  792 + self.size.width = os.width + ox;
  793 + self.size.height = os.height + oy;
  794 + self.position.left = op.left - ox;
  795 + }
  796 + else {
  797 + self.size.width = os.width + ox;
  798 + self.size.height = os.height + oy;
  799 + self.position.top = op.top - oy;
  800 + self.position.left = op.left - ox;
  801 + }
  802 + }
789 803
790   -});
791   -
792   -var num = function(v) {
793   - return parseInt(v, 10) || 0;
794   -};
  804 + });
  805 +
  806 + var num = function(v) {
  807 + return parseInt(v, 10) || 0;
  808 + };
795 809
796   -var isNumber = function(value) {
797   - return !isNaN(parseInt(value, 10));
798   -};
  810 + var isNumber = function(value) {
  811 + return !isNaN(parseInt(value, 10));
  812 + };
799 813
800 814 })(jQuery);
... ...
... ... @@ -16,6 +16,7 @@
16 16 <h:scripts>org.ajax4jsf.javascript.AjaxScript,
17 17 /org/ajax4jsf/javascript/scripts/form.js,
18 18 /org/richfaces/renderkit/html/scripts/form.js,
  19 + /org/richfaces/renderkit/html/scripts/utils.js,
19 20 /org/richfaces/renderkit/html/scripts/jquery/jquery.js,
20 21 /org/richfaces/renderkit/html/scripts/ui.core.js,
21 22 /org/richfaces/renderkit/html/scripts/ui.draggable.js,
... ... @@ -31,6 +32,6 @@
31 32 x:passThruWithExclusions="value,name,type,id"></div>
32 33 <input type="hidden" name="#{clientId}" id="#{clientId}"/>
33 34 <script type="text/javascript">
34   - <f:call name = "writeInitFunction" />
  35 + <f:call name = "writeInitFunction"/>
35 36 </script>
36 37 </f:root>
\ No newline at end of file
... ...
Please register or login to post a comment