Calling a method from XBL - xul

From a XBL method, when I need to call another method, I do like:
<method name="myMethod_1">
<body>
<![CDATA[
// do staff
]]>
</body>
</method>
<method name="myMethod_2">
<body>
<![CDATA[
document.getElementById("thisElementID").myMethod_1();
]]>
</body>
</method>
I would like to know if is there a way to call the local method without need the element id? I've tried this.myMethod_1() but it says the method don't exist.

In the specific case of an event listener, there is another way around the problem, and that is to pass the element itself as the listener. Of course you only get one handleEvent method, so this is less useful if you're listening to lots of different events on lots of different event targets.
<implementation implements="nsIDOMEventListener">
<method name="handleEvent">
<parameter name="aEvent"/>
<body>
<![CDATA[
// do stuff
]]>
</body>
</method>

can you show us code calling myMethod_2? If you call it like: document.getElement(...).myMethod_2() that's fine, but if you have something like someElement.addEventHandler("click", myxbl.myMethod_2,...); that won't work since event target will be this.
This is important for determining what is this in that context
EDIT: (Tom's reply)
ow, think I got it.. it's exactly this the problem.. I'm calling it from a keypress listener of another document, and the "this" was not what I think..

Related

Android: data-binidng: disable click

I want to disable click when variable isAgree is false:
here code:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="handler"
type="myproject.ui.SubscribeBrandDialogFragment" />
</data>
<TextView
android:id="#+id/subscribeTextView"
android:layout_width="185dp"
android:layout_height="40dp"
android:layout_marginTop="#dimen/default_margin"
android:background="#{handler.isAgree ? #drawable/border_enable_bg : #drawable/border_disable_bg}"
android:gravity="center"
android:onClick="#{handler.isAgree ? handler.onClickSubscribe() : null}"
android:textColor="#{handler.isAgree ? #color/color_primary : #color/disable_text_color}" />
</layout>
But I get error in android:onClick :
e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Cannot find the setter for attribute 'android:onClick' with parameter type void on android.widget.TextView.
file:myproject\layout\subscribe_brand_dialog.xml
loc:100:31 - 100:81
****\ data binding error ****
at android.databinding.tool.processing.Scope.assertNoError(Scope.java:112)
at android.databinding.annotationprocessor.ProcessDataBinding.doProcess(ProcessDataBinding.java:101)
at android.databinding.annotationprocessor.ProcessDataBinding.process(ProcessDataBinding.java:65)
at org.jetbrains.kotlin.kapt3.ProcessorWrapper.process(annotationProcessing.kt:131)
I know that I can fix this by java code. But I want fix this ONLY in xml layout.
Use lambda expression.
android:onClick="#{() -> handler.isAgree ? handler.onClickSubscribe() : null}"
Well a couple things.
First, I would use the controls properties the way they are meant to be used. Setting null on the click handler does not appropriately handle the UI element, you are merely hacking.
You should be disabling the click property or focus property based on your boolean, rather then toggling click handlers to null.
Secondly typically when you are doing Terinaray statements in xml click events I have seen the handler::methodName used rather then handler.methodName to ensure it is handled property in the generated databinding classes for onClick.
Lastly, if you already have the agreed boolean, why not just handle the click in the code. You literally saved yourself 1 line for another line if you think about it.
myClick()
if(isAgree) . //you saved this
.
now you have to do this
ObservableBoolean<> myBool = new ObservableField()
myBool.set(true/false)
of you are adding the
#Bindable to a method.
Either way you are not really saving code by doing the boolean check in the xml and you lose your ability to unit test it or debug. Just my two cents.

How to remove version from the extent report

I am using the extent report in my selenium project ,i want to remove the version showing in the right corner of the report.
can any one help me on this.
Do you have a extent-config.xml file?
Find in there something that looks like this:
<styles>
<![CDATA[
]]>
</styles>
And add your custom css. You'll have to inspect the element you want to hide, to find a selector for it. And then you can add css, something like this:
<styles>
<![CDATA[
#id-of-the-element{display:none};
]]>
</styles>
Alternate solution:
You will find something like this in extent-config.xml
<scripts>
<![CDATA[
$(document).ready(function() {
});
]]>
</scripts>
Simply make this change:
<scripts>
<![CDATA[
$(document).ready(function() {
document.getElementsByClassName("class name")[1].remove()
});
]]>
</scripts>

Pass parameters to all views

I have a play application (Play 1.2.4). In each page in my application I want to have access to the logged in user (using groovy). So I can perform permission check etc. I tried to put this in the main template just before the doLayout
#{set user:user/}
I can have access to the user in the main page of my application, but when going through links to other pages I can no longer have access to the user variable.
I think you had misunderstanding about using #{set} and #{get} tag on Play!Framework. Look at the documentation on #{set} and #{get} tag.
I give you example, you have three templates like follows:
main.html
<html>
<head>
<title>#{get 'title' /}</title>
</head>
<body>
#{doLayout /}
</body>
</html>
template1.html
#{extends 'main.html' /}
#{set title:header /}
<p>This is template1.html page</p>
template2.html
#{extends 'main.html' /}
#{set title:header /}
<p>This is template2.html page</p>
And the methods on controllers like these:
public static void template1() {
String header = "Template 1 Title"
render(header);
}
public static void template2() {
render();
}
This is the explanation, when you render template1.html, you may notice that we are set the page title (by using header variable) in template1.html. The title that we set, is retrieved on main.html by using #{get} on main.html.
Then look when you render template2.html, you may notice we are set the page title too. But the difference is in the controllers (on template2() method), you have not passed header variable value to the template. So, although you have set the title, the title have null value and the implication the title was not set when you render template2.html.
So, for your problem, I think when you insist to place #{set user:user /} on template and want to access user variable, you must pass the user variable on all controller methods before rendering the template. Ugh.. It's so inefficient!
Suggestion
I suggest you that you may use session to store the user data like userid, because it is accessible in all your application templates! Please look at the documentation here.
Hope this can make you understand the mechanism and will so

JSTL based nested iteration

Assume you have the following code:
<c:if test="${fn:length(myIterator) > 0}">
<span>blabla</span>
<c:forEach var="myVar" items="${myIterator}" varStatus="status">
// some stuff
</c:forEach>
<br />
</c:if>
Note that myIterator is an Iterator (surprise, surprise *g).
The problem is that I do not end up in the each loop and do not see "// some stuff" to happen. I think the reason is that fn:length(myIterator) has already iterated over the Iterator to determine its size so that we have already reached the end when arriving at the forEach loop.
I have not seen any elegant way to reset the iterator manually or so.
Of course I could try using scriptlet code (something like <% myIterator.reset() %>, but I would like to avoid that.
I have also tried something like:
<c:if test="${not empty myIterator}">
But that did not work either (did not even enter the if-clause's body).
Any elegant suggestions?
Thanks.
Why are you referring to an Iterator. That should be a Collection like an ArrayList or something.
an iterator can only be iterated once
[EDIT]
IMHO, the cleanest approach is to change the Java controller to give you a Collection. However, based on your feedback that you dont want to or can't...
Change the Java code
Use Java scriptlets in your JSP
You can solve this with some Javascript/DHTML. Consider this JSP code
<script type="text/javascript">
var loopHasContent = false;
</script>
<div id="loop-content" style="display:none">
<span>blabla</span>
<c:forEach var="myVar" items="${myIterator}" varStatus="status">
<script type="text/javascript">
loopHasContent = true;
</script>
// some stuff
</c:forEach>
<br />
</div>
<script type="text/javascript">
if(loopHasContent) {
document.getElementById("loop-content").style.display = "block";
}
</script>
You only reference the Iterable once so your issue goes away. The div is not displayed by default. As long as your forEach loop executes at least once then the javascript variable loopHasContent is set to true, otherwise it remains false. The final javascript trailing the div will only show your loop-content if it has to.

Can I give a XBL handler a name to call it?

Can I give a XBL handler a name, so I can call it from my javascript like I do with XBL methods?
It seems not, but you can create an XBL Method and call it from both your handler and other JavaScript. Something like:
<handler event="mouseover">
this.handleMouseOver();
</handler>
...
<method name="handleMouseOver">
<body>...
//and in javascript code:
yourObj.handleMouseOver();