DialogBehavior

public abstract class DialogBehavior extends JQueryBehavior implements IJQueryAjaxAware, IDialogListener
{
    private static final long serialVersionUID = 1L;
    private static final String METHOD = "dialog";

    private JQueryAjaxBehavior onDefaultClose = null;

    /**
     * Constructor
     *
     * @param selector the html selector (ie: "#myId")
     */
    public DialogBehavior(String selector)
    {
        super(selector, METHOD);
    }

    /**
     * Constructor
     *
     * @param selector the html selector (ie: "#myId")
     * @param options the {@link Options}
     */
    public DialogBehavior(String selector, Options options)
    {
        super(selector, METHOD, options);
    }

    // Properties //
    /**
     * Gets the dialog's buttons.<br/>
     *
     * @return the {@link List} of {@link Button}
     */
    protected abstract List<DialogButton> getButtons();

    // Methods //
    @Override
    public void bind(Component component)
    {
        super.bind(component);

        for (DialogButton button : this.getButtons())
        {
            component.add(this.newButtonAjaxBehavior(this, button));
        }

        if (this.isDefaultCloseEventEnabled())
        {
            component.add(this.onDefaultClose = this.newDefaultCloseBehavior());
        }
    }

    /**
     * Opens the dialogs in ajax.<br/>
     * @param target the {@link AjaxRequestTarget}
     */
    public void open(AjaxRequestTarget target)
    {
        target.appendJavaScript(this.$("'open'"));
    }

    /**
     * Closes the dialogs in ajax.<br/>
     * @param target the {@link AjaxRequestTarget}
     */
    public void close(AjaxRequestTarget target)
    {
        target.appendJavaScript(this.$("'close'"));
    }

    // Events //
    @Override
    public void onConfigure(Component component)
    {
        super.onConfigure(component);

        if (this.onDefaultClose != null)
        {
            this.setOption("close", this.onDefaultClose.getCallbackFunction());
        }

        // buttons events //
        StringBuffer buttons = new StringBuffer("[ ");

        int index = 0;
        for(ButtonAjaxBehavior behavior : component.getBehaviors(ButtonAjaxBehavior.class))
        {
            DialogButton button = behavior.getButton();

            if (index++ > 0) { buttons.append(", "); }
            buttons.append("{");
            buttons.append("'id': '").append(button.getMarkupId()).append("', ");
            buttons.append("'text': '").append(button.toString()).append("', ");
            if (!button.isEnabled()) { buttons.append("'disabled': true, "); }
            if (button.getIcon() != null) { buttons.append("icons: { primary: '").append(button.getIcon()).append("' }, "); }
            buttons.append("'click': function() { ").append(behavior.getCallbackScript()).append(" }");
            buttons.append("}");
        }

        buttons.append(" ]");

        this.setOption("buttons", buttons);
    }

    @Override
    public void onAjax(AjaxRequestTarget target, JQueryEvent event)
    {
        if (event instanceof ClickEvent)
        {
            this.onClick(target, ((ClickEvent) event).getButton());
        }

        else if (event instanceof CloseEvent)
        {
            this.onClose(target, null);
        }
    }

    // Factories //
    /**
     * Gets a new ButtonAjaxBehavior that will be called by the corresponding dialog's button.<br/>
     * This method mays be overridden internally to provide another behavior;
     *
     * @param source the {@link IJQueryAjaxAware} source
     * @param button the button that is passed to the behavior so it can be retrieved via the {@link ClickEvent}
     * @return the {@link ButtonAjaxBehavior}
     */
    protected abstract ButtonAjaxBehavior newButtonAjaxBehavior(IJQueryAjaxAware source, DialogButton button);

    /**
     * Gets the ajax behavior that will be triggered when the user clicks on the X-icon
     *
     * @return the {@link JQueryAjaxBehavior}
     */
    protected JQueryAjaxBehavior newDefaultCloseBehavior()
    {
        return new JQueryAjaxBehavior(this) {

            private static final long serialVersionUID = 1L;

            @Override
            public String getCallbackFunction()
            {
                return "function(event, ui) { if (event.button == 0) { " + this.getCallbackScript() + " } }";
            }

            @Override
            protected JQueryEvent newEvent()
            {
                return new CloseEvent();
            }
        };
    }


    // Ajax behaviors //
    /**
     * Provides the {@link JQueryAjaxBehavior} being called by the button(s).
     */
    protected static class ButtonAjaxBehavior extends JQueryAjaxBehavior
    {
        private static final long serialVersionUID = 1L;

        private final DialogButton button;

        /**
         * Constructor
         * @param source the {@link IJQueryAjaxAware}
         * @param button the {@link DialogButton} to attach to the {@link ClickEvent}
         */
        public ButtonAjaxBehavior(IJQueryAjaxAware source, DialogButton button)
        {
            super(source);

            this.button = button;
        }

        /**
         * Gets the {@link DialogButton}
         * @return the {@link DialogButton}
         */
        public DialogButton getButton()
        {
            return this.button;
        }

        @Override
        protected JQueryEvent newEvent()
        {
            return new ClickEvent(this.button);
        }
    }


    // Events classes //
    /**
     * Provides a dialog event that will be transmitted to the {@link AbstractDialog}
     */
    protected static class ClickEvent extends JQueryEvent
    {
        private final DialogButton button;

        public ClickEvent(DialogButton button)
        {
            super();

            this.button = button;
        }

        /**
         * Get the button that has been attached to this event object
         * @return the button
         */
        public DialogButton getButton()
        {
            return this.button;
        }
    }

    /**
     * An event object that will be broadcasted when the user clicks on the X-icon
     */
    protected static class CloseEvent extends JQueryEvent
    {
    }
}


public class JQueryBehavior extends JQueryAbstractBehavior
{
    private static final long serialVersionUID = 1L;
    private static final String NULL_OPTIONS = "Options have not been defined (null has been supplied to the constructor)";

    private final String selector;
    private final String method;
    private final Options options;

    private List<String> events = null;

    /**
     * Constructor
     * @param selector the html selector (ie: "#myId")
     */
    public JQueryBehavior(String selector)
    {
        this(selector, "");
    }

    /**
     * Constructor
     * @param selector the html selector (ie: "#myId")
     * @param method the jquery method
     */
    public JQueryBehavior(String selector, String method)
    {
        this(selector, method, new Options());
    }

    /**
     * Constructor
     * @param selector the html selector (ie: "#myId")
     * @param method the jquery method
     * @param options the {@link Options}
     */
    public JQueryBehavior(String selector, String method, Options options)
    {
        super(method);

        this.method = method;
        this.options = options;
        this.selector = selector;
    }

    // Methods //
    @Override
    public void renderHead(Component component, IHeaderResponse response)
    {
        super.renderHead(component, response);

        // renders javascript events
        if (this.events != null)
        {
            StringBuilder statements = new StringBuilder("jQuery(function() { ");

            for (String event : this.events)
            {
                statements.append(event);
            }

            statements.append(" });");

            response.render(JavaScriptHeaderItem.forScript(statements, this.getToken() + "-events"));
        }
    }

    // Properties //
    /**
     * Gets the selector
     * @return the selector
     */
    //XXX: report as new (and this.selector private)
    public String getSelector()
    {
        return this.selector;
    }

    /**
     * Gets the jQuery method
     * @return the method
     */
    //XXX: report as new (and this.method private)
    public String getMethod()
    {
        return this.method;
    }

    /**
     * Gets a behavior option, referenced by its key
     * @param key the option key
     * @return null if the key does not exists
     */
    public Object getOption(String key)
    {
        if (this.options == null)
        {
            throw new WicketRuntimeException(NULL_OPTIONS);
        }

        return this.options.get(key);
    }

    /**
     * Sets a behavior option.
     * @param key the option key
     * @param value the option value
     * @return the {@link JQueryBehavior} (this)
     */
    public JQueryBehavior setOption(String key, Serializable value)
    {
        if (this.options == null)
        {
            throw new WicketRuntimeException(NULL_OPTIONS);
        }

        this.options.set(key, value);

        return this;
    }

    /**
     * Gets the {@link Options}
     * @return the {@link Options}
     */
    //XXX: report as new (and this.options private)
    public Options getOptions()
    {
        return this.options;
    }

    /**
     * Adds or replace behavior options
     * @param options the {@link Options}
     */
    public void setOptions(Options options)
    {
        for (Entry<String, Serializable> option : options.entries())
        {
            this.setOption(option.getKey(), option.getValue());
        }
    }

    // Statements //
    /**
     * Registers a jQuery event callback
     * @param event the jQuery event (ie: "click")
     * @param callback the jQuery callback
     */
    protected void on(String event, String callback)
    {
        this.on(this.selector, event, callback);
    }

    /**
     * Registers a jQuery event callback
     * @param selector the html selector (ie: "#myId")
     * @param event the jQuery event (ie: "click")
     * @param callback the jQuery callback
     */
    protected void on(String selector, String event, String callback)
    {
        if (this.events == null)
        {
            this.events = new ArrayList<String>();
        }

        this.events.add(String.format("jQuery('%s').on('%s', %s);", selector, event, callback));
    }

    @Override
    protected String $()
    {
        return JQueryBehavior.$(this.selector, this.method, this.options.toString());
    }

    /**
     * Gets the jQuery statement.<br/>
     * <b>Warning: </b> This method is *not* called by the behavior directly (only {@link #$()} is).
     * @param options the list of options to be supplied to the current method
     * @return Statement like 'jQuery(function() { ... })'
     */
    public String $(Object... options)
    {
        return this.$(Options.fromList(options));
    }

    /**
     * Gets the jQuery statement.<br/>
     * <b>Warning: </b> This method is *not* called by the behavior directly (only {@link #$()} is).
     * @param options the options to be supplied to the current method
     * @return Statement like 'jQuery(function() { ... })'
     */
    public String $(String options)
    {
        return JQueryBehavior.$(this.selector, this.method, options);
    }

    /**
     * Gets the jQuery statement.
     * @param selector the html selector (ie: "#myId")
     * @param method the jQuery method to invoke
     * @param options the options to be applied
     * @return Statement like 'jQuery(function() { ... })'
     */
    private static String $(String selector, String method, String options)
    {
        return String.format("jQuery(function() { jQuery('%s').%s(%s); });", selector, method, options);
    }

    // Events //
    @Override
    public void onConfigure(Component component)
    {
        super.onConfigure(component);

        if (component instanceof IJQueryWidget)
        {
            ((IJQueryWidget)component).onConfigure(this);
        }
    }

    @Override
    public void beforeRender(Component component)
    {
        super.beforeRender(component);

        if (component instanceof IJQueryWidget)
        {
            ((IJQueryWidget)component).onBeforeRender(this);
        }
    }
}

public abstract class JQueryAbstractBehavior extends Behavior
{
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(JQueryAbstractBehavior.class);

    /**
     * Gets the {@link IJQueryLibrarySettings}
     * @return the {@link IJQueryLibrarySettings}
     */
    public static IJQueryLibrarySettings getJQueryLibrarySettings()
    {
        if (Application.exists() && (Application.get().getJavaScriptLibrarySettings() instanceof IJQueryLibrarySettings))
        {
            return (IJQueryLibrarySettings) Application.get().getJavaScriptLibrarySettings();
        }

        return JQueryLibrarySettings.get();
    }


    /**
     * Behavior name
     */
    private final String name;

    /**
     * Additional references
     */
    private final List<ResourceReference> references;

    /**
     * Constructor.
     * @param name the name of the behavior. It is used in the token so the behavior can be identified in the generated page.
     */
    public JQueryAbstractBehavior(final String name)
    {
        this.name = name;
        this.references = new ArrayList<ResourceReference>();
    }


    /**
     * Adds a reference to be added at {@link #renderHead(Component, IHeaderResponse)} time.
     * @param reference a {@link CssResourceReference}, a {@link JavaScriptResourceReference} or a {@link JQueryPluginResourceReference}
     * @return true (as specified by Collection.add(E))
     */
    public boolean add(ResourceReference reference)
    {
        return this.references.add(reference);
    }

    @Override
    public void renderHead(Component component, IHeaderResponse response)
    {
        // Gets the library settings //
        IJQueryLibrarySettings settings = getJQueryLibrarySettings();

        // jQuery UI resource reference //
        if (settings.getJQueryUIReference() != null)
        {
            response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(settings.getJQueryUIReference())));
        }

        // jQuery Globalize resource reference //
        if (settings.getJQueryGlobalizeReference() != null)
        {
            response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(settings.getJQueryGlobalizeReference())));
        }

        // Additional resource references //
        for(ResourceReference reference : this.references)
        {
            if (reference instanceof CssResourceReference)
            {
                response.render(new PriorityHeaderItem(CssHeaderItem.forReference(reference)));
            }

            if (reference instanceof JavaScriptResourceReference)
            {
                response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(reference)));
            }
        }

        // Adds the statement //
        AjaxRequestTarget target = component.getRequestCycle().find(AjaxRequestTarget.class);

        if (target != null)
        {
            target.appendJavaScript(this.toString());
        }
        else
        {
            this.renderScript(JavaScriptHeaderItem.forScript(this.toString(), this.getToken()), response);
        }
    }

    /**
     * Renders the {@link Behavior}'s javascript<br/>
     * This can be overridden to provides a priority:</br>
     * <code>response.render(new PriorityHeaderItem(item));</code>
     *
     * @param script the {@link JavaScriptHeaderItem}
     * @param response the {@link IHeaderResponse}
     */
    protected void renderScript(JavaScriptHeaderItem script, IHeaderResponse response)
    {
        response.render(script);
    }

    /**
     * Gets the jQuery statement.
     * @return Statement like 'jQuery(function() { ... })'
     */
    protected abstract String $();


    // Properties //

    /**
     * Get the unique behavior token that act as the script id.
     * @return the token
     */
    String getToken()
    {
        return String.format("jquery-%s-%d", this.name, this.hashCode());
    }

    // Events //
    @Override
    public void onConfigure(Component component)
    {
        super.onConfigure(component);

        if (Application.exists() && Application.get().usesDevelopmentConfig())
        {
            if (!Application.get().getMarkupSettings().getStripWicketTags())
            {
                LOG.warn("Application>MarkupSettings>StripWicketTags setting is currently set to false. It is highly recommended to set it to true to prevent widget misbehaviors.");
            }
        }
    }

    @Override
    public final String toString()
    {
        return this.$();
    }
}

public interface IJQueryAjaxAware
{
    void onAjax(AjaxRequestTarget target, JQueryEvent event);
}

interface IDialogListener
{
    /**
     * Indicates whether the default close event (the click on the X-icon) is enabled
     * If true, the {@link #onClose(AjaxRequestTarget, DialogButton)} event will be triggered, with a null {@link DialogButton}
     *
     * @return false by default
     */
    boolean isDefaultCloseEventEnabled();

    /**
     * Triggered when a button is clicked.
     * This method may be overridden to handle button behaviors, but the dialog will not been closed until <code>super.onClick(event)</code> or {@link DialogBehavior#close(AjaxRequestTarget)} is called.
     * @param target the {@link AjaxRequestTarget}
     * @param button the button that closed the dialog
     */
    void onClick(AjaxRequestTarget target, DialogButton button);

    /**
     * Triggered when the dialog closes.
     * @param target the {@link AjaxRequestTarget}
     * @param button the button that closed the dialog
     */
    void onClose(AjaxRequestTarget target, DialogButton button);
}




转载于:https://my.oschina.net/u/1047983/blog/146595

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值