Extending jQuery

Extending jQuery using Scala.js is done by extending the famous jQuery $ symbol. We can create a file named Notify.scala in the io.fscala.shopping.client package, in the client project.

In this file, we can first define the extension with the following piece of code:

@js.native
@JSGlobal("$")
object NotifyJS extends js.Object {
  def notify(msg: String, option: Options): String = js.native
}

An object named NotifyJS is defined, extending the Scala.js object named js.Object. It is necessary to inform the compiler that we are creating a facade of an existing JavaScript library.

The first annotation is @js.native; this annotation tells the compiler that the implementation is completely done in JavaScript. The second annotation is @JSGlobal("$") ; this is to express the fact that the API we are extending is a JavaScript class, and this class is named $. The last thing is to define the signature of the function that we would like to call and to use js.native as implementation; again, the compiler is going to make the bridge between our code and the JavaScript implementation.

The parameters of the function are String (for the first one) and Options (for the second). Options need to be defined, as this is part of the facade.

By reading the Notify.js documentation (https://notifyjs.jpillora.com/), you can see that there are a lot of options available, such as the positioning of the notification and the animation of the notification.

From the Notify.js documentation, we can get the definitions of all of the options, as follows:

{
  // whether to hide the notification on click
  clickToHide: true,
  // whether to auto-hide the notification
  autoHide: true,
  // if autoHide, hide after milliseconds
  autoHideDelay: 5000,
  // show the arrow pointing at the element
  arrowShow: true,
  // arrow size in pixels
  arrowSize: 5,
  // position defines the notification position though uses the 
defaults below position: '...', // default positions elementPosition: 'bottom left', globalPosition: 'top right', // default style style: 'bootstrap', // default class (string or [string]) className: 'error', // show animation showAnimation: 'slideDown', // show animation duration showDuration: 400, // hide animation hideAnimation: 'slideUp', // hide animation duration hideDuration: 200, // padding between element and notification gap: 2 }

We can create an Options class in Scala, as follows:

@ScalaJSDefined
trait Options extends js.Object {
  // whether to hide the notification on click
  var clickToHide: js.UndefOr[Boolean] = js.undefined
  // whether to auto-hide the notification
  var autoHide: js.UndefOr[Boolean] = js.undefined
  // if autoHide, hide after milliseconds
  var autoHideDelay: js.UndefOr[Int] = js.undefined
  // show the arrow pointing at the element
  var arrowShow: js.UndefOr[Boolean] = js.undefined
  // arrow size in pixels
  var arrowSize: js.UndefOr[Int] = js.undefined
  // position defines the notification position 
// though uses the defaults below var position: js.UndefOr[String] = js.undefined // default positions var elementPosition: js.UndefOr[String] = js.undefined var globalPosition: js.UndefOr[String] = js.undefined // default style var style: js.UndefOr[String] = js.undefined // default class (string or [string]) var className: js.UndefOr[String] = js.undefined // show animation var showAnimation: js.UndefOr[String] = js.undefined // show animation duration var showDuration: js.UndefOr[Int] = js.undefined // hide animation var hideAnimation: js.UndefOr[String] = js.undefined // hide animation duration var hideDuration: js.UndefOr[Int] = js.undefined // padding between element and notification var gap: js.UndefOr[Int] = js.undefined }

The @ScalaJSDefined annotation tells the compiler that this is a type defined in Scala, and not in JavaScript.

Then, for each property, we check the type candidate in the documentation and define it using js.UndefOr[Int]; this type acts like a bridge between the undefinedJavaScript and Options types in Scala.

Everything is now defined for our facade; we can use this facade and implement the missing notify(alarm) function of the UIManager class, as follows:

private def notify(alarm: Alarm): Unit = {
  val notifyClass = if (alarm.action == Add) "info" else "warn"
  NotifyJS.notify(alarm.message, new Options {
    className = notifyClass
    globalPosition = "right bottom"
  })
}

First, we check the type of action to set the class name of the notification, and then we use the notify native call by passing the message and the notification's options.

We are all done. Now, if the server is running, each time you add or remove a product in the cart, a notification will be sent to all of the connected browsers, as shown in the following screenshot:

The shopping page with the notification for cart updates
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset