All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hyperscala.examples.ui.ChatExample.scala Maven / Gradle / Ivy

package org.hyperscala.examples.ui

import org.hyperscala.examples.Example
import org.hyperscala.html._
import org.hyperscala.jquery.dsl._
import org.hyperscala.realtime.{Realtime, RealtimeEvent}
import org.hyperscala.ui.dynamic.{DynamicContent, DynamicTag, DynamicTagged}
import org.hyperscala.web._
import org.powerscala.Unique
import org.powerscala.property.Property

import scala.annotation.tailrec
import scala.language.reflectiveCalls

/**
 * @author Matt Hicks 
 */
class ChatExample extends Webpage with Example {
  require(Realtime)

  body.contents += new tag.P {
    contents += "Simple real-time chat example with basic user management and history."
  }

  val nickname = new Property[String]

  val chatMain = DynamicContent.url(ChatExample.Main, null)

  val chatName = chatMain.load[tag.Input]("chatName")
  val message = chatMain.load[tag.TextArea]("chatMessage")
  message.autoFocus := true
  val submit = chatMain.load[tag.Button]("submit")
  val messages = chatMain.load[tag.Div]("messages")

  chatName.changeEvent := RealtimeEvent()
  message.changeEvent := RealtimeEvent()
  submit.clickEvent := RealtimeEvent()

  chatName.changeEvent.on {
    case evt => updateNickname()
  }
  submit.clickEvent.on {
    case evt => sendMessage()
  }

  body.contents += chatMain

  ChatExample.chatHistory.foreach {   // Load history
    case (nick, text) => messages.contents += new ChatEntry(nick, text)
  }

  connected[Website] {
    case website => updateNickname()
  }

  def sendMessage() = {
    if (message.value() != null && message.value().nonEmpty) {
      ChatExample.sendMessage(this.website, nickname(), message.value())
    }
    message.value := ""
    eval($(message).focus())
  }

  def updateNickname() = {
    val website = this.website
    val sessionNickname = website.session.getOrElse[String]("chatNickname", null)
    val current = chatName.value() match {
      case "" | null => website.session.getOrElse[String]("chatNickname", "guest")
      case v => v
    }
    if (current != nickname() && current != sessionNickname) {
      nickname := ChatExample.generateNick(website, current)
    } else {
      nickname := current
    }
    chatName.value := nickname()
    website.session("chatNickname") = nickname()
  }
}

object ChatExample {
  val Main = getClass.getClassLoader.getResource("chat.html")
  val Entry = getClass.getClassLoader.getResource("chat_entry.html")

  private var history = List.empty[(String, String)]

  def instances(website: Website) = website.pages.byType[ChatExample].toList

  @tailrec
  def generateNick(website: Website, nickname: String, increment: Int = 0): String = {
    val nick = increment match {
      case 0 => nickname
      case _ => s"$nickname$increment"
    }
    if (!instances(website).exists(c => c.nickname() == nick)) {
      nick
    } else {
      generateNick(website, nickname, increment + 1)
    }
  }
  def sendMessage(website: Website, nickname: String, message: String) = synchronized {
    instances(website).foreach {
      case chat => chat.messages.contents.insert(0, new ChatEntry(nickname, message))
    }
    history = ((nickname, message) :: history).take(20)
  }
  def chatHistory = history
}

class ChatEntry(name: String, message: String) extends tag.Div with DynamicTagged[tag.Div] {
  def dynamicTag = DynamicTag.url("chat_entry.html", ChatExample.Entry)

  val chatName = getById[tag.Div]("chatName")
  val chatBody = getById[tag.Div]("chatBody")

  chatName.id := Unique()
  chatBody.id := Unique()

  chatName.contents.replaceWith(name)
  chatBody.contents.replaceWith(message)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy