blob: 66961fd6758efd2ba404be0da7ebb6c5523afe37 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zeppelin.display.angular
import java.io.PrintStream
import org.apache.zeppelin.annotation.ZeppelinApi
import org.apache.zeppelin.display.{AngularObjectWatcher, AngularObject}
import org.apache.zeppelin.interpreter.{InterpreterResult, InterpreterContext}
import scala.xml._
/**
* Element that binded to Angular object
*/
abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
val modelName: String,
val angularObjects: Map[String, AngularObject[Any]],
prefix: String,
label: String,
attributes1: MetaData,
scope: NamespaceBinding,
minimizeEmpty: Boolean,
child: Node*)
extends Elem(prefix, label, attributes1, scope, minimizeEmpty, child:_*) {
val uniqueId = java.util.UUID.randomUUID.toString.replaceAll("-", "_")
/**
* On click element
*
* @param callback
* @return
*/
@ZeppelinApi
def onClick(callback: () => Unit): AbstractAngularElem = {
onEvent("ng-click", callback)
}
/**
* On
*
* @param callback
* @return
*/
@ZeppelinApi
def onChange(callback: () => Unit): AbstractAngularElem = {
onEvent("ng-change", callback)
}
/**
* Bind angularObject to ng-model directive
*
* @param name name of angularObject
* @param value initialValue
* @return
*/
@ZeppelinApi
def model(name: String, value: Any): AbstractAngularElem = {
val registry = interpreterContext.getAngularObjectRegistry
// create AngularFunction in current paragraph
val elem = this % Attribute(None, "ng-model",
Text(s"${name}"),
Null)
val angularObject = addAngularObject(name, value)
.asInstanceOf[AngularObject[Any]]
newElem(
interpreterContext,
name,
angularObjects + ((name, angularObject)),
elem)
}
@ZeppelinApi
def model(name: String): AbstractAngularElem = {
val registry = interpreterContext.getAngularObjectRegistry
// create AngularFunction in current paragraph
val elem = this % Attribute(None, "ng-model",
Text(s"${name}"),
Null)
newElem(
interpreterContext,
name,
angularObjects,
elem)
}
/**
* Retrieve value of model
*
* @return
*/
@ZeppelinApi
def model(): Any = {
if (angularObjects.contains(modelName)) {
angularObjects(modelName).get()
} else {
None
}
}
/**
*
* @param eventName angular directive like ng-click, ng-change, etc.
* @return
*/
@ZeppelinApi
def onEvent(eventName: String, callback: () => Unit): AbstractAngularElem = {
val registry = interpreterContext.getAngularObjectRegistry
// create AngularFunction in current paragraph
val functionName = eventName.replaceAll("-", "_") + "_" + uniqueId
val elem = this % Attribute(None, eventName,
Text(s"${functionName}=${functionName} + 1"),
Null)
val angularObject = addAngularObject(functionName, 0)
angularObject.addWatcher(new AngularObjectWatcher(interpreterContext) {
override def watch(oldObject: scala.Any, newObject: scala.Any, context: InterpreterContext)
:Unit = {
InterpreterContext.set(interpreterContext)
callback()
}
})
newElem(
interpreterContext,
modelName,
angularObjects + ((eventName, angularObject)),
elem)
}
protected def addAngularObject(name: String, value: Any): AngularObject[Any]
protected def newElem(interpreterContext: InterpreterContext,
name: String,
angularObjects: Map[String, AngularObject[Any]],
elem: scala.xml.Elem): AbstractAngularElem
/**
* disassociate this element and it's child from front-end
* by removing angularobject
*/
@ZeppelinApi
def disassociate() = {
remove(this)
}
/**
* Remove all angularObject recursively
*
* @param node
*/
private def remove(node: Node): Unit = {
if (node.isInstanceOf[AbstractAngularElem]) {
node.asInstanceOf[AbstractAngularElem].angularObjects.values.foreach{ ao =>
interpreterContext.getAngularObjectRegistry.remove(ao.getName, ao.getNoteId, ao
.getParagraphId)
}
}
node.child.foreach(remove _)
}
/**
* Print into provided print stream
*
* @return
*/
@ZeppelinApi
def display(out: java.io.PrintStream): Unit = {
out.print(this.toString)
out.flush()
}
/**
* Print into InterpreterOutput
*/
@ZeppelinApi
def display(): Unit = {
val out = interpreterContext.out
out.setType(InterpreterResult.Type.ANGULAR)
out.write(this.toString())
out.flush()
}
}