How to select "a.my" as jquery in lift? - scala

I want to select all <a> with class myin liftweb, and set its text to ???:
val x = <div>
<a><span class="my">xxx</span></a>
<a class="my">yyy</a>
</div>
I tried:
"a .my *" #> "???"
and
"a" #> (".my *" #> "???")
But neither works, because both of them convert the x to:
<div>
<a><span class="my">???</span></a>
<a class="my">???</a>
</div>
Which are incorrect, they should only convert the second <a>.
What's the correct code?

As far as I know, there is no direct way to do that using Lift 2.5 and earlier. I believe they will be adding support for that more robust type of binding to Lift 3, but since it is not here yet you will need to work around it.
Since you can work directly with the NodeSeq on the right of the CssSelector, something like this should allow you to accomplish what you are looking to do:
"a" #> { ns:NodeSeq =>
if((ns \ "#class").text == "my")
("* *" #> "???").apply(ns)
else
ns
}

When I was fighting for another problem, I read this again(https://www.assembla.com/wiki/show/liftweb/binding_via_css_selectors) and I found a solution.
just use
".my" #> ("a *" #> "???")
instead of
"a" #> (".my *" #> "???")
then everything goes well

Related

lift template and snippet returning slick query result

Please excuse if this is a very basic question, I'm learning. :(
I have this class:
class X {
def do_something {
db withSession {
val qresult = for {
(d, o) <- TABLE1 innerJoin TABLE2 on (_.TB1ID === _.TB2ID)
} yield(d, o)
}
}
}
and I would like to build a HTML table out of this, something like:
(record1) d.TB1ID d.F1VALUE d.F2VALUE o.F1VALUE o.F2VALUE o.TB2ID
(record2) d.TB1ID d.F1VALUE d.F2VALUE o.F1VALUE o.F2VALUE o.TB2ID
....
would anyone be kind enough to give me a pointer where to look? I've found plenty of examples but I have trouble connecting the qresult value to something I can bind in my template.
I am using Lift and Slick 1.0.1.
Assuming you have a table in your HTML template that looks like this:
<table>
<tr>
<td class="TB1ID"></td>
<td class="dF1VALUE"></td>
<td class="dF2VALUE"></td>
<td class="oF1VALUE"></td>
<td class="oF2VALUE"></td>
<td class="TB2ID"></td>
</tr>
</table>
Then, you should be able to have your CSS Transform look like:
"tr" #> qresult.map { case (d, o) =>
".TB1ID *" #> d.TB1ID &
".dF1VALUE *" #> d.F1VALUE &
".dF2VALUE *" #> d.F2VALUE &
".oF1VALUE *" #> o.F1VALUE &
".oF1VALUE *" #> o.F2VALUE &
".TB2ID *" #> o.TB2ID
}
That will key on the TR and repeat it for every row in your qresult list. Then, for each of the columns (represented above by their class attribute), it will output the value you want associated with it. Note that the * in the selector will append the value on the right as a child of the TD instead of replacing it with the value on the right.
You can find more information on CSS Selectors and outputting HTML here:
http://simply.liftweb.net/index-7.10.html
https://www.assembla.com/wiki/show/liftweb/binding_via_css_selectors

snippet does not interpret html tags

I need is to display the contents of the list in a snippet.
I have a function like this:
def generateHtml(data: List[Documents]): NodeSeq = {
val html = <ul><li></li></ul>
def css = "li" #> data.map {
document =>
"* *" #> ( document.title + ": " + document.content )
}
css(html)
}
List values ​​have html code like this:
val data: List[Document] = List(Document("<b>title</b> 1", "content 1"),Document("`<b>title</b> 2", "content 2") )
works well because it shows me the list values, but the problem is that it does not interpret the html code (labels <b>)
in my snippet, it shows me something like this:
<b>title</b> 1: content 1
<b>title</b> 2: content 2
but what I need is to interpret the tas b
something like this:
title 1: content 1
title 2: content 2
any suggestion that I can do to interpret the tags
I found a similar problem here:
Scala: Parse HTML-fragment
probe with the solutions, but do not work
This happens because there is a conversion between String to scala.xml.Text, which escapes characters by default. If you wrap the String in scala.xml.Unparsed, it should do what uou are looking for:
def generateHtml(data: List[Documents]): NodeSeq = {
val html = <ul><li></li></ul>
def css = "li" #> data.map {
document =>
"* *" #> scala.xml.Unparsed( document.title + ": " + document.content )
}
css(html)
}
Note that is is not a great idea to do with untrusted content, ie: stuff that a user may enter. In those situations, you would probably be better off using something like Markdown or Textile.
Adding to what jcern said, you'd better keep the titles without the <b></b> inside. And while rendering, you could write
"li" #> data.map(doc => <li><b>{doc.title}</b>: {dot.content}</li> )
alternatevly, and even more better, you can use "CSS transformations" like that:
val html = <ul><li> <b class="title">t</b>: <span class="content">c</span> </li></ul>
// (in real-world render method, the html: NodeSeq is taken as a method parameter)
val transformation = "ul *" #> data.map{ doc =>
".title *" #> doc.title &
".content" #> doc.content
}
transformation(css)

`if else` with or without `()` behaviors different in css transformer of Lift?

The lift code:
import net.liftweb.util.Helpers._
object test extends App {
val xml = <div>
<span name="a">a</span>
<span name="b">b</span>
</div>
val t1 = if (true) {
"#a" #> "xxx"
} else {
"#a" #> "yyy"
} &
"#b" #> "zzz"
val t2 = (if (true) {
"#a" #> "xxx"
} else {
"#a" #> "yyy"
}) &
"#b" #> "zzz"
println("------------- t1 ------------")
println(t1(xml))
println("------------- t2 ------------")
println(t2(xml))
}
The output:
------------- t1 ------------
<div>
xxx
<span name="b">b</span>
</div>
------------- t2 ------------
<div>
xxx
zzz
</div>
Strange, right? The only difference is that the t2 has wrapped if else with ().
My friend decompiled the bytecode and found that scala has compiled the t1 similar to:
t1 = true ? "#a" #> "xxx" : "#a" #> "yyy" & "#b" #> "zzz"
As if the code is:
if (true)
"#a" #> "xxx"
else
"#a" #> "yyy" &
"#b" #> "zzz"
Where is wrong?
I guess it has to do with the operator precedence and the way code is parsed. To get a very precise answer one would have to look closely at Scala's spec.
In general, I would recommend to write a function for #a and another for #b to make things really clear when reading code. E.g.:
def ta =
if (true) "#a" #> "xxx"
else "#a" #> "yyy"
def tb = "#b" #> "zzz"
val t1 = ta & tb
Scala has a very lightweight syntax that encourages such definition unlike many other programming language. Your code tend to be much more readable when using it. Have a look at Odersky's talk on Scala with Style. He explains other interesting tricks too.
Nothing is wrong. { } around a single statement doesn't make any changes to the code. Remember, the result of a block is the result of the last statement, so if you have just one, you can also omit the { }. But even if you had multiple statements, the & is binding first, see as an example
if (false) {true; 1} else {false; 3} & {true; 2}
The result is 2 (the result of 3&2).

(Lift) Ajax submit using SHtml.select onchange event

I'm tring to implement the classic functionality of this select:elements depends on this other select:selection using Lift, E.g. select the country and get the possible states for the selected country.
The problem that I'm facing is that the "this.myForm.submit()" that I have inside the onchange of the select element is not firing the ajax request. If I use an input type"submit" it works perfectly.
Is this behaivior related with Lift framework? Is there a better way of implementing this kind of functionality using Lift libraries?
The relevant snipped code:
"name=distributionPoints" #> SHtml.select(distributionPoints, Empty, selectedDistributionPoint = _, "id" -> "the_distributionPoints") &
"name=devices" #> (SHtml.select(devices, Empty, selectedDevice = _, "id" -> "the_devices") ++ SHtml.hidden(process))
The view html:
<form class="lift:form.ajax">
<select name="distributionPoints" id="the_distributionPoints" onchange="submit()">
<option></option>
</select>
<br/>
Device:
<select name="devices" id="the_devices">
<option></option>
</select>
</form>
The rendered HTML:
<form id="F391649920812YBACEZ" action="javascript://" onsubmit="liftAjax.lift_ajaxHandler(jQuery('#'+"F391649920812YBACEZ").serialize(), null, null, "javascript");return false;">
<div>
Punto de distribución:
<select onchange="submit()" id="the_distributionPoints" name="F630704816482OLP514"></select>
<br />
Equipo:
<select name="F391649920817BLRJW5" id="the_devices"></select><input type="hidden" name="F391649920818HPS35E" value="true" />
<br />
</div>
</form>
[edit]
I finally got the solution. Like Chris mentioned I used ajaxSelect instead of just selects and instead of using setHtml there's a method called JsCmds.ReplaceOptions that does exactly what I was looking for.
You should understand that when using Ajax submit the page is not reloaded. So I would suggest you to use JsCmds.setHtml on server side to "reset" the second select element.
So, in fact the first select is an ajaxSelect which is meant to modify the second one (so it is not concerned by the hidden submit in my opinion). The second select is updated when the first one is changed, using 'selectPoint(s)'
Piece of Scala code
def selectPoint(s):JsCmd = {
selectedDistributionPoint = s;
newDevices:List[String] = findCorrespondingDevices(s);
JsCmds.setHtml("name=devices", SHtml.select(newDevices, Empty, selectedDevice = _, "id" -> "the_devices")) ++ SHtml.hidden(process))
}
"name=distributionPoints" #> SHtml.AjaxSelect(distributionPoints, Empty, s=> selectPoint(s), "id" -> "the_distributionPoints") &
"name=devices" #> (SHtml.select(Nil, Empty, selectedDevice = _, "id" -> "the_devices") ++ SHtml.hidden(process))
Piece of template code
<input name="distributionPoints" id="the_distributionPoints" onchange="submit()"/>
<input name="devices" id="the_devices"/>

BeautifulSoup: get tag name of element itself, not its children

I have the below (simplified) code, which uses the following source:
<html>
<p>line 1</p>
<div>
<a>line 2</a>
</div>
</html>
soup = BeautifulSoup('<html><p>line 1</p><div><a>line 2</a></div></html>')
ele = soup.find('p').nextSibling
somehow_print_tag_of_ele_here
I want to get the tag of ele, in this case "div". However, I only seem to be able to get the tag of its children. Am I missing something simple? I thought that I could do ele.tag.name, but that is an exception since tag is None.
#Below correctly prints the div element "<div><a>line 2</a></div>"
print ele
#Below prints "None". Printing tag.name is an exception since tag is None
print ele.tag
#Below prints "a", the child of ele
allTags = ele.findAll(True)
for e in allTags:
print e.name
At this point, I am considering doing something along the way of getting the parent of ele, then getting the tags of parent's children and, having counted how many upper siblings ele has, counting down to the correct child tag. That seems ridiculous.
ele is already a tag, try doing this:
soup = BeautifulSoup('<html><p>line 1</p><div><a>line 2</a></div></html>')
print(soup.find('p').nextSibling.name)
so in your example it would be just
print(ele.name)
You can access anything inside an element as if accessing a dictionary.
Let's say you have an element like this one.
<input id="__VIEWSTATE3" name="__VIEWSTATE3" type="hidden" value="MwqzeTH4"/>
You can access each property like this
print(elem["id"])
# prints __VIEWSTATE3
print(soup.find('h1',id_='pdp_product_title'))
it doesnot print any detail please solved this
<h1 id="pdp_product_title" class="headline-2 css-zis9ta" data-test="product-title">Nike Air Force 1 Shadow</h1>