diff --git a/build.sbt b/build.sbt index e93dad5..92089b5 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,7 @@ workbenchSettings name := "Scala.js+Vue.js example" -version := "0.2" +version := "2.2.4" scalaVersion := "2.11.8" @@ -14,7 +14,7 @@ libraryDependencies ++= Seq( "org.scala-js" %%% "scalajs-dom" % "0.9.1" ) -bootSnippet := "example.T1().main(document.getElementById('mydiv'));" +bootSnippet := "" updateBrowsers <<= updateBrowsers.triggeredBy(fastOptJS in Compile) diff --git a/project/plugins.sbt b/project/plugins.sbt index 04b6712..36e4eb0 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.12") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.14") addSbtPlugin("com.lihaoyi" % "workbench" % "0.2.3") \ No newline at end of file diff --git a/src/main/resources/index-dev.html b/src/main/resources/index-dev.html index 862773f..e89e6e9 100644 --- a/src/main/resources/index-dev.html +++ b/src/main/resources/index-dev.html @@ -26,56 +26,14 @@ height: 20px; background: black; } -.bounce-enter { - -webkit-animation: bounce-in .5s; - animation: bounce-in .5s; -} -.bounce-leave { - -webkit-animation: bounce-out .5s; - animation: bounce-out .5s; -} -@-webkit-keyframes bounce-in { - 0% { - -webkit-transform: scale(0); + .fade-enter-active, .fade-leave-active { + transition: opacity .5s } - 50% { - -webkit-transform: scale(1.2); + .fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ { + opacity: 0 } - 100% { - -webkit-transform: scale(1); - } -} - -@keyframes bounce-in { - 0% { - transform: scale(0); - } - 50% { - transform: scale(1.2); - } - 100% { - transform: scale(1); - } -} - -@-webkit-keyframes bounce-out { - 0% { - -webkit-transform: scale(1); - } - 100% { - -webkit-transform: scale(0); - } -} -@keyframes bounce-out { - 0% { - transform: scale(1); - } - 100% { - transform: scale(0); - } -} @@ -84,14 +42,16 @@
Title= -
    -
  1. - - {{content}} - - -
  2. -
+ + +
  • + + {{todo.content}} + + +
  • +
    + Tasks# {{todos.length}}
    N={{n}}
    @@ -99,31 +59,30 @@
    Using a v-text directive title= -
    Smooth CSS animation: - - +
    Smooth CSS animation: + +
    -
    +
    Title reversed={{title | reverse}}
    -
    Title wrapper={{title | wrap '<<' '>>'}}
    -
    xx
    - Special content - - - - - - - -

    - Via custom filter - Via computed property +
    Title wrapper={{title | wrap('<<','>>')}}
    +
    xx
    + Special content + + + + + + + +

    + Todos computed: {{ todosComputed }}
    - +
    @@ -133,17 +92,11 @@ // custom filter to pull out field // Now done in Scala. -//Vue.filter('extract', function (value, keyToExtract) { -// return value.map(function (item) { -// return item[keyToExtract] -// }) -// }) // we get DemoVue back from Scala, then use it var demo=example.Todo().main(); - demo.title="Todo Todo Todo" + demo.todos.push({done:false,content:"Extra task"}) - //demo.todos[0]=({done:false,content:"!!!!"}) - //demo.todos.$set(0, {done:false,content:"!!!!"}) + diff --git a/src/main/scala/com/felstar/scalajs/vue/Vue.scala b/src/main/scala/com/felstar/scalajs/vue/Vue.scala index b7c6249..445698d 100644 --- a/src/main/scala/com/felstar/scalajs/vue/Vue.scala +++ b/src/main/scala/com/felstar/scalajs/vue/Vue.scala @@ -26,13 +26,12 @@ import js.annotation.JSName def $watch(expOrFn:js.Any,callback:Callback):Unwatch=js.native def $watch(expOrFn:js.Any,callback:Callback,options:js.Any):Unwatch=js.native def $get(exp:String):js.Any=js.native - def $set(keypath:String,value:js.Any):Unit=js.native + def $set(target:js.Any,key:js.Any, value:js.Any):Unit=js.native + def $delete(target:js.Any,key:js.Any):Unit=js.native def $add(key:String,value:js.Any):Unit=js.native - def $delete(key:String):Unit=js.native def $eval(exp:String):js.Any=js.native def $interpolate(templateString:String):js.Any=js.native - def $log(keypath:String):Unit=js.native - def $log():Unit=js.native + // Events def $dispatch(event:String):Unit=js.native def $dispatch(event:String,args:js.Any):Unit=js.native @@ -87,26 +86,22 @@ import js.annotation.JSName def transition(id:String):js.Any=js.native def transition(id:String,definition:js.Any):js.Any=js.native def partial(id:String):js.Any=js.native - def partial(id:String,template:String):js.Any=js.native + def partial(id:String,template:String):js.Any=js.native def use(plugin:js.Any):js.Any=js.native def use(plugin:js.Any,args:js.Any*):js.Any=js.native + def set(target:js.Any,key:js.Any, value:js.Any):Unit=js.native + def delete(target:js.Any,key:js.Any):Unit=js.native } - @js.native - trait VueArray[T] extends js.Array[T]{ - def $set(idx:Int,obj:T):Unit=js.native - def $remove(idx:Int):Unit=js.native - } - @js.native class Directive extends js.Object { - val el:dom.raw.Element =js.native - val vm:Vue =js.native - val expression:js.Any =js.native - val arg:String =js.native - val raw:String =js.native - val name:String =js.native + val name:String =js.native + val rawName:String =js.native + val value:String =js.native + val expression:String =js.native + val modifiers:js.Any =js.native + val `def`:js.Any =js.native } - - + + diff --git a/src/main/scala/example/Todo.scala b/src/main/scala/example/Todo.scala index 71b2cf0..cc807e8 100644 --- a/src/main/scala/example/Todo.scala +++ b/src/main/scala/example/Todo.scala @@ -1,34 +1,35 @@ package example import org.scalajs.dom + import scalajs.js.annotation.JSExport import scala.scalajs.concurrent.JSExecutionContext.Implicits.runNow import dom.ext.Ajax + import scalajs.js import js.Dynamic.literal import com.felstar.scalajs.vue._ +import org.scalajs.dom.raw.HTMLElement + import js.annotation.JSName @JSExport object Todo extends { - // Strongly typed wrapper around below dynamic Vue - // You don't have to do this, can access as js.Dynamic - // But obviously type safety is a good thing, a Scala thing. @js.native trait DemoVue extends Vue{ var title:String=js.native var n:Double=js.native - var todos:VueArray[DemoVueTodo]=js.native - } - + var todos:js.Array[DemoVueTodo]=js.native + } + type DemoVueMethod=js.ThisFunction0[DemoVue,_] - + @js.native - trait DemoVueTodo extends js.Object{ + trait DemoVueTodo extends js.Object{ var done:Boolean=js.native var content:String=js.native } - + object DemoVueTodo{ def apply(done:Boolean,content:String)=literal(done=done,content=content).asInstanceOf[DemoVueTodo] } @@ -38,59 +39,47 @@ object Todo extends { // could have returned raw Vue of course def main():DemoVue = { - val tasks=js.Array("Learn JavaScript","Learn Vue.js","Learn Scala.js") - + val tasks=js.Array("Learn JavaScript","Learn Vue.js","Learn Scala.js") +// def ts=new java.util.Date().toString Vue.component("my-component", literal( props=js.Array("myMsg"), - template="

    A custom component with msg {{myMsg}} default content

    ")) + template="

    A custom component with msg {{myMsg}} default content

    ")) - // Note, don't need to define as js.ThisFunction, as signature expects this -// Vue.directive("my-directive", (directive:Directive,value:js.Any)=> { -// println(s"myDirective! expression=${directive.expression} arg=${directive.arg} raw=${directive.raw} name=${directive.name} value=$value ") -// directive.el.innerHTML="This comes from my-directive "+directive.raw+" "+value -// }) - - + Vue.directive("mydirective", literal( + update=(el:HTMLElement, directive:Directive)=>{el.innerHTML="This comes from my-directive with contents "+directive.value+" and expression "+directive.expression} + ) + ) + val demo = new Vue( literal(el="#demo", data=literal( + message="Hello Vue.js!!!!!", title="Todo App", - todos=tasks.map(content=>literal(done=content==tasks.head,content=content)), + todos=tasks.map(content=>literal(done=content==tasks.head,content=content)), barValue= 100, - n=0 - ), + n=0 + ),//, // js.ThisFunction would be fine, just trying to be more type specific methods=literal(clickHandler=((demoVue:DemoVue)=>demoVue.n-=1):DemoVueMethod, addTask=((demoVue:DemoVue)=>demoVue.todos.append(DemoVueTodo(false,s"new $ts"))):DemoVueMethod, - change1st=((demoVue:DemoVue)=>demoVue.todos.$set(0,DemoVueTodo(false,ts))):DemoVueMethod, - remove=((demoVue:DemoVue,idx:Int)=>demoVue.todos.$remove(idx)):js.ThisFunction1[DemoVue,Int,_], - flipAll=((demoVue:DemoVue)=>demoVue.todos.foreach(td=>td.done= !td.done)):DemoVueMethod + change1st=((demoVue:DemoVue)=>Vue.set(demoVue.todos, 0,DemoVueTodo(false,ts))):DemoVueMethod, + remove=((demoVue:DemoVue,idx:Int)=>Vue.delete(demoVue.todos,idx)):js.ThisFunction1[DemoVue,Int,_], + flipAll=((demoVue:DemoVue)=>demoVue.todos.foreach(td=>td.done= !td.done)):DemoVueMethod ), - computed=literal(todosFiltered=(demoVue:DemoVue)=> demoVue.todos.map(_.content)), - - filters=literal(reverse=((value:js.Any)=>value.toString.reverse), + computed=literal(todosComputed=(demoVue:DemoVue)=> demoVue.todos.map(_.content)), +// + filters=literal(reverse=((value:js.Any)=>value.toString.reverse), wrap=(value:js.Any,begin:String, end:String)=>begin+value.toString+end, extract=(array:js.Array[js.Dynamic],field:String)=> - if (js.isUndefined(array)) array else array.map(_.selectDynamic(field)) - ), - events=literal(greeting= ((demoVue:DemoVue,msg:js.Any)=> println(s"Greeting $msg")):js.ThisFunction, - greeting2= (msg:js.Any)=> println(s"Greeting2 $msg") - ), - directives=literal( // directives get passed a Directive object. - myDirective= ((directive:Directive,value:String)=> { - println(s"myDirective expression=${directive.expression} arg=${directive.arg} raw=${directive.raw} name=${directive.name} value=$value "); - directive.el.innerHTML="This comes from my-directive "+directive.raw+" "+value - }):js.ThisFunction - ) - ) + if (js.isUndefined(array)) array else array.map(_.selectDynamic(field)) + ) + ) ) - demo.$watch("title+' < println("changed "+newValue)) - demo.$emit("greeting","hello") - demo.$emit("greeting2","goodbye") - + demo.$watch("title",(newValue:String, oldValue:String) => println("changed "+newValue)) + val demoVue=demo.asInstanceOf[DemoVue] // filters declared above inline, can be also done as below @@ -99,7 +88,7 @@ object Todo extends { // println(js.JSON.stringify(demo.$data)) - demo.$log + //demo.$log demoVue }