// -*- C++ -*-
/***************************************************************************
 *   Copyright (C) 2004 by Abdiel Janulgue                                 *
 *   xynopsis at users dot sourceforge dot net                             *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#ifndef WJAVASCRIPTSLOT_H_
#define WJAVASCRIPTSLOT_H_

#include "WObject"

namespace Wt {

class WWidget;

/*! \class JSlot WJavaScript WJavaScript
 *  \brief %JSlot implements a slot that is only implemented
 *         in client side JavaScript code.
 *
 * This class provides a hook for adding your own JavaScript to respond to
 * events.
 *
 * Carefully consider the use of this. Not only is writing cross-browser
 * JavaScript hard and tedious, but one must also be aware of possible
 * security problems (see further), and ofcourse, the event handling will
 * not be available when JavaScript is disabled or not present at all.
 * 
 * If you wish to add client side event handling, with automatic
 * fall-back to server-side event handling and without writing
 * JavaScript code with the associated risks and problems, consider
 * using stateless slot implementations instead (see
 * WObject::implementStateless())
 *
 * For some purposes, stateless slot implementations are not
 * sufficient, since they do not allow state inspection. At the same
 * time, the non-availability in case of disabled JavaScript may also
 * be fine for some non-essential functionality (see for example the
 * WSuggestionPopup widget), or when you simply do not care. For these
 * situations a %JSlot can be used to add client-side event handling.
 *
 * A %JSlot must be assigned to a WWidget (through the constructor).
 * This JavaScript code will be associated with that widget, and be
 * invalidated together with that widget.
 *
 * The JavaScript code may be set (or changed) using the setJavaScript
 * function which expects a JavaScript function with the following
 * signature: 
 *
 * \code
 * function(sender, event) {
 *   // handle the event, and sender is a reference to the DOM element
 *   // which captured the event (and holds the signal). Therefore it
 *   // equivalent to the sender for a normal %Wt slot.
 *
 *   return true; // do normal event behaviour
 * }
 * \endcode
 * 
 * In the JavaScript code, you may use WWidget::jsRef() to obtain the
 * DOM element corresponding to any WWidget, or WWidget::id() to
 * obtain the DOM id. In addition you may trigger server-side events
 * using the JavaScript WtSignalEmit function (see JSignal
 * documentation). That's how far we can help you. For the rest you
 * are left to yourself, buggy browsers and quirky JavaScript
 * (http://www.quirksmode.org/ was a reliable companion to me) -- good
 * luck.
 */
class WT_API JSlot
{
public:
  /*! \brief Construct a JavaScript-only slot within the parent scope.
   *
   * The JavaScript will reside within the scope of the given widget.
   * By picking a long-lived parent, one may reuse a single block of
   * JavasCript code for multiple widgets.
   *
   * If parent = 0, then the JavaScript will be inline.
   */
  JSlot(WWidget *parent = 0);

  /*! \brief Destructor.
   */
  ~JSlot();

  /*! \brief Set or modify the JavaScript code associated with the slot.
   *
   * When the slot is triggered, the corresponding JavaScript is executed.
   */
  void setJavaScript(const std::string&);

  /*! \brief Execute the JavaScript code.
   *
   * Execute the JavaScript code, in the same way as when triggered
   * by a EventSignal. This function returns immediately, and execution of
   * the JavaScript code is deferred until after the event handling.
   */
  void exec();

private:
  WWidget *widget_;
  WStatelessSlot* imp_;

  std::string jsFunctionName() const;
  WStatelessSlot* slotimp();

  int fid_;
  static int nextFid_;

  friend class EventSignalBase;
};

typedef JSlot WJavaScriptSlot;

}

#endif
