Example #1
0
User AuthModel::processAuthToken()
{
  WApplication *app = WApplication::instance();
  const WEnvironment& env = app->environment();

  if (baseAuth()->authTokensEnabled()) {
    const std::string *token =
      env.getCookie(baseAuth()->authTokenCookieName());

    if (token) {
      AuthTokenResult result = baseAuth()->processAuthToken(*token, users());

      switch(result.state()) {
      case AuthTokenState::Valid: {
        if (!result.newToken().empty()) {
          /*
           * Only extend the validity from what we had currently.
           */
          app->setCookie(baseAuth()->authTokenCookieName(), result.newToken(),
                         result.newTokenValidity(), "", "", app->environment().urlScheme() == "https");
        }

	return result.user();
      }
      case AuthTokenState::Invalid:
        app->setCookie(baseAuth()->authTokenCookieName(),std::string(), 0, "", "", app->environment().urlScheme() == "https");

	return User();
      }
    }
  }

  return User();
}
Example #2
0
WDialog::DialogCode WDialog::exec(const WAnimation& animation)
{
  if (recursiveEventLoop_)
    throw WException("WDialog::exec(): already being executed.");

  animateShow(animation);

#ifdef WT_TARGET_JAVA
  if (!WebController::isAsyncSupported())
     throw WException("WDialog#exec() requires a Servlet 3.0 enabled servlet " 
		      "container and an application with async-supported "
		      "enabled.");
#endif

  WApplication *app = WApplication::instance();
  recursiveEventLoop_ = true;

  if (app->environment().isTest()) {
    app->environment().dialogExecuted().emit(this);
    if (recursiveEventLoop_)
      throw WException("Test case must close dialog");
  } else {
    do {
      app->session()->doRecursiveEventLoop();
    } while (recursiveEventLoop_);
  }

  hide();

  return result_;
}
WDefaultLoadingIndicator::WDefaultLoadingIndicator()
{
  setImplementation(std::unique_ptr<WWidget>
		    (new WText(tr("Wt.WDefaultLoadingIndicator.Loading"))));
  setInline(false);
  setStyleClass("Wt-loading");

  WApplication *app = WApplication::instance();

  app->styleSheet().addRule("div.Wt-loading",
			    "background-color: red; color: white;"
			    "font-family: Arial,Helvetica,sans-serif;"
			    "font-size: small;"
			    "position: absolute; right: 0px; top: 0px;");
  app->styleSheet().addRule("body div > div.Wt-loading",
			    "position: fixed;");

  if (app->environment().userAgent().find("MSIE 5.5") != std::string::npos
      || app->environment().userAgent().find("MSIE 6") != std::string::npos)
    app->styleSheet().addRule
      ("div.Wt-loading",
       "right: expression((("
       "ignoreMe2 = document.documentElement.scrollLeft ? "
       "document.documentElement.scrollLeft : "
       "document.body.scrollLeft )) + 'px' );"
       "top: expression((("
       "ignoreMe = document.documentElement.scrollTop ? "
       "document.documentElement.scrollTop : "
       "document.body.scrollTop)) + 'px' );");
}
Example #4
0
WWidget *WItemDelegate::createEditor(const WModelIndex& index,
				     WFlags<ViewItemRenderFlag> flags) const
{
  IndexContainerWidget *const result =
      new IndexContainerWidget(index);
  result->setSelectable(true);

  WLineEdit *lineEdit = new WLineEdit();
  lineEdit->setText(asString(index.data(EditRole), textFormat_));
  lineEdit->enterPressed().connect
    (boost::bind(&WItemDelegate::doCloseEditor, this, result, true));
  lineEdit->escapePressed().connect
    (boost::bind(&WItemDelegate::doCloseEditor, this, result, false));
  lineEdit->escapePressed().preventPropagation();

  if (flags & RenderFocused)
    lineEdit->setFocus(true);

  // We use a layout so that the line edit fills the entire cell.
  // Somehow, this does not work with konqueror, but it does respond
  // properly to width, height being set to 100% !
  WApplication *app = WApplication::instance();
  if (app->environment().agent() != WEnvironment::Konqueror) {
    result->setLayout(new WHBoxLayout());
    result->layout()->setContentsMargins(1, 1, 1, 1);
    result->layout()->addWidget(lineEdit);
  } else {
    lineEdit->resize(WLength(100, WLength::Percentage),
		     WLength(100, WLength::Percentage));
    result->addWidget(lineEdit);
  }

  return result;
}
Example #5
0
void WTextEdit::initTinyMCE()
{
  const char *THIS_JS = "js/WTextEdit.js";

  WApplication *app = WApplication::instance();

  if (!app->javaScriptLoaded(THIS_JS)) {
    if (app->environment().ajax())
      app->doJavaScript("window.tinyMCE_GZ = { loaded: true };", false);

    int version = getTinyMCEVersion();

    std::string folder = version == 3 ? "tiny_mce/" : "tinymce/";
    std::string jsFile = version == 3 ? "tiny_mce.js" : "tinymce.js";

    std::string tinyMCEBaseURL = WApplication::relativeResourcesUrl() + folder;
    WApplication::readConfigurationProperty("tinyMCEBaseURL", tinyMCEBaseURL);

    if (!tinyMCEBaseURL.empty()
	&& tinyMCEBaseURL[tinyMCEBaseURL.length()-1] != '/')
      tinyMCEBaseURL += '/';

    app->require(tinyMCEBaseURL + jsFile, "window['tinyMCE']");
    app->styleSheet().addRule(".mceEditor",
			      "display: block; position: absolute;");

    LOAD_JAVASCRIPT(app, THIS_JS, "WTextEdit", wtjs1);
  }
}
Example #6
0
void WFormWidget::setEmptyText(const WString& emptyText) 
{
  emptyText_ = emptyText;

  WApplication* app = WApplication::instance();
  const WEnvironment& env = app->environment();

  if (env.ajax()) {
    if (!emptyText_.empty()) {
      if (!flags_.test(BIT_JS_OBJECT))
	defineJavaScript();
      else
	updateEmptyText();

      if (!removeEmptyText_) {
	removeEmptyText_ = new JSlot(this);
      
	focussed().connect(*removeEmptyText_);
	blurred().connect(*removeEmptyText_);
	keyWentDown().connect(*removeEmptyText_);

	std::string jsFunction = 
	  "function(obj, event) {"
	  """jQuery.data(" + jsRef() + ", 'obj').applyEmptyText();"
	  "}";
	removeEmptyText_->setJavaScript(jsFunction);
      }
    } else {
      delete removeEmptyText_;
      removeEmptyText_ = 0;
    }
  } else {
    setToolTip(emptyText);
  }
}
Example #7
0
void WWidgetVectorPainter::updateContents(std::vector<DomElement *>& result,
					  WPaintDevice *device)
{
  WVectorImage *vectorDevice = dynamic_cast<WVectorImage *>(device);

  if (widget_->repaintFlags_ & PaintUpdate) {
    DomElement *painter = DomElement::updateGiven
      (WT_CLASS ".getElement('p" + widget_->id()+ "').firstChild",
       DomElement_DIV);

    painter->setProperty(PropertyAddedInnerHTML, vectorDevice->rendered());

    WApplication *app = WApplication::instance();
    if (app->environment().agentIsOpera())
      painter->callMethod("forceRedraw();");

    result.push_back(painter);
  } else {
    DomElement *canvas = DomElement::getForUpdate
      ('p' + widget_->id(), DomElement_DIV);

    /*
     * In fact, we should use another property, since we could be using
     * document.importNode() instead of myImportNode() since the xml does not
     * need to be interpreted as HTML...
     */
    canvas->setProperty(PropertyInnerHTML, vectorDevice->rendered());
    result.push_back(canvas);
  }

  widget_->sizeChanged_ = false;

  delete device;
}
Example #8
0
void WCssTheme::applyValidationStyle(WWidget *widget,
				     const Wt::WValidator::Result& validation,
				     WFlags<ValidationStyleFlag> styles) const
{
  WApplication *app = WApplication::instance();

  LOAD_JAVASCRIPT(app, "js/CssThemeValidate.js", "validate", wtjs1);
  LOAD_JAVASCRIPT(app, "js/CssThemeValidate.js", "setValidationState", wtjs2);

  if (app->environment().ajax()) {
    WStringStream js;
    js << WT_CLASS ".setValidationState(" << widget->jsRef() << ","
       << (validation.state() == WValidator::Valid ? 1 : 0) << ","
       << validation.message().jsStringLiteral() << ","
       << styles.value() << ");";

    widget->doJavaScript(js.str());
  } else {
    bool validStyle
      = (validation.state() == WValidator::Valid) && 
      (styles & ValidationValidStyle);
    bool invalidStyle
      = (validation.state() != WValidator::Valid) && 
      (styles & ValidationInvalidStyle);

    widget->toggleStyleClass("Wt-valid", validStyle);
    widget->toggleStyleClass("Wt-invalid", invalidStyle);
  }
}
Example #9
0
bool WStackedWidget::loadAnimateJS()
{
  WApplication *app = WApplication::instance();

  if (app->environment().supportsCss3Animations()) {
    LOAD_JAVASCRIPT(app, "js/WStackedWidget.js", "WStackedWidget", wtjs1);
    return true;
  } else
    return false;
}
Example #10
0
void WDialog::render(WFlags<RenderFlag> flags)
{
  if (flags & RenderFull) {
    WApplication *app = WApplication::instance();

    bool centerX = offset(Left).isAuto() && offset(Right).isAuto(),
      centerY = offset(Top).isAuto() && offset(Bottom).isAuto();

    /*
     * Make sure layout adjusts to contents preferred width, especially
     * important for IE workaround which uses static position scheme
     */
    if (app->environment().ajax())
      if (width().isAuto())
	if (maximumWidth().unit() == WLength::Percentage ||
	    maximumWidth().toPixels() == 0)
	  impl_->resolveWidget("layout")->setMaximumSize(999999, maximumHeight());

    doJavaScript("new " WT_CLASS ".WDialog("
		 + app->javaScriptClass() + "," + jsRef()
		 + "," + titleBar_->jsRef()
		 + "," + (centerX ? "1" : "0")
		 + "," + (centerY ? "1" : "0") + ");");

    /*
     * When a dialog is shown immediately for a new session, the recentering
     * logic comes too late and causes a glitch. Thus we include directly in
     * the HTML a JavaScript block to mitigate that
     */
    if (!app->environment().agentIsIElt(9)) {
      std::string js = WString::tr("Wt.WDialog.CenterJS").toUTF8();
      Utils::replace(js, "$el", "'" + id() + "'");
      Utils::replace(js, "$centerX", centerX ? "1" : "0");
      Utils::replace(js, "$centerY", centerY ? "1" : "0");

      impl_->bindString
	("center-script", "<script>" + js + "</script>", XHTMLUnsafeText);
    } else
      impl_->bindEmpty("center-script");
  }

  WCompositeWidget::render(flags);
}
Example #11
0
std::vector<WCssStyleSheet> WCssTheme::styleSheets() const
{
  std::vector<WCssStyleSheet> result;

  if (!name_.empty()) {
    std::string themeDir = resourcesUrl();

    WApplication *app = WApplication::instance();

    result.push_back(WCssStyleSheet(WLink(themeDir + "wt.css")));

    if (app->environment().agentIsIE())
      result.push_back(WCssStyleSheet(WLink(themeDir + "wt_ie.css")));

    if (app->environment().agent() == WEnvironment::IE6)
      result.push_back(WCssStyleSheet(WLink(themeDir + "wt_ie6.css")));
  }

  return result;
}
Example #12
0
void WPushButton::doRedirect()
{
  WApplication *app = WApplication::instance();

  if (!app->environment().ajax()) {
    if (linkState_.link.type() == WLink::InternalPath)
      app->setInternalPath(linkState_.link.internalPath().toUTF8(), true);
    else
      app->redirect(linkState_.link.url());
  }
}
Example #13
0
void AuthModel::setRememberMeCookie(const User& user)
{
  WApplication *app = WApplication::instance();
  const AuthService *s = baseAuth();

  app->setCookie(s->authTokenCookieName(),
		 s->createAuthToken(user),
		 s->authTokenValidity() * 60,
		 s->authTokenCookieDomain(),
		 "",
		 app->environment().urlScheme() == "https");
}
Example #14
0
void MessageBox::setHidden(bool hidden, const WAnimation& animation)
{
  if (hidden != hidden_) {
    hidden_ = hidden;

    WApplication *app = WApplication::instance();

    if (!hidden)
      setExposeMask(app);
    else
      restoreExposeMask(app);
 
    if (hidden)
      app->doJavaScript(elRef() + ".hide();");
    else {
      std::stringstream config;
      config << "{a:0";
      createConfig(config);
      config << "}";

      std::string var;
      if (firstDisplay_) {
	var = elRef() + "=Ext.Msg";

	/* fix cursor problem in FF 1.5, 2 */
	if (!app->environment().agentIsIE())
	  app->doJavaScript
	  ("Ext.Msg.getDialog().on('show', function(d) {"
	   "var div = Ext.get(d.el);"
	   "div.setStyle('overflow', 'auto');"
	   "var text = div.select('.ext-mb-textarea', true);"
	   "if (!text.item(0))"
	   "text = div.select('.ext-mb-text', true);"
	   "if (text.item(0))"
	   "text.item(0).dom.select();});");
      } else
	var = elRef();

      WApplication::instance()
	->doJavaScript(var + ".show(" + config.str() + ");");

      if (progress_) {
	WApplication::instance()
	  ->doJavaScript(elRef() + ".updateProgress("
			 + boost::lexical_cast<std::string>(progressValue_)
			 + ");");
      }

      firstDisplay_ = false;
    }
  }
}
Example #15
0
void WTimer::gotTimeout()
{
  if (active_) {
    if (!singleShot_) {
      *timeout_ = Time() + static_cast<int>(interval_.count());
      if (!timerWidget_->jsRepeat()) {
        WApplication *app = WApplication::instance();
        timerWidget_->timerStart(app->environment().ajax());
      }
    } else
      stop();
  }
}
Example #16
0
WPopupMenuItem *WPopupMenu::exec(const WPoint& p)
{
  if (recursiveEventLoop_)
    throw WException("WPopupMenu::exec(): already being executed.");

  WApplication *app = WApplication::instance();
  recursiveEventLoop_ = true;

  popup(p);

  if (app->environment().isTest()) {
    app->environment().popupExecuted().emit(this);
    if (recursiveEventLoop_)
      throw WException("Test case must close popup menu.");
  } else {
    do {
      app->session()->doRecursiveEventLoop();
    } while (recursiveEventLoop_);
  }

  return result_;
}
Example #17
0
/**
* @brief Get's the cookie from the app
*
* @return The cookie that the client's browser is giving us
*/
const string& BaseSessionHandle::getCookie() const {
    // First ask the browser
    WApplication* app = WApplication::instance();
    const WEnvironment::CookieMap& cookies = app->environment().cookies();
    WEnvironment::CookieMap::const_iterator i = cookies.find(_cookieName);
    if (i != cookies.end()) {
        return (*i).second;
    }
    // Fall back to cached version
    // If the browser doesn't have a cookie, we might have just set it and no requests have happened yet
    // Even if this server side cache is old (and the user has logged out, and the client side cookie deleted)
    // It shouldn't matter because the session store still won't return a user ID for it.
    // But still if there is a browser side cookie, that takes precedence
    return cookieCache;
}
Example #18
0
WMediaPlayer::WMediaPlayer(MediaType mediaType, WContainerWidget *parent)
  : WCompositeWidget(parent),
    mediaType_(mediaType),
    videoWidth_(0),
    videoHeight_(0),
    gui_(this),
    boundSignals_(0)
{
  for (unsigned i = 0; i < 11; ++i)
    control_[i] = 0;

  for (unsigned i = 0; i < 3; ++i)
    display_[i] = 0;

  for (unsigned i = 0; i < 2; ++i)
    progressBar_[i] = 0;

  WTemplate *impl = new WMediaPlayerImpl(this, tr("Wt.WMediaPlayer.template"));
  impl->bindString("gui", std::string());

  setImplementation(impl);

  WApplication *app = WApplication::instance();

  LOAD_JAVASCRIPT(app, "js/WMediaPlayer.js", "WMediaPlayer", wtjs1);

  std::string res = WApplication::relativeResourcesUrl() + "jPlayer/";

  if (!app->environment().ajax())
    app->require(res + "jquery.min.js");

  if (app->require(res + "jquery.jplayer.min.js"))
    app->useStyleSheet(res + "skin/jplayer.blue.monday.css");

  if (mediaType_ == Video)
    setVideoSize(480, 270);

#ifndef WT_TARGET_JAVA
  implementJavaScript(&WMediaPlayer::play,
		      jsPlayerRef() + ".jPlayer('play');");
  implementJavaScript(&WMediaPlayer::pause,
		      jsPlayerRef() + ".jPlayer('pause');");
  implementJavaScript(&WMediaPlayer::stop,
		      jsPlayerRef() + ".jPlayer('stop');");
#endif
}
Example #19
0
StdGridLayoutImpl2::~StdGridLayoutImpl2()
{ 
  WApplication *app = WApplication::instance();

  /*
   * If it is a top-level layout (as opposed to a nested layout),
   * configure overflow of the container.
   */
  if (parentLayoutImpl() == 0) {
    if (container() == app->root()) {
      app->setBodyClass("");
      app->setHtmlClass("");
    }

    if (app->environment().agentIsIElt(9) && container())
      container()->setOverflow(WContainerWidget::OverflowVisible);
  }
}
Example #20
0
void WPushButton::renderHRef(DomElement& element)
{
  if (!linkState_.link.isNull() && !isDisabled()) {
    WApplication *app = WApplication::instance();

    if (!linkState_.clickJS) {
      linkState_.clickJS = new JSlot();
      clicked().connect(*linkState_.clickJS);

      if (!app->environment().ajax())
	clicked().connect(this, &WPushButton::doRedirect);
    }

    if (linkState_.link.type() == WLink::InternalPath)
      linkState_.clickJS->setJavaScript
	("function(){" +
	 app->javaScriptClass() + "._p_.setHash("
	 + jsStringLiteral(linkState_.link.internalPath()) + ",true);"
	 "}");
    else {
      std::string url = linkState_.link.resolveUrl(app);

      if (linkState_.link.target() == TargetNewWindow)
	linkState_.clickJS->setJavaScript
	  ("function(){"
	   "window.open(" + jsStringLiteral(url) + ");"
	   "}");
      else
	linkState_.clickJS->setJavaScript
	  ("function(){"
	   "window.location=" + jsStringLiteral(url) + ";"
	   "}");
    }

    clicked().senderRepaint(); // XXX only for Java port necessary
  } else {
    delete linkState_.clickJS;
    linkState_.clickJS = 0;
  }
}
Example #21
0
void WTimer::start()
{
  WApplication *app = WApplication::instance();
  if (!active_) {
    if (app && app->timerRoot())
      app->timerRoot()->addWidget(std::move(uTimerWidget_));
  }

  active_ = true;
  *timeout_ = Time() + static_cast<int>(interval_.count());

  bool jsRepeat = !singleShot_ &&
                  ((app && app->environment().ajax()) ||
                   !timeout().isExposedSignal());

  timerWidget_->timerStart(jsRepeat);

  if (!timeoutConnected_) {
    timeout().connect(this, &WTimer::gotTimeout);
    timeoutConnected_ = true;
  }
}
CgiEnv::CgiEnv()
    : m_pimpl(make_unique<CgiEnv::Impl>(this))
{
    WApplication *app = WApplication::instance();

    m_pimpl->ClientInfoIP = app->environment().clientAddress();
    m_pimpl->ClientInfoBrowser = app->environment().userAgent();
    m_pimpl->ClientInfoReferer = app->environment().referer();

    m_pimpl->ExtractClientInfoDetail();

    m_pimpl->ClientInfoLocation =
        (format("%1% %2% %3% %4% %5% %6%")
         % ClientInfoRecord.city
         % ClientInfoRecord.region
         % ClientInfoRecord.country_code
         % ClientInfoRecord.country_code3
         % ClientInfoRecord.country_name
         % ClientInfoRecord.continent_code).str();
    if (ClientInfoRecord.latitude != "" && ClientInfoRecord.longitude != "") {
        m_pimpl->ClientInfoLocation +=
            (format(" %1%,%2%")
             % ClientInfoRecord.latitude
             % ClientInfoRecord.longitude).str();
    }
    algorithm::trim(m_pimpl->ClientInfoLocation);

    m_pimpl->ServerInfoHost = app->environment().hostName();
    m_pimpl->ServerInfoURL = app->environment().urlScheme() + "://" + m_pimpl->ServerInfoHost;
    m_pimpl->ServerInfoRootLoginUrl = m_pimpl->ServerInfoURL
                                      + (algorithm::ends_with(m_pimpl->ServerInfoURL, "/") ? "" : "/")
                                      + "?root";
    m_pimpl->ServerInfoNoReplyAddr = "no-reply@" + m_pimpl->ServerInfoHost;

    string queryStr = app->environment().getCgiValue("QUERY_STRING");
    m_pimpl->FoundXSS = (queryStr.find("<") != string::npos ||
                         queryStr.find(">") != string::npos ||
                         queryStr.find("%3C") != string::npos ||
                         queryStr.find("%3E") != string::npos ||
                         queryStr.find("%3c") != string::npos ||
                         queryStr.find("%3e") != string::npos)
                        ? true : false;

    bool logout = false;

    SubscriptionData.Subscribe = Subscription::Action::None;

    Http::ParameterMap map = app->environment().getParameterMap();
    for (std::map<string, Http::ParameterValues>::const_iterator it = map.begin(); it != map.end(); ++it) {
        if (it->first == "lang") {
            auto itLang = m_pimpl->LanguageMapper.right.find(it->second[0]);
            if (itLang != m_pimpl->LanguageMapper.right.end()) {
                m_pimpl->CurrentLanguage = itLang->second;
            } else {
                m_pimpl->CurrentLanguage = Language::Invalid;
            }
        }

        if (it->first == "root") {
            m_pimpl->IsRootLoginRequested = true;
        }

        if (it->first == "logout") {
            logout = true;
        }

        if (it->first == "subscribe" && it->second[0] != "") {
            try {
                if (it->second[0] == "1" || it->second[0] == "2"
                        || it->second[0] == "-1" || it->second[0] == "-2") {
                    auto action = lexical_cast<short>(it->second[0]);
                    SubscriptionData.Subscribe = static_cast<Subscription::Action>(action);
                }
            } catch (...) {
                SubscriptionData.Subscribe = Subscription::Action::Subscribe;
            }
        }

        if (it->first == "inbox" && it->second[0] != "") {
            static const regex REGEX(Pool::Storage()->RegexEmail());
            smatch result;
            if (regex_search(it->second[0], result, REGEX)) {
                SubscriptionData.Inbox.assign(it->second[0]);
            }
        }

        if (it->first == "subscription" && it->second[0] != "") {
            static const regex REGEX(Pool::Storage()->RegexLanguageArray());
            smatch result;
            if (regex_search(it->second[0], result, REGEX)) {
                vector<string> vec;
                split(vec, it->second[0], boost::is_any_of(","));
                vector<Subscription::Language> langs;
                for (const auto &s : vec) {
                    if (s == "en") {
                        langs.push_back(Subscription::Language::En);
                    } else if (s == "fa") {
                        langs.push_back(Subscription::Language::Fa);
                    }
                }
                SubscriptionData.Languages = std::move(langs);
            }
        }

        if (it->first == "recipient" && it->second[0] != "") {
            static const regex REGEX(Pool::Storage()->RegexUuid());
            smatch result;
            if (regex_search(it->second[0], result, REGEX)) {
                SubscriptionData.Uuid.assign(it->second[0]);
            }
        }

        if (it->first == "token" && it->second[0] != "") {
            try {
                string token;
                Pool::Crypto()->Decrypt(it->second[0], token);
                SubscriptionData.Timestamp = lexical_cast<time_t>(token);
            } catch (...) {
            }
        }

        if (it->first == "contact-form") {
            m_pimpl->IsContactFormRequested = true;
        }
    }

    if (m_pimpl->IsRootLoginRequested && logout) {
        m_pimpl->IsRootLogoutRequested = true;
    }
}
Example #23
0
void WContainerWidget::updateDom(DomElement& element, bool all)
{
  if (all && element.type() == DomElement_LI && isInline())
    element.setProperty(PropertyStyleDisplay, "inline");

  if (flags_.test(BIT_CONTENT_ALIGNMENT_CHANGED) || all) {
    AlignmentFlag hAlign = contentAlignment_ & AlignHorizontalMask;

    bool ltr = WApplication::instance()->layoutDirection() == LeftToRight;

    switch (hAlign) {
    case AlignLeft:
      if (flags_.test(BIT_CONTENT_ALIGNMENT_CHANGED))
	element.setProperty(PropertyStyleTextAlign, ltr ? "left" : "right");
      break;
    case AlignRight:
      element.setProperty(PropertyStyleTextAlign, ltr ? "right" : "left");
      break;
    case AlignCenter:
      element.setProperty(PropertyStyleTextAlign, "center");
      break;
    case AlignJustify:
#ifndef WT_NO_LAYOUT
      if (!layout_)
#endif // WT_NO_LAYOUT
	element.setProperty(PropertyStyleTextAlign, "justify");
      break;
    default:
      break;
    }

    if (domElementType() == DomElement_TD) {
      AlignmentFlag vAlign = contentAlignment_ & AlignVerticalMask;
      switch (vAlign) {
      case AlignTop:
	if (flags_.test(BIT_CONTENT_ALIGNMENT_CHANGED))
	  element.setProperty(PropertyStyleVerticalAlign, "top");
	break;
      case AlignMiddle:
	element.setProperty(PropertyStyleVerticalAlign, "middle");
	break;
      case AlignBottom:
	element.setProperty(PropertyStyleVerticalAlign, "bottom");
      default:
	break;
      }
    }
  }

  if (flags_.test(BIT_ADJUST_CHILDREN_ALIGN)
      || flags_.test(BIT_CONTENT_ALIGNMENT_CHANGED) || all) {
    /*
     * Welcome to CSS hell.
     *
     * Apparently, the text-align property only applies to inline elements.
     * To center non-inline children, the standard says to set its left and
     * right margin to 'auto'.
     *
     * I assume the same applies for aligning to the right ?
     */
    for (unsigned i = 0; i < children_->size(); ++i) {
      WWidget *child = (*children_)[i];

      if (!child->isInline()) {
	AlignmentFlag ha = contentAlignment_ & AlignHorizontalMask;
	if (ha == AlignCenter) {
	  if (!child->margin(Left).isAuto())
	    child->setMargin(WLength::Auto, Left);
	  if (!child->margin(Right).isAuto())
	    child->setMargin(WLength::Auto, Right);
	} else if (ha == AlignRight) {
	  if (!child->margin(Left).isAuto())
	    child->setMargin(WLength::Auto, Left);
	}
      }
    }

    flags_.reset(BIT_CONTENT_ALIGNMENT_CHANGED);
    flags_.reset(BIT_ADJUST_CHILDREN_ALIGN);
  }

  if (flags_.test(BIT_PADDINGS_CHANGED)
      || (all && padding_ &&
	  !(   padding_[0].isAuto() && padding_[1].isAuto()
	    && padding_[2].isAuto() && padding_[3].isAuto()))) {

    if ((padding_[0] == padding_[1])
	&& (padding_[0] == padding_[2])
	&& (padding_[0] == padding_[3]))
      element.setProperty(PropertyStylePadding,
			  padding_[0].cssText());
    else
      element.setProperty(PropertyStylePadding,
			  padding_[0].cssText()
			  + " " + padding_[1].cssText()
			  + " " + padding_[2].cssText()
			  + " " + padding_[3].cssText());

    flags_.reset(BIT_PADDINGS_CHANGED);
  }

  WInteractWidget::updateDom(element, all);

  if (flags_.test(BIT_OVERFLOW_CHANGED)
      || (all && overflow_ &&
	  !(overflow_[0] == OverflowVisible
	    && overflow_[1] == OverflowVisible))) {
    static const char *cssText[] = { "visible", "auto", "hidden", "scroll" };

    element.setProperty(PropertyStyleOverflowX, cssText[overflow_[0]]);
    element.setProperty(PropertyStyleOverflowY, cssText[overflow_[1]]);

    flags_.reset(BIT_OVERFLOW_CHANGED);

    /* If a container widget has overflow, then, if ever something
     * inside it has position scheme relative/absolute, it will not
     * scroll properly unless every element up to the container and including 
     * the container itself has overflow: relative.
     *
     * The following fixes the common case:
     * container (overflow) - container - layout
     */
    WApplication *app = WApplication::instance();
    if (app->environment().agentIsIE()
	&& (overflow_[0] == OverflowAuto || overflow_[0] == OverflowScroll))
      if (positionScheme() == Static)
	element.setProperty(PropertyStylePosition, "relative");
  }
}
Example #24
0
File: Widget.C Project: ReWeb3D/wt
void Widget::initExt()
{
  std::string extBaseURL = "ext";
  WApplication::readConfigurationProperty("extBaseURL", extBaseURL);

  if (!extBaseURL.empty() && extBaseURL[extBaseURL.length()-1] != '/')
    extBaseURL += '/';

  WApplication *app = WApplication::instance();

  if (app->require(extBaseURL + "ext-base.js", "window['Ext']")) {
    app->require(extBaseURL + "ext-all.js", "window.Ext['DomHelper']");
    app->useStyleSheet(extBaseURL + "resources/css/ext-all.css");

    // fixes for Firefox 3:
    app->styleSheet().addRule(".x-date-middle", "width:130px;");

    // rendering glitches on all browsers:
    app->styleSheet().addRule(".ext-gecko .x-form-text", "margin-top: -1px;");
    app->styleSheet().addRule(".ext-safari .x-form-text", "margin-top: -1px;");
    app->styleSheet().addRule(".ext-ie .x-form-text",
			      "margin-top: 0px !important;"
			      "margin-bottom: 0px !important;");
    app->doJavaScript(/*app->javaScriptClass() + '.' + */ "ExtW = new Array();"
		      "Ext.QuickTips.init();"
		      "Ext.BLANK_IMAGE_URL='" + extBaseURL 
		      + "resources/images/default/s.gif';", false);
    app->declareJavaScriptFunction("deleteExtW",
				   "" "function(id){"
				   ""   "var w=ExtW[id];"
				   ""   "if(w){"
				   ""      "if (w.el && w.destroy) w.destroy();"
				   ""      "delete ExtW[id];"
				   ""   "}"
				   "" "}");

    if (app->environment().agentIsIE())
      app->doJavaScript
	("if ((typeof Range !== 'undefined')"
	 ""    "&& !Range.prototype.createContextualFragment) {"
	 """Range.prototype.createContextualFragment = function(html) {"
	 ""  "var startNode = this.startContainer;"
	 ""  "var doc = startNode.nodeType == 9 ? startNode :"
	 ""            "startNode.ownerDocument;"
	 ""  "var container = doc.createElement('div');"
	 ""  "container.innerHTML = html;"
	 ""  "var frag = doc.createDocumentFragment(), n;"
	 ""  "while ( (n = container.firstChild) ) {"
	 ""    "frag.appendChild(n);"
	 ""  "}"
	 ""  "return frag;"
	 """};"
	 "}", false);
    /*
     * Normally, Ext does this in its onReady function, but this is not
     * fired when loading ExtJS on demand.
     */
    std::string bodyClass;
    if (app->environment().agentIsIE()) {
      bodyClass = " ext-ie ";
      bodyClass += app->environment().agent() == WEnvironment::IE6
	? "ext-ie6" : "ext-ie7 ";
    } else if (app->environment().agentIsSafari())
      bodyClass = " ext-safari";
    else if (app->environment().agentIsOpera())
      bodyClass = " ext-opera";
    else if (app->environment().agentIsGecko())
      bodyClass = " ext-gecko";

    const std::string& ua = app->environment().userAgent();

    if (ua.find("Linux") != std::string::npos)
      bodyClass += " ext-linux";
    if (ua.find("Macintosh") != std::string::npos
	|| ua.find("Mac OS X") != std::string::npos)
      bodyClass += " ext-mac";
    
    app->setBodyClass(app->bodyClass() + bodyClass);
    app->setHtmlClass(app->htmlClass() + " ext-strict");
  }
}
Example #25
0
void WAbstractToggleButton::updateDom(DomElement& element, bool all)
{
  WApplication *app = WApplication::instance();
  const WEnvironment& env = app->environment();

  DomElement *input = 0;
  DomElement *span = 0;
  DomElement *label = 0;

  // Already apply theme here because it may determine its organization
  if (all)
    app->theme()->apply(this, element, 1);

  if (element.type() == DomElement_INPUT)
    input = &element;
  else {
    if (all) {
      input = DomElement::createNew(DomElement_INPUT);
      input->setName("in" + id());

      span = DomElement::createNew(DomElement_SPAN);
      span->setName("t" + id());
 
      if (element.type() != DomElement_LABEL) {
	label = DomElement::createNew(DomElement_LABEL);
	label->setName("l" + id());
      }
    } else {
      input = DomElement::getForUpdate("in" + id(), DomElement_INPUT);
      span = DomElement::getForUpdate("t" + id(), DomElement_SPAN);
    }
  }

  if (all)
    updateInput(*input, all);

  EventSignal<> *check = voidEventSignal(CHECKED_SIGNAL, false);
  EventSignal<> *uncheck = voidEventSignal(UNCHECKED_SIGNAL, false);
  EventSignal<> *change = voidEventSignal(CHANGE_SIGNAL, false);
  EventSignal<WMouseEvent> *click = mouseEventSignal(M_CLICK_SIGNAL, false);

  /*
   * We piggy-back the checked and uncheck signals on the change signal.
   *
   * If agent is IE, then we piggy-back the change on the clicked signal.
   */
  bool piggyBackChangeOnClick = env.agentIsIE();

  bool needUpdateChangeSignal =
    (change && change->needsUpdate(all))
    || (check && check->needsUpdate(all))
    || (uncheck && uncheck->needsUpdate(all));

  bool needUpdateClickedSignal =
    (click && click->needsUpdate(all))
     || (piggyBackChangeOnClick && needUpdateChangeSignal);

  WFormWidget::updateDom(*input, all);

  /*
   * Copy all properties to the exterior element, as they relate to style,
   * etc... We ignore here attributes (except for tooltip),
   * see WWebWidget: other attributes need not be moved.
   *
   * But -- bug #423, disabled and readonly are properties that should be
   * kept on the interior element.
   */
  if (&element != input) {
    if (element.properties().find(PropertyClass) != element.properties().end())
      input->addPropertyWord(PropertyClass, element.getProperty(PropertyClass));
    element.setProperties(input->properties());
    input->clearProperties();

    std::string v = element.getProperty(Wt::PropertyDisabled);
    if (!v.empty()) {
      input->setProperty(Wt::PropertyDisabled, v);
      element.removeProperty(Wt::PropertyDisabled);
    }

    v = element.getProperty(Wt::PropertyReadOnly);
    if (!v.empty()) {
      input->setProperty(Wt::PropertyReadOnly, v);
      element.removeProperty(Wt::PropertyReadOnly);
    }

    v = input->getAttribute("title");
    if (!v.empty())
      element.setAttribute("title", v);
  }

  if (flags_.test(BIT_STATE_CHANGED) || all) {
    input->setProperty(Wt::PropertyChecked,
		       state_ == Unchecked ? "false" : "true");

    if (supportsIndeterminate(env))
      input->setProperty(Wt::PropertyIndeterminate,
			 state_ == PartiallyChecked ? "true" : "false");
    else
      input->setProperty(Wt::PropertyStyleOpacity,
			 state_ == PartiallyChecked ? "0.5" : "");

	flags_.reset(BIT_STATE_CHANGED);
  }

  std::vector<DomElement::EventAction> changeActions;

  if (needUpdateChangeSignal
      || (piggyBackChangeOnClick && needUpdateClickedSignal)
      || all) {
    std::string dom = "o";

    if (check) {
      if (check->isConnected())
	changeActions.push_back
	  (DomElement::EventAction(dom + ".checked",
				   check->javaScript(),
				   check->encodeCmd(),
				   check->isExposedSignal()));
      check->updateOk();
    }

    if (uncheck) {
      if (uncheck->isConnected())
	changeActions.push_back
	  (DomElement::EventAction("!" + dom + ".checked",
				   uncheck->javaScript(),
				   uncheck->encodeCmd(),
				   uncheck->isExposedSignal()));
      uncheck->updateOk();
    }

    if (change) {
      if (change->isConnected())
	changeActions.push_back
	  (DomElement::EventAction(std::string(),
				   change->javaScript(),
				   change->encodeCmd(),
				   change->isExposedSignal()));
      change->updateOk();
    }

    if (!piggyBackChangeOnClick) {
      if (!(all && changeActions.empty()))
	input->setEvent("change", changeActions);
    }
  }

  if (needUpdateClickedSignal || all) {
    if (piggyBackChangeOnClick) {
      if (click) {
	changeActions.push_back
	  (DomElement::EventAction(std::string(),
				   click->javaScript(),
				   click->encodeCmd(),
				   click->isExposedSignal()));
	click->updateOk();
      }

      if (!(all && changeActions.empty()))
	input->setEvent(CLICK_SIGNAL, changeActions);
    } else
      if (click)
	updateSignalConnection(*input, *click, CLICK_SIGNAL, all);
  }

  if (span) {
    if (all || flags_.test(BIT_TEXT_CHANGED)) {
      span->setProperty(PropertyInnerHTML, text_.formattedText());
	  if(all || flags_.test(BIT_WORD_WRAP_CHANGED)) {
		span->setProperty(PropertyStyleWhiteSpace, flags_.test(BIT_WORD_WRAP) ? "normal" : "nowrap");
		flags_.reset(BIT_WORD_WRAP_CHANGED);
	  }
	  flags_.reset(BIT_TEXT_CHANGED);
    }
  }

  if (&element != input) {
    if (label) {
      label->addChild(input);
      label->addChild(span);
      element.addChild(label);
    } else {
      element.addChild(input);
      element.addChild(span);
    }
  }
}
void WAbstractToggleButton::updateDom(DomElement& element, bool all)
{
  WApplication *app = WApplication::instance();
  const WEnvironment& env = app->environment();

  DomElement *input = 0;
  DomElement *span = 0;

  if (element.type() == DomElement_LABEL) {
    if (all) {
      input = DomElement::createNew(DomElement_INPUT);
      input->setName("in" + id());

      span = DomElement::createNew(DomElement_SPAN);
      span->setName("l" + id());
    } else {
      input = DomElement::getForUpdate("in" + id(), DomElement_INPUT);
      span = DomElement::getForUpdate("l" + id(), DomElement_SPAN);
    }
  } else
    input = &element;

  if (all)
    updateInput(*input, all);

  EventSignal<> *check = voidEventSignal(CHECKED_SIGNAL, false);
  EventSignal<> *uncheck = voidEventSignal(UNCHECKED_SIGNAL, false);
  EventSignal<> *change = voidEventSignal(CHANGE_SIGNAL, false);
  EventSignal<WMouseEvent> *click = mouseEventSignal(M_CLICK_SIGNAL, false);

  /*
   * We piggy-back the checked and uncheck signals on the change signal.
   *
   * If agent is IE, then we piggy-back the change on the clicked signal.
   */
  bool piggyBackChangeOnClick = env.agentIsIE();

  bool needUpdateChangeSignal =
    (change && change->needsUpdate(all))
    || (check && check->needsUpdate(all))
    || (uncheck && uncheck->needsUpdate(all));

  bool needUpdateClickedSignal =
    (click && click->needsUpdate(all))
     || (piggyBackChangeOnClick && needUpdateChangeSignal);

  WFormWidget::updateDom(*input, all);

  /*
   * Copy all properties to the exterior element, as they relate to style,
   * etc... We ignore here attributes, see WWebWidget: there seems not to
   * be attributes that sensibly need to be moved.
   *
   * But -- bug #423, disabled and readonly are properties that should be
   * kept on the interior element.
   */
  if (&element != input) {
    element.setProperties(input->properties());
    input->clearProperties();

    std::string v = element.getProperty(Wt::PropertyDisabled);
    if (!v.empty()) {
      input->setProperty(Wt::PropertyDisabled, v);
      element.removeProperty(Wt::PropertyDisabled);
    }

    v = element.getProperty(Wt::PropertyReadOnly);
    if (!v.empty()) {
      input->setProperty(Wt::PropertyReadOnly, v);
      element.removeProperty(Wt::PropertyReadOnly);
    }
  }

  if (stateChanged_ || all) {
    input->setProperty(Wt::PropertyChecked,
		       state_ == Unchecked ? "false" : "true");

    if (supportsIndeterminate(env))
      input->setProperty(Wt::PropertyIndeterminate,
			 state_ == PartiallyChecked ? "true" : "false");
    else
      input->setProperty(Wt::PropertyStyleOpacity,
			 state_ == PartiallyChecked ? "0.5" : "");

    stateChanged_ = false;
  }

  std::vector<DomElement::EventAction> changeActions;

  if (needUpdateChangeSignal
      || (piggyBackChangeOnClick && needUpdateClickedSignal)
      || all) {
    std::string dom = "o";

    if (check) {
      if (check->isConnected())
	changeActions.push_back
	  (DomElement::EventAction(dom + ".checked",
				   check->javaScript(),
				   check->encodeCmd(),
				   check->isExposedSignal()));
      check->updateOk();
    }

    if (uncheck) {
      if (uncheck->isConnected())
	changeActions.push_back
	  (DomElement::EventAction("!" + dom + ".checked",
				   uncheck->javaScript(),
				   uncheck->encodeCmd(),
				   uncheck->isExposedSignal()));
      uncheck->updateOk();
    }

    if (change) {
      if (change->needsUpdate(all))
	changeActions.push_back
	  (DomElement::EventAction(std::string(),
				   change->javaScript(),
				   change->encodeCmd(),
				   change->isExposedSignal()));
      change->updateOk();
    }

    if (!piggyBackChangeOnClick) {
      if (!(all && changeActions.empty()))
	input->setEvent("change", changeActions);
    }
  }

  if (needUpdateClickedSignal || all) {
    if (piggyBackChangeOnClick) {
      if (click) {
	changeActions.push_back
	  (DomElement::EventAction(std::string(),
				   click->javaScript(),
				   click->encodeCmd(),
				   click->isExposedSignal()));
	click->updateOk();
      }

      if (!(all && changeActions.empty()))
	input->setEvent(CLICK_SIGNAL, changeActions);
    } else
      if (click)
	updateSignalConnection(*input, *click, CLICK_SIGNAL, all);
  }

  if (span) {
    if (all || textChanged_) {
      span->setProperty(PropertyInnerHTML, text_.formattedText());
      textChanged_ = false;
    }
  }

  if (&element != input) {
    element.addChild(input);
    element.addChild(span);
  }
}
Example #27
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);
}
Example #28
0
void WAnchor::updateDom(DomElement& element, bool all)
{
  if (element.type() != DomElement_A) {
    WContainerWidget::updateDom(element, all);
    return;
  }

  if (flags_.test(BIT_CHANGE_TAG)) {
    if (!all)
      element.callJavaScript(WT_CLASS ".changeTag(" + jsRef() + ",'a');");

    flags_.reset(BIT_CHANGE_TAG);
  }

  bool needsUrlResolution = false;

  if (flags_.test(BIT_LINK_CHANGED) || all) {
    WApplication *app = WApplication::instance();

    std::string url = link_.resolveUrl(app);

    /*
     * From 但浩亮: setRefInternalPath() and setTarget(TargetNewWindow)
     * does not work without the check below:
     */
    if (target_ == TargetSelf)
      changeInternalPathJS_
	= link_.manageInternalPathChange(app, this, changeInternalPathJS_);
    else {
      delete changeInternalPathJS_;
      changeInternalPathJS_ = 0;
    }

    url = app->encodeUntrustedUrl(url);

    std::string href = resolveRelativeUrl(url);
    element.setAttribute("href", href);

    needsUrlResolution = !app->environment().hashInternalPaths()
      && href.find("://") == std::string::npos && href[0] != '/';

    flags_.reset(BIT_LINK_CHANGED);
  }

  if (flags_.test(BIT_TARGET_CHANGED) || all) {
    switch (target_) {
    case TargetSelf:
      if (!all)
	element.setProperty(PropertyTarget, "_self");
      break;
    case TargetThisWindow:
      element.setProperty(PropertyTarget, "_top");
      break;
    case TargetNewWindow:
      element.setProperty(PropertyTarget, "_blank");
    }
    flags_.reset(BIT_TARGET_CHANGED);
  }

  WContainerWidget::updateDom(element, all);

  if (needsUrlResolution) {
    if (all)
      element.setProperty(PropertyClass,
			  Utils::addWord(styleClass().toUTF8(), "Wt-rr"));
    else
      element.callJavaScript("$('#" + id() + "').addClass('Wt-rr');");
  }
}
Example #29
0
void WDialog::create()
{
  closeIcon_ = 0;
  footer_ = 0;
  modal_ = true;
  resizable_ = false;
  recursiveEventLoop_ = false;
  impl_ = dynamic_cast<WTemplate *>(implementation());

  const char *CSS_RULES_NAME = "Wt::WDialog";

  WApplication *app = WApplication::instance();

  if (!app->styleSheet().isDefined(CSS_RULES_NAME)) {
    /* Needed for the dialog cover */
    if (app->environment().agentIsIElt(9))
      app->styleSheet().addRule("body", "height: 100%;");

    std::string position
      = app->environment().agent() == WEnvironment::IE6 ? "absolute" : "fixed";

    // we use left: 50%, top: 50%, margin hack when JavaScript is not available
    // see below for an IE workaround
    app->styleSheet().addRule("div.Wt-dialog", std::string() +
			      (app->environment().ajax() ?
			       "visibility: hidden;" : "") 
			      //"position: " + position + ';'
			      + (!app->environment().ajax() ?
				 "left: 50%; top: 50%;"
				 "margin-left: -100px; margin-top: -50px;" :
				 "left: 0px; top: 0px;"),
			      CSS_RULES_NAME);

    if (app->environment().agent() == WEnvironment::IE6) {
      app->styleSheet().addRule
	("div.Wt-dialogcover",
	 "position: absolute;"
	 "left: expression("
	 "(ignoreMe2 = document.documentElement.scrollLeft) + 'px' );"
	 "top: expression("
	 "(ignoreMe = document.documentElement.scrollTop) + 'px' );");

      // simulate position: fixed left: 50%; top 50%
      if (!app->environment().ajax())
	app->styleSheet().addRule
	  ("div.Wt-dialog",
	   "position: absolute;"
	   "left: expression("
	   "(ignoreMe2 = document.documentElement.scrollLeft + "
	   "document.documentElement.clientWidth/2) + 'px' );"
	   "top: expression("
	   "(ignoreMe = document.documentElement.scrollTop + "
	   "document.documentElement.clientHeight/2) + 'px' );");
    }
  }

  LOAD_JAVASCRIPT(app, "js/WDialog.js", "WDialog", wtjs1);

  WContainerWidget *layoutContainer = new WContainerWidget();
  layoutContainer->setStyleClass("dialog-layout");
  WVBoxLayout *layout = new WVBoxLayout(layoutContainer);
  layout->setContentsMargins(0, 0, 0, 0);
  layout->setSpacing(0);
  impl_->bindWidget("layout", layoutContainer);

  titleBar_ = new WContainerWidget();
  app->theme()->apply(this, titleBar_, DialogTitleBarRole);

  caption_ = new WText(titleBar_);
  caption_->setInline(false);
  
  contents_ = new WContainerWidget();
  app->theme()->apply(this, contents_, DialogBodyRole);

  layout->addWidget(titleBar_);
  layout->addWidget(contents_, 1);

  saveCoverState(app, app->dialogCover());

  /*
   * Cannot be done using the CSS stylesheet in case there are
   * contained elements with setHideWithOffsets() set
   *
   * For IE, we cannot set it yet since it will confuse width measurements
   * to become minimum size instead of (unconstrained) preferred size
   */
  if (app->environment().ajax()) {
    setAttributeValue("style", "visibility: hidden");

    /*
     * This is needed for animations only, but setting absolute or
     * fixed positioning confuses layout measurement in IE browsers
     */
    if (!app->environment().agentIsIElt(9))
      setPositionScheme(Fixed);
  } else
    setPositionScheme(app->environment().agent() == WEnvironment::IE6
		      ? Absolute : Fixed);
}
Example #30
0
void WPushButton::updateDom(DomElement& element, bool all)
{
  if (all) {
    element.setAttribute("type", "button");
    element.setProperty(PropertyClass, "Wt-btn");
  }

  if (flags_.test(BIT_ICON_CHANGED) || (all && !icon_.isNull())) {
    DomElement *image = DomElement::createNew(DomElement_IMG);
    image->setProperty(PropertySrc, icon_.url());
    image->setId("im" + formName());
    element.insertChildAt(image, 0);
    flags_.set(BIT_ICON_RENDERED);
  }

  if (flags_.test(BIT_TEXT_CHANGED) || all) {
    element
      .setProperty(Wt::PropertyInnerHTML,
		   text_.literal() ? escapeText(text_, true).toUTF8()
		   : text_.toUTF8());
    flags_.reset(BIT_TEXT_CHANGED);
  }

  if (flags_.test(BIT_LINK_CHANGED) || (all && !link_.isNull())) {
    if (!link_.isNull()) {
      WApplication *app = WApplication::instance();

      if (!redirectJS_) {
	redirectJS_ = new JSlot();
	clicked().connect(*redirectJS_);

	if (!app->environment().ajax())
	  clicked().connect(this, &WPushButton::doRedirect);
      }

      if (link_.type() == WLink::InternalPath)
	redirectJS_->setJavaScript
	  ("function(){"
	   WT_CLASS ".history.navigate(" + jsStringLiteral(link_.internalPath())
	   + ",true);"
	   "}");
      else
	if (linkTarget_ == TargetNewWindow)
	  redirectJS_->setJavaScript
	    ("function(){"
	     "window.open(" + jsStringLiteral(link_.url()) + ");"
	     "}");
	else
	  redirectJS_->setJavaScript
	    ("function(){"
	     "window.location=" + jsStringLiteral(link_.url()) + ";"
	     "}");
      clicked().senderRepaint(); // XXX only for Java port necessary
    } else {
      delete redirectJS_;
      redirectJS_ = 0;
    }
  }

  WFormWidget::updateDom(element, all);
}