Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 2012 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/html/HTMLDialogElement.h"
     28 
     29 #include "bindings/v8/ExceptionState.h"
     30 #include "core/dom/ExceptionCode.h"
     31 #include "core/page/FrameView.h"
     32 #include "core/rendering/RenderBlock.h"
     33 #include "core/rendering/style/RenderStyle.h"
     34 
     35 namespace WebCore {
     36 
     37 using namespace HTMLNames;
     38 
     39 static bool needsCenteredPositioning(const RenderStyle* style)
     40 {
     41     return style->position() == AbsolutePosition && style->hasAutoTopAndBottom();
     42 }
     43 
     44 HTMLDialogElement::HTMLDialogElement(const QualifiedName& tagName, Document* document)
     45     : HTMLElement(tagName, document)
     46     , m_topIsValid(false)
     47     , m_top(0)
     48     , m_returnValue("")
     49 {
     50     ASSERT(hasTagName(dialogTag));
     51     setHasCustomStyleCallbacks();
     52     ScriptWrappable::init(this);
     53 }
     54 
     55 PassRefPtr<HTMLDialogElement> HTMLDialogElement::create(const QualifiedName& tagName, Document* document)
     56 {
     57     return adoptRef(new HTMLDialogElement(tagName, document));
     58 }
     59 
     60 void HTMLDialogElement::close(const String& returnValue, ExceptionState& es)
     61 {
     62     if (!fastHasAttribute(openAttr)) {
     63         es.throwDOMException(InvalidStateError);
     64         return;
     65     }
     66     setBooleanAttribute(openAttr, false);
     67     document()->removeFromTopLayer(this);
     68     m_topIsValid = false;
     69 
     70     if (!returnValue.isNull())
     71         m_returnValue = returnValue;
     72 }
     73 
     74 PassRefPtr<RenderStyle> HTMLDialogElement::customStyleForRenderer()
     75 {
     76     RefPtr<RenderStyle> originalStyle = originalStyleForRenderer();
     77     RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
     78 
     79     // Override top to remain centered after style recalcs.
     80     if (needsCenteredPositioning(style.get()) && m_topIsValid)
     81         style->setTop(Length(m_top.toInt(), WebCore::Fixed));
     82 
     83     return style.release();
     84 }
     85 
     86 void HTMLDialogElement::reposition()
     87 {
     88     // Layout because we need to know our ancestors' positions and our own height.
     89     document()->updateLayoutIgnorePendingStylesheets();
     90 
     91     RenderBox* box = renderBox();
     92     if (!box || !needsCenteredPositioning(box->style()))
     93         return;
     94 
     95     // Set up dialog's position to be safe-centered in the viewport.
     96     // FIXME: Figure out what to do in vertical writing mode.
     97     FrameView* frameView = document()->view();
     98     int scrollTop = frameView->scrollOffset().height();
     99     int visibleHeight = frameView->visibleContentRect(ScrollableArea::IncludeScrollbars).height();
    100     m_top = scrollTop;
    101     if (box->height() < visibleHeight)
    102         m_top += (visibleHeight - box->height()) / 2;
    103     m_topIsValid = true;
    104 
    105     setNeedsStyleRecalc(LocalStyleChange);
    106 }
    107 
    108 void HTMLDialogElement::show()
    109 {
    110     if (fastHasAttribute(openAttr))
    111         return;
    112     setBooleanAttribute(openAttr, true);
    113     reposition();
    114 }
    115 
    116 void HTMLDialogElement::showModal(ExceptionState& es)
    117 {
    118     if (fastHasAttribute(openAttr) || !inDocument()) {
    119         es.throwDOMException(InvalidStateError);
    120         return;
    121     }
    122     document()->addToTopLayer(this);
    123     setBooleanAttribute(openAttr, true);
    124     reposition();
    125 }
    126 
    127 bool HTMLDialogElement::isPresentationAttribute(const QualifiedName& name) const
    128 {
    129     // FIXME: Workaround for <https://bugs.webkit.org/show_bug.cgi?id=91058>: modifying an attribute for which there is an attribute selector
    130     // in html.css sometimes does not trigger a style recalc.
    131     if (name == openAttr)
    132         return true;
    133 
    134     return HTMLElement::isPresentationAttribute(name);
    135 }
    136 
    137 bool HTMLDialogElement::shouldBeReparentedUnderRenderView(const RenderStyle* style) const
    138 {
    139     if (style && style->position() == AbsolutePosition)
    140         return true;
    141     return Element::shouldBeReparentedUnderRenderView(style);
    142 }
    143 
    144 } // namespace WebCore
    145