Last active
February 16, 2016 10:06
-
-
Save zv3/2dad7cb63813e82f8412 to your computer and use it in GitHub Desktop.
Answer to SO question http://stackoverflow.com/questions/18737876/add-script-to-the-head-from-scala-template-tags-in-play-framework-2/35429095#35429095
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// controllers/Application.scala | |
object Application extends Controller { | |
def index = ActionWithAttrs { implicit request => | |
Ok(views.html.index()) | |
} | |
} | |
object ActionWithAttrs extends StackableAction |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@(implicit request: Request[_]) | |
@main{ | |
@indexHead @* content that goes in the head tag *@ | |
} { | |
@indexBody | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import views.support.JavascriptPage | |
@(implicit request: Request[_]) | |
@JavascriptPage.addNonBlockingJS("some-unique-id-for-this-script") { | |
window.alert("mega kill"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package views.support | |
import controllers.{RequestWithAttributes, AttributeKey} | |
import play.api.mvc.{Request, RequestHeader} | |
import play.twirl.api.Html | |
// views/support/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 | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@(head: Html)(body: Html)(implicit request: Request[_]) | |
<html> | |
<head> | |
@head | |
</head> | |
<body> | |
@body | |
@inlineNonBlockingJS @* we append all of our javascript non blocking code (that were added to the Map up until this line) *@ | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers | |
import play.api.mvc._ | |
import scala.collection.concurrent.TrieMap | |
import scala.concurrent.Future | |
import scala.reflect.ClassTag | |
// Borrowed from: https://github.com/rabitarochan/Play2-ChainAction/blob/master/core/src/main/scala/com/github/rabitarochan/play2/stackableaction/StackableAction.scala | |
// controllers/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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment