DomElement *StdWidgetItemImpl::createDomElement(bool fitWidth, bool fitHeight, WApplication *app) { WWidget *w = item_->widget(); w->setInline(false); DomElement *d = w->createSDomElement(app); DomElement *result = d; if (app->environment().agentIsIElt(9) && (d->type() == DomElement_TEXTAREA || d->type() == DomElement_SELECT || d->type() == DomElement_INPUT || d->type() == DomElement_BUTTON)) { d->removeProperty(PropertyStyleDisplay); } // FIXME IE9 does border-box perhaps ? if (!app->environment().agentIsIE() && w->javaScriptMember(WWidget::WT_RESIZE_JS).empty() && d->type() != DomElement_TABLE /* buggy in Chrome, see #1856 */ && app->theme()->canBorderBoxElement(*d)) d->setProperty(PropertyStyleBoxSizing, "border-box"); return result; }
void WTextEdit::updateDom(DomElement& element, bool all) { WTextArea::updateDom(element, all); if (element.type() == DomElement_TEXTAREA) element.removeProperty(PropertyStyleDisplay); // we are creating the actual element if (all && element.type() == DomElement_TEXTAREA) { std::stringstream config; config << "{"; bool first = true; for (SettingsMapType::const_iterator it = configurationSettings_.begin(); it != configurationSettings_.end(); ++it) { if (it->first == "plugins") continue; if (!first) config << ','; first = false; config << it->first << ": " << Impl::asJSLiteral(it->second, XHTMLUnsafeText); } if (!first) config << ','; config << "plugins: '" << plugins() << "'"; config << ",init_instance_callback: obj.init" "}"; DomElement dummy(DomElement::ModeUpdate, DomElement_TABLE); updateDom(dummy, true); element.callJavaScript("(function() { " """var obj = $('#" + id() + "').data('obj');" """obj.render(" + config.str() + "," + jsStringLiteral(dummy.cssStyle()) + "," + (changed().isConnected() ? "true" : "false") + ");" "})();"); contentChanged_ = false; } if (!all && contentChanged_) { element.callJavaScript(jsRef() + ".ed.load();"); contentChanged_ = false; } }
void WPushButton::updateDom(DomElement& element, bool all) { if (all && element.type() == DomElement_BUTTON) element.setAttribute("type", "button"); bool updateInnerHtml = !icon_.isNull() && flags_.test(BIT_TEXT_CHANGED); if (updateInnerHtml || flags_.test(BIT_ICON_CHANGED) || (all && !icon_.isNull())) { DomElement *image = DomElement::createNew(DomElement_IMG); image->setProperty(PropertySrc, icon_.resolveUrl(WApplication::instance())); image->setId("im" + formName()); element.insertChildAt(image, 0); flags_.set(BIT_ICON_RENDERED); flags_.reset(BIT_ICON_CHANGED); } if (flags_.test(BIT_TEXT_CHANGED) || all) { element.setProperty(Wt::PropertyInnerHTML, text_.formattedText()); flags_.reset(BIT_TEXT_CHANGED); } // bool needsUrlResolution = false; if (flags_.test(BIT_LINK_CHANGED) || all) { if (element.type() == DomElement_A) { /* needsUrlResolution = */ WAnchor::renderHRef(this, linkState_, element); WAnchor::renderHTarget(linkState_, element, all); } else renderHRef(element); flags_.reset(BIT_LINK_CHANGED); } if (isCheckable()) { if (flags_.test(BIT_CHECKED_CHANGED) || all) { if (!all || flags_.test(BIT_IS_CHECKED)) { toggleStyleClass("active", flags_.test(BIT_IS_CHECKED), true); } flags_.reset(BIT_CHECKED_CHANGED); } } if (!all) WApplication::instance()->theme()->apply(this, element, MainElementThemeRole); WFormWidget::updateDom(element, all); }
void WFileUpload::updateDom(DomElement& element, bool all) { bool containsProgress = progressBar_ && progressBar_->parent() == this; DomElement *inputE = 0; if (element.type() != DomElement_INPUT && flags_.test(BIT_DO_UPLOAD) && containsProgress && !progressBar_->isRendered()) element.addChild(progressBar_->createSDomElement(WApplication::instance())); // upload() + disable() does not work. -- fix after this release, // change order of javaScript_ and properties rendering in DomElement if (fileUploadTarget_ && flags_.test(BIT_DO_UPLOAD)) { element.callMethod("submit()"); flags_.reset(BIT_DO_UPLOAD); if (containsProgress) { inputE = DomElement::getForUpdate("in" + id(), DomElement_INPUT); inputE->setProperty(PropertyStyleDisplay, "none"); } } if (flags_.test(BIT_ENABLED_CHANGED)) { if (!inputE) inputE = DomElement::getForUpdate("in" + id(), DomElement_INPUT); if (isDisabled()) inputE->callMethod("disabled=true"); else inputE->callMethod("disabled=false"); flags_.reset(BIT_ENABLED_CHANGED); } EventSignal<> *change = voidEventSignal(CHANGE_SIGNAL, false); if (change && change->needsUpdate(all)) { if (!inputE) inputE = DomElement::getForUpdate("in" + id(), DomElement_INPUT); updateSignalConnection(*inputE, *change, "change", all); } if (inputE) element.addChild(inputE); WWebWidget::updateDom(element, all); }
void WTextArea::updateDom(DomElement& element, bool all) { if (element.type() == DomElement_TEXTAREA) if (contentChanged_ || all) { element.setProperty(Wt::PropertyValue, content_.toUTF8()); contentChanged_ = false; } if (attributesChanged_ || all) { element.setAttribute("cols", boost::lexical_cast<std::string>(cols_)); element.setAttribute("rows", boost::lexical_cast<std::string>(rows_)); attributesChanged_ = false; } WFormWidget::updateDom(element, all); }
void WImage::updateDom(DomElement& element, bool all) { DomElement *img = &element; if (all && element.type() == DomElement_SPAN) { DomElement *map = map_->createSDomElement(WApplication::instance()); element.addChild(map); img = DomElement::createNew(DomElement_IMG); img->setId("i" + id()); } if (flags_.test(BIT_IMAGE_LINK_CHANGED) || all) { if (!imageLink_.isNull()) { std::string url = resolveRelativeUrl(imageLink_.url()); WApplication *app = WApplication::instance(); url = app->encodeUntrustedUrl(url); img->setProperty(Wt::PropertySrc, url); } else img->setProperty(Wt::PropertySrc, "#"); flags_.reset(BIT_IMAGE_LINK_CHANGED); } if (flags_.test(BIT_ALT_TEXT_CHANGED) || all) { img->setAttribute("alt", altText_.toUTF8()); flags_.reset(BIT_ALT_TEXT_CHANGED); } if (flags_.test(BIT_MAP_CREATED) || (all && map_)) { img->setAttribute("usemap", '#' + map_->id()); flags_.reset(BIT_MAP_CREATED); } WInteractWidget::updateDom(*img, all); if (&element != img) element.addChild(img); }
DomElement *WFileUpload::createDomElement(WApplication *app) { DomElement *result = DomElement::createNew(domElementType()); if (result->type() == DomElement_FORM) result->setId(id()); else result->setName(id()); EventSignal<> *change = voidEventSignal(CHANGE_SIGNAL, false); if (fileUploadTarget_) { DomElement *i = DomElement::createNew(DomElement_IFRAME); i->setProperty(PropertyClass, "Wt-resource"); i->setProperty(PropertySrc, fileUploadTarget_->url()); i->setName("if" + id()); if (app->environment().agentIsIE()) { // http://msdn.microsoft.com/en-us/library/ms536474%28v=vs.85%29.aspx // HTA's (started by mshta.exe) have a different security model than // a normal web app, and therefore a HTA browser does not allow // interaction from iframes to the parent window unless this // attribute is set. If omitted, this causes the 'uploaded()' // signal to be blocked when a Wt app is executed as a HTA. i->setAttribute("APPLICATION", "yes"); } DomElement *form = result; form->setAttribute("method", "post"); form->setAttribute("action", fileUploadTarget_->url()); form->setAttribute("enctype", "multipart/form-data"); form->setProperty(PropertyStyle, "margin:0;padding:0;display:inline"); form->setProperty(PropertyTarget, "if" + id()); /* * wrap iframe in an extra span to work around bug in IE which does * not set the name use DOM methods */ DomElement *d = DomElement::createNew(DomElement_SPAN); d->addChild(i); form->addChild(d); DomElement *input = DomElement::createNew(DomElement_INPUT); input->setAttribute("type", "file"); if (flags_.test(BIT_MULTIPLE)) input->setAttribute("multiple", "multiple"); input->setAttribute("name", "data"); input->setAttribute("size", boost::lexical_cast<std::string>(textSize_)); input->setId("in" + id()); if (!isEnabled()) input->setProperty(Wt::PropertyDisabled, "true"); if (change) updateSignalConnection(*input, *change, "change", true); form->addChild(input); } else { result->setAttribute("type", "file"); if (flags_.test(BIT_MULTIPLE)) result->setAttribute("multiple", "multiple"); result->setAttribute("size", boost::lexical_cast<std::string>(textSize_)); if (!isEnabled()) result->setProperty(Wt::PropertyDisabled, "true"); if (change) updateSignalConnection(*result, *change, "change", true); } updateDom(*result, true); flags_.reset(BIT_ENABLE_AJAX); return result; }
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); } }
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');"); } }
void WWebWidget::updateDom(DomElement& element, bool all) { /* * determine display */ if (hiddenChanged_ || geometryChanged_ || all) { if (!hidden_) { if (element.isDefaultInline() != inline_) { if (inline_) { if (element.type() == DomElement::TABLE) element.setProperty(PropertyStyleDisplay, "inline-table"); else if (element.type() != DomElement::TD) element.setProperty(PropertyStyleDisplay, "inline-block"); } else { element.setProperty(PropertyStyleDisplay, "block"); } } else if (hiddenChanged_) { element.setProperty(PropertyStyleDisplay, inline_ ? "inline" : "block"); } } else element.setProperty(PropertyStyleDisplay, "none"); hiddenChanged_ = false; } if (geometryChanged_ || all) { /* * set position */ switch (positionScheme_) { case Static: break; case Relative: element.setProperty(PropertyStylePosition, "relative"); break; case Absolute: element.setProperty(PropertyStylePosition, "absolute"); break; case Fixed: element.setProperty(PropertyStylePosition, "fixed"); break; } /* * set z-index */ if (popup_) element.setProperty(PropertyStyleZIndex, boost::lexical_cast<std::string>(zIndex())); /* * set float */ switch (floatSide_) { case None: break; case Left: element.setProperty(PropertyStyleFloat, "left"); break; break; case Right: element.setProperty(PropertyStyleFloat, "right"); break; break; default: /* illegal values */ ; } /* * set clear: FIXME: multiple values */ switch (clearSides_) { case None: break; case Left: element.setProperty(PropertyStyleClear, "left"); break; break; case Right: element.setProperty(PropertyStyleClear, "right"); break; break; case Verticals: element.setProperty(PropertyStyleClear, "both"); break; break; default: /* illegal values */ ; } /* * set width & height */ if (!width_.isAuto()) element.setProperty(PropertyStyleWidth, width_.cssText()); if (!height_.isAuto()) element.setProperty(PropertyStyleHeight, height_.cssText()); if (!minimumWidth_.isAuto() && (minimumWidth_.value() != 0)) element.setProperty(PropertyStyleMinWidth, minimumWidth_.cssText()); if (!minimumHeight_.isAuto() && (minimumHeight_.value() != 0)) element.setProperty(PropertyStyleMinHeight, minimumHeight_.cssText()); if (!maximumWidth_.isAuto()) // == none element.setProperty(PropertyStyleMaxWidth, maximumWidth_.cssText()); if (!maximumHeight_.isAuto()) // == none element.setProperty(PropertyStyleMaxHeight, maximumHeight_.cssText()); /* * set offsets */ if (positionScheme_ != Static) { static const Property properties[] = { PropertyStyleTop, PropertyStyleRight, PropertyStyleBottom, PropertyStyleLeft }; for (unsigned i = 0; i < 4; ++i) { if (!offsets_[i].isAuto()) element.setProperty(properties[i], offsets_[i].cssText()); } } /* * set vertical alignment */ switch (verticalAlignment_) { case AlignBaseline: break; case AlignSub: element.setProperty(PropertyStyleVerticalAlign, "sub"); break; case AlignSuper: element.setProperty(PropertyStyleVerticalAlign, "super"); break; case AlignTop: element.setProperty(PropertyStyleVerticalAlign, "top"); break; case AlignTextTop: element.setProperty(PropertyStyleVerticalAlign, "text-top"); break; case AlignMiddle: element.setProperty(PropertyStyleVerticalAlign, "middle"); break; case AlignBottom: element.setProperty(PropertyStyleVerticalAlign, "bottom"); break; case AlignTextBottom: element.setProperty(PropertyStyleVerticalAlign, "text-bottom"); break; case AlignLength: element.setProperty(PropertyStyleVerticalAlign, verticalAlignmentLength_.cssText()); break; } geometryChanged_ = false; } if (marginsChanged_ || all) { if (marginsChanged_ || (margin_[0].value() != 0)) element.setProperty(PropertyStyleMarginTop, margin_[0].cssText()); if (marginsChanged_ || (margin_[1].value() != 0)) element.setProperty(PropertyStyleMarginRight, margin_[1].cssText()); if (marginsChanged_ || (margin_[2].value() != 0)) element.setProperty(PropertyStyleMarginBottom, margin_[2].cssText()); if (marginsChanged_ || (margin_[3].value() != 0)) element.setProperty(PropertyStyleMarginLeft, margin_[3].cssText()); marginsChanged_ = false; } if (toolTipChanged_ || all) { if ((toolTip_.length() > 0) || toolTipChanged_) element.setAttribute("title", toolTip_); toolTipChanged_ = false; } if (styleClass_.length() == 0) { decorationStyle_.updateDomElement(element, all); } else { if (styleClassChanged_ || all) { element.setAttribute("class", styleClass_); styleClassChanged_ = false; } } renderOk(); for (unsigned i = 0; i < childRemoveChanges_.size(); ++i) delete childRemoveChanges_[i]; childRemoveChanges_.clear(); }
void WCssTheme::apply(WWidget *widget, DomElement& element, int elementRole) const { { WPopupWidget *popup = dynamic_cast<WPopupWidget *>(widget); if (popup) element.addPropertyWord(PropertyClass, "Wt-outset"); } switch (element.type()) { case DomElement_BUTTON: element.addPropertyWord(PropertyClass, "Wt-btn"); break; case DomElement_UL: if (dynamic_cast<WPopupMenu *>(widget)) element.addPropertyWord(PropertyClass, "Wt-popupmenu Wt-outset"); else { WTabWidget *tabs = dynamic_cast<WTabWidget *>(widget->parent()->parent()); if (tabs) element.addPropertyWord(PropertyClass, "Wt-tabs"); else { WSuggestionPopup *suggestions = dynamic_cast<WSuggestionPopup *>(widget); if (suggestions) element.addPropertyWord(PropertyClass, "Wt-suggest"); } } break; case DomElement_LI: { WMenuItem *item = dynamic_cast<WMenuItem *>(widget); if (item) { if (item->isSeparator()) element.addPropertyWord(PropertyClass, "Wt-separator"); if (item->isSectionHeader()) element.addPropertyWord(PropertyClass, "Wt-sectheader"); if (item->menu()) element.addPropertyWord(PropertyClass, "submenu"); } } break; case DomElement_DIV: { WDialog *dialog = dynamic_cast<WDialog *>(widget); if (dialog) { element.addPropertyWord(PropertyClass, "Wt-dialog"); return; } WPanel *panel = dynamic_cast<WPanel *>(widget); if (panel) { element.addPropertyWord(PropertyClass, "Wt-panel Wt-outset"); return; } WProgressBar *bar = dynamic_cast<WProgressBar *>(widget); if (bar) { switch (elementRole) { case MainElementThemeRole: element.addPropertyWord(PropertyClass, "Wt-progressbar"); break; case ProgressBarBarRole: element.addPropertyWord(PropertyClass, "Wt-pgb-bar"); break; case ProgressBarLabelRole: element.addPropertyWord(PropertyClass, "Wt-pgb-label"); } return; } } break; case DomElement_INPUT: { WAbstractSpinBox *spinBox = dynamic_cast<WAbstractSpinBox *>(widget); if (spinBox) { element.addPropertyWord(PropertyClass, "Wt-spinbox"); return; } WDateEdit *dateEdit = dynamic_cast<WDateEdit *>(widget); if (dateEdit) { element.addPropertyWord(PropertyClass, "Wt-dateedit"); return; } } break; default: break; } }
bool WBootstrapTheme::canBorderBoxElement(const DomElement& element) const { // confuses the CSS for it, see #1937 return element.type() != DomElementType::INPUT; }
void WBootstrapTheme::apply(WWidget *widget, DomElement& element, int elementRole) const { bool creating = element.mode() == DomElement::Mode::Create; if (!widget->isThemeStyleEnabled()) return; { WPopupWidget *popup = dynamic_cast<WPopupWidget *>(widget); if (popup) { WDialog *dialog = dynamic_cast<WDialog *>(widget); if (!dialog) element.addPropertyWord(Property::Class, "dropdown-menu"); } } switch (element.type()) { case DomElementType::A: { if (creating && dynamic_cast<WPushButton *>(widget)) element.addPropertyWord(Property::Class, classBtn(widget)); WPushButton *btn = dynamic_cast<WPushButton *>(widget); if (creating && btn && btn->isDefault()) element.addPropertyWord(Property::Class, "btn-primary"); if (element.getProperty(Property::Class).find("dropdown-toggle") != std::string::npos) { WMenuItem *item = dynamic_cast<WMenuItem *>(widget->parent()); if (!dynamic_cast<WPopupMenu *>(item->parentMenu())) { DomElement *b = DomElement::createNew(DomElementType::B); b->setProperty(Property::Class, "caret"); element.addChild(b); } } break; } case DomElementType::BUTTON: { if (creating && !widget->hasStyleClass("list-group-item")) element.addPropertyWord(Property::Class, classBtn(widget)); WPushButton *button = dynamic_cast<WPushButton *>(widget); if (button) { if (creating && button->isDefault()) element.addPropertyWord(Property::Class, "btn-primary"); if (button->menu() && element.properties().find(Property::InnerHTML) != element.properties().end()) { element.addPropertyWord(Property::InnerHTML, "<span class=\"caret\"></span>"); } if (creating && !button->text().empty()) element.addPropertyWord(Property::Class, "with-label"); if (!button->link().isNull()) LOG_ERROR("Cannot use WPushButton::setLink() after the button has " "been rendered with WBootstrapTheme"); } break; } case DomElementType::DIV: { WDialog *dialog = dynamic_cast<WDialog *>(widget); if (dialog) { if (version_ == BootstrapVersion::v2) element.addPropertyWord(Property::Class, "modal"); else element.addPropertyWord(Property::Class, "modal-dialog Wt-dialog"); return; } WPanel *panel = dynamic_cast<WPanel *>(widget); if (panel) { element.addPropertyWord(Property::Class, classAccordionGroup()); return; } WProgressBar *bar = dynamic_cast<WProgressBar *>(widget); if (bar) { switch (elementRole) { case MainElement: element.addPropertyWord(Property::Class, "progress"); break; case ProgressBarBar: element.addPropertyWord(Property::Class, classBar()); break; case ProgressBarLabel: element.addPropertyWord(Property::Class, "bar-label"); } return; } WGoogleMap *map = dynamic_cast<WGoogleMap *>(widget); if (map) { element.addPropertyWord(Property::Class, "Wt-googlemap"); return; } WAbstractItemView *itemView = dynamic_cast<WAbstractItemView *>(widget); if (itemView) { element.addPropertyWord(Property::Class, "form-inline"); return; } WNavigationBar *navBar = dynamic_cast<WNavigationBar *>(widget); if (navBar) { element.addPropertyWord(Property::Class, classNavbar()); return; } } break; case DomElementType::LABEL: { if (elementRole == 1) { if (version_ == BootstrapVersion::v3) { WCheckBox *cb = dynamic_cast<WCheckBox *>(widget); WRadioButton *rb = nullptr; if (cb) { element.addPropertyWord(Property::Class, widget->isInline() ? "checkbox-inline" : "checkbox"); } else { rb = dynamic_cast<WRadioButton *>(widget); if (rb) element.addPropertyWord(Property::Class, widget->isInline() ? "radio-inline" : "radio"); } if ((cb || rb) && !widget->isInline()) element.setType(DomElementType::DIV); } else { WCheckBox *cb = dynamic_cast<WCheckBox *>(widget); WRadioButton *rb = nullptr; if (cb) { element.addPropertyWord(Property::Class, "checkbox"); } else { rb = dynamic_cast<WRadioButton *>(widget); if (rb) element.addPropertyWord(Property::Class, "radio"); } if ((cb || rb) && widget->isInline()) element.addPropertyWord(Property::Class, "inline"); } } } break; case DomElementType::LI: { WMenuItem *item = dynamic_cast<WMenuItem *>(widget); if (item) { if (item->isSeparator()) element.addPropertyWord(Property::Class, "divider"); if (item->isSectionHeader()) element.addPropertyWord(Property::Class, "nav-header"); if (item->menu()) { if (dynamic_cast<WPopupMenu *>(item->parentMenu())) element.addPropertyWord(Property::Class, "dropdown-submenu"); else element.addPropertyWord(Property::Class, "dropdown"); } } } break; case DomElementType::INPUT: { if (version_ == BootstrapVersion::v3 && formControlStyle_) { WAbstractToggleButton *tb = dynamic_cast<WAbstractToggleButton *>(widget); if (!tb) element.addPropertyWord(Property::Class, "form-control"); } WAbstractSpinBox *spinBox = dynamic_cast<WAbstractSpinBox *>(widget); if (spinBox) { element.addPropertyWord(Property::Class, "Wt-spinbox"); return; } WDateEdit *dateEdit = dynamic_cast<WDateEdit *>(widget); if (dateEdit) { element.addPropertyWord(Property::Class, "Wt-dateedit"); return; } WTimeEdit *timeEdit = dynamic_cast<WTimeEdit *>(widget); if (timeEdit) { element.addPropertyWord(Property::Class, "Wt-timeedit"); return; } } break; case DomElementType::TEXTAREA: case DomElementType::SELECT: if (version_ == BootstrapVersion::v3 && formControlStyle_) element.addPropertyWord(Property::Class, "form-control"); break; case DomElementType::UL: { WPopupMenu *popupMenu = dynamic_cast<WPopupMenu *>(widget); if (popupMenu) { element.addPropertyWord(Property::Class, "dropdown-menu"); if (popupMenu->parentItem() && dynamic_cast<WPopupMenu *>(popupMenu->parentItem()->parentMenu())) element.addPropertyWord(Property::Class, "submenu"); } else { WMenu *menu = dynamic_cast<WMenu *>(widget); if (menu) { element.addPropertyWord(Property::Class, "nav"); WTabWidget *tabs = dynamic_cast<WTabWidget *>(menu->parent()->parent()); if (tabs) element.addPropertyWord(Property::Class, "nav-tabs"); } else { WSuggestionPopup *suggestions = dynamic_cast<WSuggestionPopup *>(widget); if (suggestions) element.addPropertyWord(Property::Class, "typeahead"); } } } case DomElementType::SPAN: { WInPlaceEdit *inPlaceEdit = dynamic_cast<WInPlaceEdit *>(widget); if (inPlaceEdit) element.addPropertyWord(Property::Class, "Wt-in-place-edit"); else { WDatePicker *picker = dynamic_cast<WDatePicker *>(widget); if (picker) element.addPropertyWord(Property::Class, "Wt-datepicker"); } } break; default: break; } }
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"); } }
void WBootstrapTheme::apply(WWidget *widget, DomElement& element, int elementRole) const { { WPopupWidget *popup = dynamic_cast<WPopupWidget *>(widget); if (popup) { WDialog *dialog = dynamic_cast<WDialog *>(widget); if (!dialog) element.addPropertyWord(PropertyClass, "dropdown-menu"); } } switch (element.type()) { case DomElement_A: if (dynamic_cast<WPushButton *>(widget)) element.addPropertyWord(PropertyClass, "btn"); break; case DomElement_BUTTON: { element.addPropertyWord(PropertyClass, "btn"); WPushButton *button = dynamic_cast<WPushButton *>(widget); if (button) { if (button->isDefault()) element.addPropertyWord(PropertyClass, "btn-primary"); if (button->menu()) { element.addPropertyWord(PropertyInnerHTML, "<span class=\"caret\"></span>"); } } break; } case DomElement_DIV: { WDialog *dialog = dynamic_cast<WDialog *>(widget); if (dialog) { element.addPropertyWord(PropertyClass, "modal"); return; } WPanel *panel = dynamic_cast<WPanel *>(widget); if (panel) { element.addPropertyWord(PropertyClass, "accordion-group"); return; } WProgressBar *bar = dynamic_cast<WProgressBar *>(widget); if (bar) { switch (elementRole) { case MainElementThemeRole: element.addPropertyWord(PropertyClass, "progress"); break; case ProgressBarBarRole: element.addPropertyWord(PropertyClass, "bar"); break; case ProgressBarLabelRole: element.addPropertyWord(PropertyClass, "bar-label"); } return; } WGoogleMap *map = dynamic_cast<WGoogleMap *>(widget); if (map) { element.addPropertyWord(PropertyClass, "Wt-googlemap"); return; } WAbstractItemView *itemView = dynamic_cast<WAbstractItemView *>(widget); if (itemView) { element.addPropertyWord(PropertyClass, "form-horizontal"); return; } } break; case DomElement_LABEL: { WCheckBox *cb = dynamic_cast<WCheckBox *>(widget); if (cb) { element.addPropertyWord(PropertyClass, "checkbox"); if (cb->isInline()) element.addPropertyWord(PropertyClass, "inline"); } else { WRadioButton *rb = dynamic_cast<WRadioButton *>(widget); if (rb) { element.addPropertyWord(PropertyClass, "radio"); if (rb->isInline()) element.addPropertyWord(PropertyClass, "inline"); } } } break; case DomElement_LI: { WMenuItem *item = dynamic_cast<WMenuItem *>(widget); if (item) { if (item->isSeparator()) element.addPropertyWord(PropertyClass, "divider"); if (item->isSectionHeader()) element.addPropertyWord(PropertyClass, "nav-header"); } } break; case DomElement_INPUT: { WAbstractSpinBox *spinBox = dynamic_cast<WAbstractSpinBox *>(widget); if (spinBox) { element.addPropertyWord(PropertyClass, "Wt-spinbox"); return; } WDateEdit *dateEdit = dynamic_cast<WDateEdit *>(widget); if (dateEdit) { element.addPropertyWord(PropertyClass, "Wt-dateedit"); return; } } break; case DomElement_UL: { WPopupMenu *popupMenu = dynamic_cast<WPopupMenu *>(widget); if (popupMenu) element.addPropertyWord(PropertyClass, "dropdown-menu"); else { WMenu *menu = dynamic_cast<WMenu *>(widget); if (menu) { element.addPropertyWord(PropertyClass, "nav"); WTabWidget *tabs = dynamic_cast<WTabWidget *>(menu->parent()->parent()); if (tabs) element.addPropertyWord(PropertyClass, "nav-tabs"); } else { WSuggestionPopup *suggestions = dynamic_cast<WSuggestionPopup *>(widget); if (suggestions) element.addPropertyWord(PropertyClass, "typeahead"); } } } case DomElement_SPAN: { WInPlaceEdit *inPlaceEdit = dynamic_cast<WInPlaceEdit *>(widget); if (inPlaceEdit) element.addPropertyWord(PropertyClass, "Wt-in-place-edit"); } break; default: break; } }