Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!--
- // ChatPage.html
- //
- // Created by Faye Li on 3 Feb 2017
- // Modified by Don Hopkins (dhopkins@donhopkins.com).
- // Copyright 2017 High Fidelity, Inc.
- //
- // Distributed under the Apache License, Version 2.0.
- // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
- -->
- <html>
- <head>
- <title>Chat</title>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600,700"" rel="stylesheet">
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
- <style>
- input[type=button],
- button {
- font-family: 'Raleway';
- font-weight: bold;
- font-size: 20px;
- vertical-align: top;
- width: 100%;
- height: 40px;
- min-width: 120px;
- padding: 0px 18px;
- margin-top: 5px;
- margin-right: 6px;
- border-radius: 5px;
- border: none;
- color: #fff;
- background-color: #000;
- background: linear-gradient(#343434 20%, #000 100%);
- cursor: pointer;
- }
- .commandButton {
- width: 100px !important;
- }
- input[type=text] {
- font-family: 'Raleway';
- font-weight: bold;
- font-size: 20px;
- vertical-align: top;
- height: 40px;
- color: #000;
- width: 100%;
- background-color: #fff;
- background: linear-gradient(#343434 20%, #fff 100%);
- }
- input[type=button].red {
- color: #fff;
- background-color: #94132e;
- background: linear-gradient(#d42043 20%, #94132e 100%);
- }
- input[type=button].blue {
- color: #fff;
- background-color: #1080b8;
- background: linear-gradient(#00b4ef 20%, #1080b8 100%);
- }
- input[type=button].white {
- color: #121212;
- background-color: #afafaf;
- background: linear-gradient(#fff 20%, #afafaf 100%);
- }
- input[type=button]:enabled:hover {
- background: linear-gradient(#000, #000);
- border: none;
- }
- input[type=button].red:enabled:hover {
- background: linear-gradient(#d42043, #d42043);
- border: none;
- }
- input[type=button].blue:enabled:hover {
- background: linear-gradient(#00b4ef, #00b4ef);
- border: none;
- }
- input[type=button].white:enabled:hover {
- background: linear-gradient(#fff, #fff);
- border: none;
- }
- input[type=button]:active {
- background: linear-gradient(#343434, #343434);
- }
- input[type=button].red:active {
- background: linear-gradient(#94132e, #94132e);
- }
- input[type=button].blue:active {
- background: linear-gradient(#1080b8, #1080b8);
- }
- input[type=button].white:active {
- background: linear-gradient(#afafaf, #afafaf);
- }
- input[type=button]:disabled {
- color: #252525;
- background: linear-gradient(#575757 20%, #252525 100%);
- }
- input[type=button][pressed=pressed] {
- color: #00b4ef;
- }
- body {
- width: 100%;
- overflow-x: hidden;
- overflow-y: hidden;
- margin: 0;
- font-family: 'Raleway', sans-serif;
- color: white;
- background: linear-gradient(#2b2b2b, #0f212e);
- }
- .Content {
- font-size: 20px;
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- }
- .TopBar {
- height: 40px;
- background: linear-gradient(#2b2b2b, #1e1e1e);
- font-weight: bold;
- padding: 10px 10px 10px 10px;
- display: flex;
- align-items: center;
- width: 100%;
- font-size: 28px;
- flex-grow: 0;
- }
- .ChatLog {
- padding: 20px;
- font-size: 20px;
- flex-grow: 1;
- color: white;
- background-color: black;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
- }
- .ChatLogLine {
- margin-bottom: 15px;
- }
- .ChatLogLineDisplayName {
- font-weight: bold;
- }
- .ChatLogLineMessage {
- }
- .LogLogLine {
- margin-bottom: 15px;
- }
- .LogLogLineMessage {
- font-style: italic;
- }
- .ChatInput {
- display: flex;
- flex-direction: row;
- flex-grow: 0;
- }
- .ChatInputText {
- padding: 20px 20px 20px 20px;
- height: 60px !important;
- font-size: 20px !important;
- flex-grow: 1;
- display: flex;
- flex-direction: column;
- }
- .responsive {
- width: 100%;
- max-width: 420px;
- height: auto;
- }
- </style>
- </head>
- <body>
- <div class="Content">
- <div class="TopBar">
- <b>Chat</b>
- </div>
- <div class="ChatLog" id="ChatLog"></div>
- <div class="ChatInput">
- <input type="text" class="ChatInputText" id="ChatInputText" size="256" maxlength="256" />
- </div>
- </div>
- </body>
- <script>
- //linky function
- (function($) {
- "use strict";
- $.fn.linky = function(options) {
- return this.each(function() {
- var $el = $(this),
- linkifiedContent = _linkify($el, options);
- $el.html(linkifiedContent);
- });
- };
- function _linkify($el, options) {
- var links = {
- twitter: {
- baseUrl: "https://twitter.com/",
- hashtagSearchUrl: "hashtag/"
- },
- instagram: {
- baseUrl: "http://instagram.com/",
- hashtagSearchUrl: null // Doesn't look like there is one?
- },
- github: {
- baseUrl: "https://github.com/",
- hashtagSearchUrl: null
- }
- },
- defaultOptions = {
- mentions: false,
- hashtags: false,
- urls: true,
- linkTo: "twitter" // Let's default to Twitter
- },
- extendedOptions = $.extend(defaultOptions, options),
- elContent = $el.html(),
- // Regular expression courtesy of Matthew O'Riordan, see: http://goo.gl/3syEKK
- urlRegEx = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;,:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+,~%\/\.\w\-]*)?\??(?:[\-\+=&;,:%@\.\w]*)#?(?:[\.\!\/\\\w]*))?)/g,
- matches;
- // Linkifying URLs
- if (extendedOptions.urls) {
- matches = elContent.match(urlRegEx);
- if (matches) {
- elContent = _linkifyUrls(matches, $el);
- }
- }
- // Linkifying mentions
- if (extendedOptions.mentions) {
- elContent = _linkifyMentions(elContent, links[extendedOptions.linkTo].baseUrl);
- }
- // Linkifying hashtags
- if (extendedOptions.hashtags) {
- elContent = _linkifyHashtags(elContent, links[extendedOptions.linkTo]);
- }
- return elContent;
- }
- // For any URLs present, unless they are already identified within
- // an `a` element, linkify them.
- function _linkifyUrls(matches, $el) {
- var elContent = $el.html();
- $.each(matches, function() {
- var ext = this.split('.').pop();
- switch(true){
- case ext == "png":
- case ext == "jpg":
- case ext == "gif":
- case ext == "jpeg":
- elContent = elContent.replace(this, "<img src='" + this + "'class=\"responsive\">");
- break;
- case ext == "webm":
- elContent = elContent.replace(this, "<video controls class=\"responsive\"><source src='" + this + "' type='video/" + ext + "'></video>");
- break;
- case !!this.match(/^(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?(?=.*v=((\w|-){11}))(?:\S+)?$/):
- var youtubeMatch = this.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);
- if(youtubeMatch && youtubeMatch[2].length == 11 && this.match(/^(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?(?=.*v=((\w|-){11}))(?:\S+)?$/)){
- elContent = "<iframe width='420' height='236' src='//www.youtube.com/embed/" + youtubeMatch[2] + "' frameborder='0'></iframe>";
- break;
- }
- // else fall through to default
- default:
- elContent = elContent.replace(this, "<a href='" + this + "' target='_blank'>" + this + "</a>");
- break;
- }
- });
- return elContent;
- }
- // Find any mentions (e.g. @andrs) and turn them into links that
- // refer to the appropriate social profile (e.g. twitter or instagram).
- function _linkifyMentions(text, baseUrl) {
- return text.replace(/(^|\s|\(|>)@(\w+)/g, "$1<a href='" + baseUrl + "$2' target='_blank'>@$2</a>");
- }
- // Find any hashtags (e.g. #linkyrocks) and turn them into links that refer
- // to the appropriate social profile.
- function _linkifyHashtags(text, links) {
- // If there is no search URL for a hashtag, there isn't much we can do
- if (links.hashtagSearchUrl === null) return text;
- return text.replace(/(^|\s|\(|>)#((\w|[\u00A1-\uFFFF])+)/g, "$1<a href='" + links.baseUrl + links.hashtagSearchUrl + "$2' target='_blank'>#$2</a>");
- }
- }(jQuery));
- //console.log("ChatPage: loading script...");
- var messageData = {}; // The data that is sent along with the message.
- var typing = false; // True while the user is typing.
- var typingTimerDuration = 1; // How long to wait before ending typing, in seconds.
- var typingTimer = null; // The timer to end typing.
- var $ChatLog; // The scrolling chat log.
- var $ChatInputText; // The text field for entering text.
- // Recreate the lines in chatLog as the DOM in $ChatLog.
- function updateChatLog() {
- $ChatLog.html('');
- for (var i = 0, n = chatLog.length; i < n; i++) {
- var a = chatLog[i];
- var avatarID = a[0];
- var displayName = a[1];
- var message = a[2];
- var data = a[3];
- //console.log("updateChatLog", i, a, displayName, message);
- if (avatarID) {
- receiveChatMessage(avatarID, displayName, message, data);
- } else {
- logMessage(message);
- }
- }
- }
- // Call this no every keystroke.
- function type() {
- beginTyping();
- handleType();
- }
- // Reset the typing timer, and notify if we're starting.
- function beginTyping() {
- if (typingTimer) {
- clearTimeout(typingTimer);
- }
- typingTimer = setTimeout(function() {
- typing = false;
- handleEndTyping();
- }, typingTimerDuration * 1000);
- if (typing) {
- return;
- }
- typing = true;
- handleBeginTyping();
- }
- // Clear the typing timer and notify if we're finished.
- function endTyping() {
- if (typingTimer) {
- clearTimeout(typingTimer);
- typingTimer = null;
- }
- if (!typing) {
- return;
- }
- typing = false;
- handleEndTyping();
- }
- // Notify the interface script on every keystroke.
- function handleType() {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "Type"
- }));
- }
- // Notify the interface script when we begin typing.
- function handleBeginTyping() {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "BeginTyping"
- }));
- }
- // Notify the interface script when we end typing.
- function handleEndTyping() {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "EndTyping"
- }));
- }
- // Append a chat message to $ChatLog.
- function receiveChatMessage(avatarID, displayName, message, data) {
- var $logLine =
- $('<div/>')
- .addClass('ChatLogLine')
- .data('chat-avatarID', avatarID)
- .data('chat-displayName', displayName)
- .data('chat-message', message)
- .data('chat-data', data)
- .appendTo($ChatLog);
- var $logLineDisplayName =
- $('<span/>')
- .addClass('ChatLogLineDisplayName')
- .text(displayName + ': ')
- .on('mouseenter', function(event) {
- identifyAvatar(avatarID);
- //event.cancelBubble();
- $logLineDisplayName.css({
- color: '#00ff00',
- 'text-decoration': 'underline'
- });
- })
- .on('mouseleave', function(event) {
- unidentifyAvatar(avatarID);
- //event.cancelBubble();
- $logLineDisplayName.css({
- color: 'white',
- 'text-decoration': 'none'
- });
- })
- .click(function(event) {
- faceAvatar(avatarID, displayName);
- //event.cancelBubble();
- })
- .appendTo($logLine);
- var $logLineMessage =
- $('<span/>')
- .addClass('ChatLogLineMessage')
- .text(message).linky()
- .appendTo($logLine);
- }
- // Append a log message to $ChatLog.
- function logMessage(message) {
- var $logLine =
- $('<div/>')
- .addClass('LogLogLine')
- .data('chat-message', message)
- .appendTo($ChatLog);
- var $logLineMessage =
- $('<span/>')
- .addClass('LogLogLineMessage')
- .text(message)
- .appendTo($logLine);
- }
- // Scroll $ChatLog so the last line is visible.
- function scrollChatLog() {
- var $logLine = $ChatLog.children().last();
- if (!$logLine || !$logLine.length) {
- return;
- }
- var chatLogHeight = $ChatLog.outerHeight(true);
- var logLineTop = ($logLine.offset().top - $ChatLog.offset().top);
- var logLineBottom = logLineTop + $logLine.outerHeight(true);
- var scrollUp = logLineBottom - chatLogHeight;
- if (scrollUp > 0) {
- $ChatLog.scrollTop($ChatLog.scrollTop() + scrollUp);
- }
- }
- // Tell the interface script we have initialized.
- function emitReadyEvent() {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "Ready"
- }));
- }
- // The user entered an empty chat message.
- function emptyChatMessage() {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "EmptyChatMessage",
- data: null
- }));
- }
- // The user entered a non-empty chat message.
- function handleChatMessage(message, data) {
- //console.log("handleChatMessage", message);
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "HandleChatMessage",
- message: message,
- data: data
- }));
- }
- // Clear the chat log, of course.
- function clearChatLog() {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "ClearChatLog"
- }));
- }
- // Identify an avatar.
- function identifyAvatar(avatarID) {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "IdentifyAvatar",
- avatarID: avatarID
- }));
- }
- // Stop identifying an avatar.
- function unidentifyAvatar(avatarID) {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "UnidentifyAvatar",
- avatarID: avatarID
- }));
- }
- // Face an avatar.
- function faceAvatar(avatarID, displayName) {
- EventBridge.emitWebEvent(
- JSON.stringify({
- type: "FaceAvatar",
- avatarID: avatarID,
- displayName: displayName
- }));
- }
- // Let's get this show on the road!
- function main() {
- //console.log("ChatPage: main");
- $ChatLog = $('#ChatLog');
- $ChatInputText = $('#ChatInputText');
- // Whenever the chat log resizes, or the input text gets or loses focus,
- // scroll the chat log to the last line.
- $ChatLog.on('resize', function(event) {
- //console.log("ChatLog resize", $ChatLog, event);
- scrollChatLog();
- });
- $ChatInputText.on('focus blur', function(event) {
- //console.log("ChatInputText focus blur", $ChatInputText, event);
- scrollChatLog();
- });
- // Track when the user is typing, and handle the message when the user hits return.
- $ChatInputText.on('keydown', function(event) {
- type();
- if (event.keyCode == 13) {
- var message = $ChatInputText.val().substr(0, 256);
- $ChatInputText.val('');
- if (message == '') {
- emptyChatMessage();
- } else {
- handleChatMessage(message, messageData);
- }
- endTyping();
- }
- });
- // Start out with the input text in focus.
- $ChatInputText.focus();
- // Hook up a handler for events that come from hifi.
- EventBridge.scriptEventReceived.connect(function (message) {
- //console.log("ChatPage: main: scriptEventReceived", message);
- var messageData = JSON.parse(message);
- var messageType = messageData['type'];
- switch (messageType) {
- case "Update":
- chatLog = messageData['chatLog'];
- updateChatLog();
- scrollChatLog();
- break;
- case "ReceiveChatMessage":
- receiveChatMessage(messageData['avatarID'], messageData['displayName'], messageData['message'], message['data']);
- scrollChatLog();
- break;
- case "LogMessage":
- logMessage(messageData['message']);
- scrollChatLog();
- break;
- default:
- console.log("WEB: received unexpected script event message: " + message);
- break;
- }
- });
- emitReadyEvent();
- }
- // Start up once the document is loaded.
- $(document).ready(main);
- </script>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement