Re: Extracting attributes of DOM elements

[email protected] Tue, 24 Apr 2007 10:58:58 -0400
Newsgroups gmane.comp.mozilla.jrex
Message-ID <[email protected]>
Gyuri,

Not without additional extensions, I'm afraid (at least not that I could 
find).  I've implemented a bit of a hack in 
org.mozilla.jrex.dom.JRexNodeImpl which required creating some new JNI 
methods.  This doesn't exactly follow the normal JRex conventions of 
creating wrapper Java objects for all of the Gecko internals but it 
works well enough for me.

I created a method called GetNodeComputedStyle as a method on a 
JRexNodeImpl that returns the computed style as a string (e.g., 
"font-style: italic ; font-variant: small-caps; font-weight: 900; 
font-size: 12px; font-family: arial").  This was good enough for my 
needs, and there seemed to be some bugs in Mozilla 1.8 (I forget now 
where I read this) that made these attributes inaccessible in a more 
fine-grained interface.  In any case, if you need more fine-grained 
access the string should be easy enough to parse.

To achieve this, I added the following to JRexNodeImpl.java (note that 
this has not been very thoroughly tested):

private native String GetNodeComputedStyle() throws JRexException;

public String getNodeComputedStyle() throws DOMException{
     if(JRexL.on)JRexL.log(className,"**** getNodeComputedStyle ****");
     String text=null;
     try{
         text=GetNodeComputedStyle();
     }catch(JRexException ex){
         JRexL.printStackTrace(ex);
     }
     if(JRexL.on)JRexL.log(className,
                           "**** getNodeComputedStyle text<"
                           +text+"> ****");
     return text;
}


And I added the following to org_mozilla_jrex_dom_JRexNodeImpl.cpp:

NS_IMETHODIMP
GetCssText(nsIDOMCSSStyleDeclaration * computedStyle, nsAString& aCssText) {
     nsresult rv;
     PRUint32 count;
     computedStyle->GetLength(&count);

     aCssText.Truncate();

     for (PRUint32 i = 0; i < count; ++i) {
         nsAutoString propertyName;
         nsAutoString propertyValue;
         rv = computedStyle->Item(i, propertyName);
         if (NS_FAILED(rv)) {
             JREX_LOGLN("ERROR GETTING PROPERTY NAME")
             return rv;
         }
         rv = computedStyle->GetPropertyValue(propertyName, propertyValue);
         if (NS_FAILED(rv)) {
             JREX_LOGLN("ERROR GETTING PROPERTY VALUE FOR PROPERTY 
"<<ToNewUTF8String(propertyName))
             return rv;
         }

         // If this isn't the first item in the list, then
         // its ok to append a separator.
         if (!aCssText.IsEmpty()) {
             aCssText.Append(NS_LITERAL_STRING("; "));
         }
         aCssText.Append(propertyName);
         aCssText.Append(NS_LITERAL_STRING(": "));
         aCssText.Append(propertyValue);
     }

     return NS_OK;
}

inline JREX_JNI_UTIL::JRexCommonJRV*
JRexNodeImpl_GetNodeComputedStyleInternal(JNIEnv *env, nsIDOMNode* node){
     JNIEnv *env1=env?env:JRex_GetEnv(0);
     if(IS_NULL(env1))return NULL;

     JREX_JNI_UTIL::JRexCommonJRV *jrv=new JREX_JNI_UTIL::JRexCommonJRV;
     if(IS_NULL(jrv))return NULL;
     jobject jval=NULL;
     nsresult rv=NS_ERROR_FAILURE;
     if (node){
         JREX_LOGLN("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ NODE"<<node)
         nsEmbedString retString;
         nsCOMPtr<nsIDOMNode> domNode = node;
         nsCOMPtr<nsIDOMNode> parentNode;
         nsCOMPtr<nsIDOMDocument> document;
         domNode->GetOwnerDocument(getter_AddRefs(document));
         nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(document));
         if (docView) {
             JREX_LOGLN("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ docView"<<docView)
             nsCOMPtr<nsIDOMAbstractView> defaultView;
             docView->GetDefaultView(getter_AddRefs(defaultView));
             nsCOMPtr<nsIDOMViewCSS> 
defaultCSSView(do_QueryInterface(defaultView));
             if (defaultCSSView) {
                 JREX_LOGLN("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 
docView"<<docView)
                 nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
                 while (PR_TRUE) {
                     nsCOMPtr<nsIDOMElement> 
domElement(do_QueryInterface(domNode));
 
JREX_LOGLN("%%%%%%%%%%%%%%%%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ domNode"<<domNode)
 
JREX_LOGLN("%%%%%%%%%%%%%%%%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 
domElement"<<domElement)
                     // bail for the parent node of the root element or 
null argument
                     if (!domElement)
                         break;
                     nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
                     defaultCSSView->GetComputedStyle(domElement, 
EmptyString(), getter_AddRefs(computedStyle));
                     if (computedStyle) {
 
JREX_LOGLN(">>>>>>>>>>>>>>>>>>>>>>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 
computedStyle"<<docView)
                         nsCOMPtr<nsIDOMCSSValue> cssValue;
                         rv=GetCssText(computedStyle, retString);
                         if (NS_SUCCEEDED(rv)) {
                             char* data=ToNewUTF8String(retString);
                             JREX_LOGLN("SUCCESS! 
 >>>>>>>>>>>>>>>>>>>>>>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ retString"<<data)
                             break;
                         }
                     }

                     domNode->GetParentNode(getter_AddRefs(parentNode));
                     domNode = parentNode;
                 }
             }
         }
         if(NS_SUCCEEDED(rv))
             NS_STR_TO_JSTR(env1, retString, jval)
     }
     if(jval){
         jrv->jobj=env1->NewGlobalRef(jval);
         env1->DeleteLocalRef(jval);
     }else{
         jrv->jobj=NULL;
     }
     jrv->rv=rv;
     return jrv;
}

/*
  * Class:     org_mozilla_jrex_dom_JRexNodeImpl
  * Method:    GetNodeComputedStyle
  * Signature: ()Ljava/lang/String;
  */
JNIEXPORT jstring JNICALL 
Java_org_mozilla_jrex_dom_JRexNodeImpl_GetNodeComputedStyle(JNIEnv * 
env, jobject node) {
     if(!JRexDOMGlobals::sIntialized) return NULL;
     JREX_TRY
     nsIDOMNode* 
thisNode=(nsIDOMNode*)NS_INT32_TO_PTR(env->GetIntField(node, 
JRexDOMGlobals::nodePeerID));
     JREX_LOGLN("GetNodeComputedStyle()--> **** thisNode 
<"<<thisNode<<"> ****")
     if(IS_NULL(thisNode)){
         ThrowJRexException(env, "GetNodeComputedStyle)--> **** thisNode 
DOES NOT EXIST!!! ****", 0);
         return NULL;
     }

     JREX_JNI_UTIL::JRexCommonJRV *jrv=NULL;
     if(IS_EQT){
         JREX_LOGLN("GetNodeComputedStyle--> **** IN EVT Q THREAD ****")
         jrv=JRexNodeImpl_GetNodeComputedStyleInternal(env, thisNode);
     }else{
         nsresult rv=ExecInEventQDOM(thisNode, 
JREX_GET_NODE_COMPUTED_STYLE, nsnull, PR_TRUE,
                                     HandleJRexNodeEvent, 
DestroyJRexNodeEvent, (void**)&jrv);
         JREX_LOGLN("GetNodeComputedStyle--> **** ExecInEventQDOM 
rv<"<<rv<<"> ****")
     }
     JREX_LOGLN("GetNodeComputedStyle)--> **** jrv<"<<jrv<<"> ****")
     if(NOT_NULL(jrv)){
         nsresult rv=jrv->rv;
         jobject jobj=NULL;
         if(jrv->jobj){
             jobj=env->NewLocalRef(jrv->jobj);
             env->DeleteGlobalRef(jrv->jobj);
         }
         delete jrv;
         if(NS_FAILED(rv)){
             if (NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM){
                 JREX_LOGLN("GetNodeComputedStyle()--> **** 
GetNodeComputedStyle DOM ERROR OCCURED !!!****")
                 JRexDOMGlobals::ThrowDOMException(env, rv);
             }else{
                 JREX_LOGLN("GetNodeComputedStyle()--> **** 
GetNodeComputedStyle NON-DOM ERROR OCCURED !!!****")
                 ThrowJRexException(env, "**** GetNodeComputedStyle 
Failed ****", rv);
             }
         }
         return (jstring)jobj;
     }
     JREX_CATCH(env)
     return NULL;
}



I also added this a new value to the JRexNodeEventTypes enum:

enum JRexNodeEventTypes{	JREX_APPEND_CHILD=0U,
...
//CSS
JREX_GET_NODE_COMPUTED_STYLE,
};

and a case in the switch inside HandleJRexEvent to ensure that this call 
is made in the EQT:

void* PR_CALLBACK HandleJRexNodeEvent(PLEvent* aEvent){
...
         case JREX_GET_NODE_COMPUTED_STYLE: {
             JREX_LOGLN("HandleJRexNodeEvent 
JREX_GET_NODE_COMPUTED_STYLE EVENT!!!****")
             return 
(void*)JRexNodeImpl_GetNodeComputedStyleInternal(NULL, node.get());
         }
...
}



fifi wrote:
> Hi,
> 
> 	We would like to get attributes of elements in DOM, like style of the 
> element, whether it is written by bold, italics, getting its font, color, 
> etc. These attributes can be expressed by tag, in the css stylesheet ... Does 
> any method exist for computing these attributes from JRex DOM?
> 
> 	Thanks for your help,
> 
> 		Gyuri Frivolt
>