Пример #1
0
void WWebWidget::updateSignalConnection(DomElement& element,
				     const char *signal,
				     const std::string eventName,
				     const char *condition,
				     bool all, const char *argName)
{
  WSignalInstance_ *s = getSignal(signal);
  if (all
      || s->connectivityChanged()
      || s->staticCodeChanged()) {
    if (isConnected(s))
      element.setEventSignal(eventName, *s, argName, condition);
    else
      element.removeEventSignal(eventName);

    s->connectivityOk();
  }
}
Пример #2
0
void WInteractWidget::updateDom(DomElement& element, bool all)
{
  bool updateKeyDown = false;

  WApplication *app = WApplication::instance();

  /*
   * -- combine enterPress, escapePress and keyDown signals
   */
  EventSignal<> *enterPress = voidEventSignal(ENTER_PRESS_SIGNAL, false);
  EventSignal<> *escapePress = voidEventSignal(ESCAPE_PRESS_SIGNAL, false);
  EventSignal<WKeyEvent> *keyDown = keyEventSignal(KEYDOWN_SIGNAL, false);

  updateKeyDown = (enterPress && enterPress->needsUpdate(all))
    || (escapePress && escapePress->needsUpdate(all))
    || (keyDown && keyDown->needsUpdate(all));

  if (updateKeyDown) {
    std::vector<DomElement::EventAction> actions;

    if (enterPress) {
      if (enterPress->needsUpdate(true)) {
	/*
	 * prevent enterPressed from triggering a changed event on all
	 * browsers except for Opera and IE
	 */
	std::string extraJS;

	const WEnvironment& env = app->environment();

	if (dynamic_cast<WFormWidget *>(this)
	    && !env.agentIsOpera() && !env.agentIsIE())
	  extraJS = "var g=this.onchange;"
	    ""      "this.onchange=function(){this.onchange=g;};";

	actions.push_back
	  (DomElement::EventAction("e.keyCode && (e.keyCode == 13)",
				   enterPress->javaScript() + extraJS,
				   enterPress->encodeCmd(),
				   enterPress->isExposedSignal()));
      }
      enterPress->updateOk();
    }

    if (escapePress) {
      if (escapePress->needsUpdate(true)) {
	actions.push_back
	  (DomElement::EventAction("e.keyCode && (e.keyCode == 27)",
				   escapePress->javaScript(),
				   escapePress->encodeCmd(),
				   escapePress->isExposedSignal()));
      }
      escapePress->updateOk();
    }

    if (keyDown) {
      if (keyDown->needsUpdate(true)) {
	actions.push_back
	  (DomElement::EventAction(std::string(),
				   keyDown->javaScript(),
				   keyDown->encodeCmd(),
				   keyDown->isExposedSignal()));
      }
      keyDown->updateOk();
    }

    if (!actions.empty())
      element.setEvent("keydown", actions);
    else if (!all)
      element.setEvent("keydown", std::string(), std::string());
  }

  /*
   * -- allow computation of dragged mouse distance
   */
  EventSignal<WMouseEvent> *mouseDown
    = mouseEventSignal(MOUSE_DOWN_SIGNAL, false);
  EventSignal<WMouseEvent> *mouseUp
    = mouseEventSignal(MOUSE_UP_SIGNAL, false);
  EventSignal<WMouseEvent> *mouseMove
    = mouseEventSignal(MOUSE_MOVE_SIGNAL, false);
  EventSignal<WMouseEvent> *mouseDrag
    = mouseEventSignal(MOUSE_DRAG_SIGNAL, false);

  bool updateMouseMove
    = (mouseMove && mouseMove->needsUpdate(all))
    || (mouseDrag && mouseDrag->needsUpdate(all));

  bool updateMouseDown
    = (mouseDown && mouseDown->needsUpdate(all))
    || updateMouseMove;

  bool updateMouseUp
    = (mouseUp && mouseUp->needsUpdate(all))
    || updateMouseMove;

  std::string CheckDisabled = "if($(o).hasClass('" +
    app->theme()->disabledClass() +
    "')){" WT_CLASS ".cancelEvent(e);return;}";

  if (updateMouseDown) {
    /*
     * when we have a mouseUp event, we also need a mouseDown event
     * to be able to compute dragDX/Y.
     *
     * When we have:
     *  - a mouseDrag
     *  - or a mouseDown + (mouseMove or mouseUp),
     * we need to capture everything after on mouse down, and keep track of the
     * down button if we have a mouseMove or mouseDrag
     */
    WStringStream js;

    js << CheckDisabled;

    if (mouseUp && mouseUp->isConnected())
      js << app->javaScriptClass() << "._p_.saveDownPos(event);";

    if ((mouseDrag && mouseDrag->isConnected())
	|| (mouseDown && mouseDown->isConnected()
	    && ((mouseUp && mouseUp->isConnected())
		|| (mouseMove && mouseMove->isConnected()))))
      js << WT_CLASS ".capture(this);";

    if ((mouseMove && mouseMove->isConnected())
	|| (mouseDrag && mouseDrag->isConnected()))
      js << WT_CLASS ".mouseDown(e);";

    if (mouseDown) {
      js << mouseDown->javaScript();
      element.setEvent("mousedown", js.str(),
		       mouseDown->encodeCmd(), mouseDown->isExposedSignal());
      mouseDown->updateOk();
    } else
      element.setEvent("mousedown", js.str(), std::string(), false);
  }

  if (updateMouseUp) {
    WStringStream js;

    /*
     * when we have a mouseMove or mouseDrag event, we need to keep track
     * of unpressing the button.
     */
    js << CheckDisabled;

    if ((mouseMove && mouseMove->isConnected())
	|| (mouseDrag && mouseDrag->isConnected()))
      js << WT_CLASS ".mouseUp(e);";
      
    if (mouseUp) {
      js << mouseUp->javaScript();
      element.setEvent("mouseup", js.str(),
		       mouseUp->encodeCmd(), mouseUp->isExposedSignal());
      mouseUp->updateOk();
    } else
      element.setEvent("mouseup", js.str(), std::string(), false);
  }

  if (updateMouseMove) {
    /*
     * We need to mix mouseDrag and mouseMove events.
     */
    std::vector<DomElement::EventAction> actions;
    
    if (mouseMove) {
      actions.push_back
	(DomElement::EventAction(std::string(),
				 mouseMove->javaScript(),
				 mouseMove->encodeCmd(),
				 mouseMove->isExposedSignal()));
      mouseMove->updateOk();
    }

    if (mouseDrag) {
      actions.push_back
	(DomElement::EventAction(WT_CLASS ".buttons",
				 mouseDrag->javaScript()
				 + WT_CLASS ".drag(e);",
				 mouseDrag->encodeCmd(),
				 mouseDrag->isExposedSignal()));
      mouseDrag->updateOk();
    }

    element.setEvent("mousemove", actions);
  }

  /*
   * -- mix mouseClick and mouseDblClick events in mouseclick since we
   *    only want to fire one of both
   */
  EventSignal<WMouseEvent> *mouseClick
    = mouseEventSignal(M_CLICK_SIGNAL, false);
  EventSignal<WMouseEvent> *mouseDblClick
    = mouseEventSignal(DBL_CLICK_SIGNAL, false);  

  bool updateMouseClick
    = (mouseClick && mouseClick->needsUpdate(all))
    || (mouseDblClick && mouseDblClick->needsUpdate(all));

  if (updateMouseClick) {
    WStringStream js;

    js << CheckDisabled;

    if (mouseDrag)
      js << "if (" WT_CLASS ".dragged()) return;";

    if (mouseDblClick && mouseDblClick->needsUpdate(all)) {
      /*
       * Click: if timer is running:
       *  - clear timer, dblClick()
       *  - start timer, clear timer and click()
       */

      /* We have to prevent this immediately ! */
      if (mouseClick) {
	if (mouseClick->defaultActionPrevented() ||
	    mouseClick->propagationPrevented()) {
	  js << WT_CLASS ".cancelEvent(e";
	  if (mouseClick->defaultActionPrevented() &&
	      mouseClick->propagationPrevented())
	    js << ");";
	  else if (mouseClick->defaultActionPrevented())
	    js << ",0x2);";
	  else
	    js << ",0x1);";
	}
      }

      js << "if(" WT_CLASS ".isDblClick(o, e)) {"
	 << mouseDblClick->javaScript();

      if (mouseDblClick->isExposedSignal())
	js << app->javaScriptClass()
		 << "._p_.update(o,'" << mouseDblClick->encodeCmd()
		 << "',e,true);";

      mouseDblClick->updateOk();

      js <<
	"}else{"
	"""if (" WT_CLASS ".isIElt9 && document.createEventObject) "
	""  "e = document.createEventObject(e);"
	"""o.wtE1 = e;"
	"""o.wtClickTimeout = setTimeout(function() {"
	""   "o.wtClickTimeout = null; o.wtE1 = null;";

      if (mouseClick) {
	js << mouseClick->javaScript();

	if (mouseClick->isExposedSignal()) {
	  js << app->javaScriptClass()
		   << "._p_.update(o,'" << mouseClick->encodeCmd()
		   << "',e,true);";
	}

	mouseClick->updateOk();
      }

      const Configuration& conf = app->environment().server()->configuration();
      js << "}," << conf.doubleClickTimeout() << ");}";
    } else {
      if (mouseClick && mouseClick->needsUpdate(all)) {
	js << mouseClick->javaScript();

	if (mouseClick->isExposedSignal()) {
	  js << app->javaScriptClass()
	     << "._p_.update(o,'" << mouseClick->encodeCmd()
	     << "',e,true);";
	}

	mouseClick->updateOk();
      }
    }

    element.setEvent(CLICK_SIGNAL, js.str(),
		     mouseClick ? mouseClick->encodeCmd() : "");

    if (mouseDblClick) {
      if (app->environment().agentIsIElt(9))
	element.setEvent("dblclick", "this.onclick()");
    }
  }

  /*
   * -- mouseOver with delay
   */
  EventSignal<WMouseEvent> *mouseOver
    = mouseEventSignal(MOUSE_OVER_SIGNAL, false);
  EventSignal<WMouseEvent> *mouseOut
    = mouseEventSignal(MOUSE_OUT_SIGNAL, false); 

  bool updateMouseOver = mouseOver && mouseOver->needsUpdate(all);

  if (mouseOverDelay_) {
    if (updateMouseOver) {
      WStringStream js;
      js << "o.over=setTimeout(function() {"
	 << "o.over = null;"
	 << mouseOver->javaScript();

      if (mouseOver->isExposedSignal()) {
	js << app->javaScriptClass()
	   << "._p_.update(o,'" << mouseOver->encodeCmd() << "',e,true);";
      }

      js << "}," << mouseOverDelay_ << ");";

      element.setEvent("mouseover", js.str(), "");

      mouseOver->updateOk();

      if (!mouseOut)
	mouseOut = mouseEventSignal(MOUSE_OUT_SIGNAL, true);

      element.setEvent("mouseout",
		       "clearTimeout(o.over); o.over=null;"
		       + mouseOut->javaScript(),
		       mouseOut->encodeCmd(), mouseOut->isExposedSignal());
      mouseOut->updateOk();
    }
  } else {
    if (updateMouseOver) {
      element.setEventSignal("mouseover", *mouseOver);
      mouseOver->updateOk();
    }

    bool updateMouseOut = mouseOut && mouseOut->needsUpdate(all);

    if (updateMouseOut) {
      element.setEventSignal("mouseout", *mouseOut);
      mouseOut->updateOk();
    }
  }

  updateEventSignals(element, all);

  WWebWidget::updateDom(element, all);
}