2009-07-16 11 views
11

में किसी तत्व पर एक GWT ईवेंट को हुक करना मैं एक जीडब्ल्यूटी ऐप लिख रहा हूं जिसमें एक आईफ्रेम में बाहरी दस्तावेज़ के साथ बातचीत करना शामिल है। अवधारणा के सबूत के रूप में, मैं एक बटन पर एक क्लिक हैंडलर संलग्न करने की कोशिश कर रहा हूं।एक बाहरी आईफ्रेम

जावास्क्रिप्ट में निम्नलिखित काम करता है

var iframe = document.getElementById("rawJSIFrame"); 
var doc = iframe.contentDocument; 
var body = doc.body; 
var button = doc.getElementsByTagName("input").namedItem("submit"); 
button.onclick = function() { 
    alert("Clicked!"); 
}; 

GWT में बराबर करने के लिए कोशिश कर रहा है, मैंने किया था निम्नलिखित:

public class ElementWrapper extends Widget implements HasClickHandlers { 

    public ElementWrapper(Element theElement) { 
     setElement(theElement); 
    } 

    public HandlerRegistration addClickHandler(ClickHandler handler) { 
     return addDomHandler(handler, ClickEvent.getType()); 
    } 


} 

:

public void addClickHandlerToSubmitButton(String buttonElementName, ClickHandler clickHandler) { 
    IFrameElement iframe = IFrameElement.as(frame.getElement()); 
    Document frameDocument = getIFrameDocument(iframe); 
    if (frameDocument != null) { 
     Element buttonElement = finder(frameDocument).tag("input").name(buttonElementName).findOne(); 
     ElementWrapper wrapper = new ElementWrapper(buttonElement); 
     HandlerRegistration handlerRegistration = wrapper.addClickHandler(clickHandler); 
    } 
} 

private native Document getIFrameDocument(IFrameElement iframe)/*-{ 
     return iframe.contentDocument; 
}-*/; 

निम्नलिखित ElementWrapper वर्ग है बटन खोजने के लिए कोड ठीक काम करता है लेकिन वास्तविक क्लिक इवेंट हैंडलर नहीं आ रहा है। क्या किसी के पास पहले एक समान समस्या थी, और आपने इसे कैसे हल किया?

अग्रिम धन्यवाद,

टिन

उत्तर

10

Hilbrand समस्या जा रहा है कि GWT विधि onAttach() आमंत्रित नहीं किया गया के बारे में सही है: यहाँ संशोधित कोड wrap विधि का उपयोग है।

मैं अपने मूल समाधान लागू, ElementWrapper के लिए निम्न विधि जोड़ने:

public void onAttach() { 
    super.onAttach(); 
    } 

और कहा जाता ElementWrapper के बाद wrapper.onAttach() जोड़ा बनाया जाता है। एक जादू की तरह काम करता है!

+0

धन्यवाद! मुझे पता था कि एक क्लीनर तरीका होना था :) – triggerNZ

0

आप JSNI इस्तेमाल कर सकते हैं कोड आपकी JavaScript टुकड़ा पुन: उपयोग करने के लिए। आपका जावास्क्रिप्ट कोड किसी ऑब्जेक्ट पर एक gwt विधि को कॉल करेगा जो इसे iframe में बटन की ओर से फेंक देगा।

क्यों जीडब्ल्यूटी कोड काम नहीं करता है - मुझे लगता है कि ऐसा इसलिए है क्योंकि वे नियमित ब्राउज़र घटनाओं के शीर्ष पर कुछ परत का उपयोग करते हैं जो शायद 1 से अधिक फ्रेम नहीं फैल सकता है। हालांकि यह सिर्फ एक अनुमान है। आप इसे एक फीचर/बग अनुरोध के रूप में फिर से जीडब्ल्यूटी टीम के रूप में फाइल कर सकते हैं। अगर मैं सही हूं तो आपका कोड ठीक दिखता है।

+0

कूल, उत्तर के लिए धन्यवाद। मुझे लगता है कि मैं जेएसएनआई पथ का पता लगाऊंगा, हालांकि मैं जितना संभव हो कस्टम जावास्क्रिप्ट लिखने से दूर रहना चाहता हूं। – triggerNZ

1

इस शोध के बाद, मैंने पाया कि आईफ्रेम अप्रासंगिक है। मेजबान पृष्ठ पर सामान्य बटन पर एक ही व्यवहार काम नहीं करता है।

मैंने मूल रूप से जेडब्ल्यूटी के ईवेंट हैंडलिंग तंत्र के हिस्से को दोहराने के लिए जेएसएनआई का उपयोग करके इसे ठीक किया है। निम्नलिखित काम करता है:

Element buttonElement = DOM.getElementById("externalButton"); 
new CustomElementWrapper(buttonElement).addClickHandler(new ClickHandler() { 
public void onClick(ClickEvent event) { 
     Window.alert("GWT hooked into button"); 
    } 
}); 

CustomElementWrapper कहां है:

public class CustomElementWrapper extends Widget implements HasClickHandlers { 
    private ClickEventManager clickEventManager; 

    public CustomElementWrapper(Element theElement) { 
     setElement(theElement); 
     clickEventManager = new ClickEventManager(theElement); 
    } 

    public HandlerRegistration addClickHandler(ClickHandler handler) { 
     //The 'right' way of doing this would be the code below. However, this doesn't work 
     // A bug in GWT? 
     //  
     //    return addDomHandler(handler, ClickEvent.getType()); 
     return clickEventManager.registerClickHandler(handler); 
    } 


    void invokeClickHandler() { 
     clickEventManager.invokeClickHandler(); 
    } 

    public boolean isClickHandlerRegistered() { 
     return clickEventManager.isClickHandlerRegistered(); 
    } 
} 

अंत में, ClickEventManager, जहां वास्तविक काम होता है:

public class ClickEventManager { 
private boolean clickHandlerRegistered = false; 
private ClickHandler clickHandler; 
private Element element; 

public ClickEventManager(Element element) { 
    this.element = element; 
} 

public void invokeClickHandler() { 
    //This shouldn't really be null but we are bypassing GWT's native event mechanism 
    //so we can't create an event 
    clickHandler.onClick(null); 
} 

public boolean isClickHandlerRegistered() { 
    return clickHandlerRegistered; 
} 

HandlerRegistration registerClickHandler(ClickHandler handler) { 
    clickHandler = handler; 

    if (!clickHandlerRegistered) { 
     registerClickHandlerInJS(element); 
     clickHandlerRegistered = true; 
    } 
    return new HandlerRegistration() { 
     public void removeHandler() { 
      //For now, we don't support the removal of handlers 
      throw new UnsupportedOperationException(); 
     } 
    }; 
} 
private native void registerClickHandlerInJS(Element element)/*-{ 
    element.__clickManager = this; 
    element.onclick 
     = function() { 
      var cm = this.__clickManager; 
      [email protected]::invokeClickHandler()(); 
     } 
}-*/; 
} 

व्यक्तिगत रूप से, मैं इस समाधान से नफरत है क्योंकि मैं दिखाई देते हैं जीडब्ल्यूटी के इवेंट हैंडलिंग को डुप्लिकेट करने और संभवतः गंदा जावास्क्रिप्ट मेमोरी लीक पेश करने के लिए। मेरा पहला पोस्ट क्यों काम नहीं करता है (यह याद रखना कि आईफ्रेम पहलू लाल हेरिंग है) पर कोई विचार है, इसकी सराहना की जाएगी।

धन्यवाद,

टिन

+0

धन्यवाद, धन्यवाद! यह वही था जो मुझे आईई 7 में काम करने के लिए जरूरी था! – SorcyCat

4

मैं उम्मीद समस्या यह है कि GWT विधि onAttach() नहीं बुलाया जाता है जब आप अपना पहला उदाहरण के रूप में रैपिंग का उपयोग करें। आप बटन विजेट पर स्थिर wrap विधि का उपयोग करने का प्रयास कर सकते हैं। हालांकि इसका उपयोग करने के लिए inputbutton टाइप होना चाहिए। या wrap विधि के कार्यान्वयन पर एक नज़र डालें।

Element buttonElement = finder(frameDocument).tag("input").name(buttonElementName).findOne(); 
Button button = Button.wrap(buttonElement); 
HandlerRegistration handlerRegistration = button.addClickHandler(clickHandler); 
0

कृपया मेरा पिछला उत्तर देखें। आपके मूल समाधान में थोड़ा सा संशोधन यह काम करेगा।

1

आप पा सकते हैं यह सहायक:

Element root = Document.get().getElementById("target"); 
    DirectPanel p = new DirectPanel(root); 
    Button register = new Button("Register"); 
    register.addClickHandler(new ClickHandler() { 
    @Override 
    public void onClick(ClickEvent event) { 
     // ... 
    } 
    }); 
    p.add(register); 

और मनमाने ढंग से तत्वों को घटनाओं के लिए बाध्य:

Element root = Document.get().getElementById("target"); 
    DirectPanel p = new DirectPanel(root); 
    p.addClickHandler(new ClickHandler() { 
    @Override 
    public void onClick(ClickEvent event) { 
     // ... 
    } 
    }); 

import com.google.gwt.dom.client.Element; 
import com.google.gwt.event.dom.client.ClickEvent; 
import com.google.gwt.event.dom.client.ClickHandler; 
import com.google.gwt.event.dom.client.HasClickHandlers; 
import com.google.gwt.event.shared.HandlerRegistration; 
import com.google.gwt.user.client.ui.AbsolutePanel; 

public class DirectPanel extends AbsolutePanel implements HasClickHandlers { 
     public DirectPanel(Element elem) { 
       super(elem.<com.google.gwt.user.client.Element> cast()); 
       onAttach(); 
     } 

     @Override 
     public HandlerRegistration addClickHandler(ClickHandler handler) { 
       return addDomHandler(handler, ClickEvent.getType()); 
     } 
} 

फिर आप विजेट कंटेनर में मनमाने ढंग से कंटेनर बनाने के लिए सक्षम हो जाएगा

विशेष रूप से आपके मामले में, इसे आजमाएं:

IFrameElement frm = Document.get().createIFrameElement(); 
Document d = frm.getContentDocument(); 
NodeList<Element> inputs = d.getElementsByTagName("input"); 
InputElement target = null; 
for(int i = 0; i < inputs.getLength(); ++i) { 
    Element e = inputs.getItem(0); 
    if (e.getNodeName().equals("submit")) { 
    target = InputElement.as(e); 
    break; 
    } 
} 
if (target != null) { 
    DirectPanel p = new DirectPanel(target); 
    p.addClickHandler(new ClickHandler() { 
    @Override 
    public void onClick(ClickEvent event) { 
     // TODO Auto-generated method stub 
    } 
    }); 
} 

यह हमेशा मुझे रहस्यमय करता है कि जीडब्ल्यूटी यह इतना कठिन और खराब दस्तावेज कर रहा है।

1

iframes का उपयोग करने के बजाय मैं सुझाव देता हूं कि आप आसानी से com.google.gwt.http.client.RequestBuilder के माध्यम से जीडब्ल्यूटी से http अनुरोध करें। इस तरह:

private void getHtml(String url) { 
     RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, url); 

     rb.setCallback(new RequestCallback() { 

      @Override 
      public void onResponseReceived(Request request, Response response) { 
       HTMLPanel html = new HTMLPanel(response.getText()); 

       // Now you have a widget with the requested page 
       // thus you may do whatever you want with it. 
      } 

      @Override 
      public void onError(Request request, Throwable exception) { 
       Log.error("error " + exception); 
      } 
     }); 

     try { 
      rb.send(); 
     } catch (RequestException e) { 
      Log.error("error " + e); 
     } 
    } 
संबंधित मुद्दे