我想从标签内添加javascript到我网页的<head>
。
这是我在我的网页上使用的更多脚本:
main.scala.html
@(title: String, scripts: Html = Html(""))(content: Html)
<!DOCTYPE html>
<html lang="nl">
<head>
<title>@title</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
@scripts
</head>
<body>
@content
</body>
</html>
page.scala.html
@scripts = {
<script type="text/javascript">
$(document).ready(function() {
alert(1);
});
</script>
}
@main("Title", scripts) {
<p>page content</p>
}
到目前为止一切顺利!但是我想在我编写的标签(组件)中做同样的事情,需要在网页中包含一些javascript代码。
我的问题是如何将<script>
元素从标记传递到main.scala.html
?
所以page.scala.html
将是:
page.scala.html
@import tags._
@main("Title") {
@mytag("green")
}
mytag.scala.html
@(color: String)
<script type="text/javascript">
$(document).ready(function() {
alert('@color');
});
</script>
<p>Some more content</p>
在这种情况下,<script>
标记会在HTML页面的中间呈现,我想将<script>
标记传递到@scripts
变量中,以便在<head>
内呈现} tag。
答案 0 :(得分:4)
好的,我想出了一个更好的解决方案恕我直言。
我创建了以下标记:
<强> script.scala.html 强>
@(content: Html)
@{
var additionalScripts = ctx().args.get("additionalScripts").asInstanceOf[List[Html]];
if(additionalScripts == null) {
additionalScripts = new ArrayList[Html]();
ctx().args.put("additionalScripts", additionalScripts)
}
val added = additionalScripts.add(content);
}
<强> renderscripts.scala.html 强>
@additionalScripts = @{ctx().args.get("additionalScripts").asInstanceOf[List[Html]]}
@if(additionalScripts != null) {
@for(additionalScript <- additionalScripts) {
@additionalScript
}
}
在main.scala.html
中,您可以使用:
@(title: String)(content: Html)
@import tags._
<!DOCTYPE html>
<html lang="nl">
<head>
<title>@title</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
@renderscripts()
</head>
<body>
@content
</body>
</html>
您可以使用以下方法在模板或标签中指定其他脚本:
@import tags._
@script {
<script type="text/javascript">
$(document).ready(function() {
alert('This will be in the head!');
});
</script>
}
这很好,对吗? :)
也许有人可以使用他们的Scala魔法来清理或增强我的代码:)
答案 1 :(得分:0)
这是可行的,但我同意ajozwik,并说你的脚本内联将变得更容易,并且仍然可以正常工作。
您可以执行的操作是将另一个参数组(基本上是另一个(content:Html)
)添加到您的主模板,该模板将使用<script>
生成mytag
标记。
<强> main.scala.html 强>
@(title: String, scripts: Html = Html(""))(content: Html)(implicit mytagScripts: Html = null)
<!DOCTYPE html>
<html lang="nl">
<head>
<title>@title</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
@scripts
@mytagScripts
</head>
<body>
@content
</body>
</html>
在您使用mytag
的任何视图上,您需要定义mytagScripts
的值。它是隐含的,因此您不必在不使用它的模板上定义它,它只使用默认值。
除了您需要生成<script>
并将其存储以供日后使用之外,您的标记模板不会发生太大变化。我们可以使用Context.args
地图。
<强> mytag.scala.html 强>
@(color:String)
@{ctx().args.put("mytagScriptHtml", new Html("<script>alert('" + color + "');</script>"))}
<div>
<!-- whatever else you're tag is generating -->
</div>
最后,你的页面看起来像这样。请注意第二组花括号,它是主模板上定义mytagScripts
的内容。组之间的关闭/打开括号必须在同一行上,否则您将收到编译器错误。
<强> page.scala.html 强>
@import tags._
@main("Title") {
@mytag("green")
} {
@ctx().args.get("mytagScriptHtml")
}
简化示例...如果您希望在页面中多次使用该标记,则需要跟踪<script>
中的List
标记或其他内容。同样的概念,因为您可以在Object
中存储任何Context.args
。
答案 2 :(得分:0)
为什么不直接将mytag
传递给main
:
page.scala.html
:
@import tags.html.mytag
@main("Title", mytag("green")) {
<p>page content</p>
}
答案 3 :(得分:0)
我在Play-scala 2.4中做了类似的事情,但是在主体关闭标签之前有脚本进入页脚。我不熟悉Play的java api,但我相信这个概念仍然有用。
这是要点:https://gist.github.com/zv3/2dad7cb63813e82f8412
控制器/ StackableAction.scala
// Borrowed from: https://github.com/rabitarochan/Play2-ChainAction/blob/master/core/src/main/scala/com/github/rabitarochan/play2/stackableaction/StackableAction.scala
abstract class StackableAction extends ActionBuilder[RequestWithAttributes] with StackableFilter {
override def filter[A](request: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Future[Result]): Future[Result] = {
f(request)
}
def invokeBlock[A](req: Request[A], block: RequestWithAttributes[A] => Future[Result]): Future[Result] = {
val reqWA = new RequestWithAttributes(req, new TrieMap[AttributeKey[_], Any]())
filter(reqWA)(block)
}
}
trait StackableFilter {
def filter[A](request: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Future[Result]): Future[Result]
}
trait AttributeKey[A] {
def ->(value: A): Attribute[A] = Attribute(this, value)
}
case class Attribute[A](key: AttributeKey[A], value: A) {
def toTuple: (AttributeKey[A], A) = (key, value)
}
class RequestWithAttributes[A](request: Request[A], attributes: TrieMap[AttributeKey[_], Any]) extends WrappedRequest[A](request) {
def get[B](key: AttributeKey[B]): Option[B] = attributes.get(key).asInstanceOf[Option[B]]
def set[B](key: AttributeKey[B], value: B): RequestWithAttributes[A] = {
attributes.put(key, value)
this
}
def getAll[T](implicit classTag: ClassTag[T]) = {
attributes.filterKeys {
case p: T => true
case _ => false
}
}
}
视图/支撑/ JavascriptPage.scala
object JavascriptPage {
case class NonBlockingJS(key: String) extends AttributeKey[Html]
case class BlockingJS(key: String) extends AttributeKey[Html]
def addNonBlockingJS(div: String)(jscript: Html)(implicit request: Request[_]): Unit = {
request match {
case i: RequestWithAttributes[_] =>
i.set(NonBlockingJS(div), jscript)
case _ =>
}
}
// scripts that are supposed to go into the <head> tag, thus blocking scripts
def addBlockingJS(div: String)(jscript: Html)(implicit request: Request[_]): Unit = {
request match {
case i: RequestWithAttributes[_] =>
i.set(BlockingJS(div), jscript)
case _ =>
}
}
// scripts that are supposed to go before the </body> tag, non blocking scripts that is
def getNonBlockingJS()(implicit request: Request[_]): Seq[(String, Html)] = {
request match {
case i: RequestWithAttributes[_] =>
i.getAll[NonBlockingJS].toSeq.map {
case (NonBlockingJS(div), jscript: Html) => (div, jscript)
}
case _ => Seq.empty
}
}
}
inlineNonBlockingJS.scala.html
@import views.support.JavascriptPage
@(implicit request: Request[_])
<script src="/javascripts/your_javascript_app.js"></script>
<script id="non-blocking" type="text/javascript">
@defining(JavascriptPage.getNonBlockingJS()) { scripts =>
@scripts.map { case (_, item) => @item }
}
</script>
它基本上将请求(使用play的动作组合)包含在一个案例类中,该案例类将TrieMap作为其成员之一,然后将其作为与请求关联的额外属性的持有者,这些属性可以是javascript条目以及在请求期间你想拥有和分享的其他任何东西。