Advertisement
salahzar

chat.html

Aug 13th, 2018
533
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 21.01 KB | None | 0 0
  1.  
  2. <!--
  3. //  ChatPage.html
  4. //
  5. //  Created by Faye Li on 3 Feb 2017
  6. //  Modified by Don Hopkins (dhopkins@donhopkins.com).
  7. //  Copyright 2017 High Fidelity, Inc.
  8. //
  9. //  Distributed under the Apache License, Version 2.0.
  10. //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
  11. -->
  12. <html>
  13.     <head>
  14.         <title>Chat</title>
  15.         <meta charset="utf-8">
  16.         <meta name="viewport" content="width=device-width, initial-scale=1">
  17.         <link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600,700"" rel="stylesheet">
  18.         <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  19.  
  20.         <style>
  21.             input[type=button],
  22.             button {
  23.                 font-family: 'Raleway';
  24.                 font-weight: bold;
  25.                 font-size: 20px;
  26.                 vertical-align: top;
  27.                 width: 100%;
  28.                 height: 40px;
  29.                 min-width: 120px;
  30.                 padding: 0px 18px;
  31.                 margin-top: 5px;
  32.                 margin-right: 6px;
  33.                 border-radius: 5px;
  34.                 border: none;
  35.                 color: #fff;
  36.                 background-color: #000;
  37.                 background: linear-gradient(#343434 20%, #000 100%);
  38.                 cursor: pointer;
  39.             }
  40.  
  41.             .commandButton {
  42.                 width: 100px !important;
  43.             }
  44.  
  45.             input[type=text] {
  46.                 font-family: 'Raleway';
  47.                 font-weight: bold;
  48.                 font-size: 20px;
  49.                 vertical-align: top;
  50.                 height: 40px;
  51.                 color: #000;
  52.                 width: 100%;
  53.                 background-color: #fff;
  54.                 background: linear-gradient(#343434 20%, #fff 100%);
  55.             }
  56.  
  57.             input[type=button].red {
  58.                 color: #fff;
  59.                 background-color: #94132e;
  60.                 background: linear-gradient(#d42043 20%, #94132e 100%);
  61.             }
  62.             input[type=button].blue {
  63.                 color: #fff;
  64.                 background-color: #1080b8;
  65.                 background: linear-gradient(#00b4ef 20%, #1080b8 100%);
  66.             }
  67.             input[type=button].white {
  68.                 color: #121212;
  69.                 background-color: #afafaf;
  70.                 background: linear-gradient(#fff 20%, #afafaf 100%);
  71.             }
  72.  
  73.             input[type=button]:enabled:hover {
  74.                 background: linear-gradient(#000, #000);
  75.                 border: none;
  76.             }
  77.             input[type=button].red:enabled:hover {
  78.                 background: linear-gradient(#d42043, #d42043);
  79.                 border: none;
  80.             }
  81.             input[type=button].blue:enabled:hover {
  82.                 background: linear-gradient(#00b4ef, #00b4ef);
  83.                 border: none;
  84.             }
  85.             input[type=button].white:enabled:hover {
  86.                 background: linear-gradient(#fff, #fff);
  87.                 border: none;
  88.             }
  89.  
  90.             input[type=button]:active {
  91.                 background: linear-gradient(#343434, #343434);
  92.             }
  93.             input[type=button].red:active {
  94.                 background: linear-gradient(#94132e, #94132e);
  95.             }
  96.             input[type=button].blue:active {
  97.                 background: linear-gradient(#1080b8, #1080b8);
  98.             }
  99.             input[type=button].white:active {
  100.                 background: linear-gradient(#afafaf, #afafaf);
  101.             }
  102.  
  103.             input[type=button]:disabled {
  104.                 color: #252525;
  105.                 background: linear-gradient(#575757 20%, #252525 100%);
  106.             }
  107.  
  108.             input[type=button][pressed=pressed] {
  109.                 color: #00b4ef;
  110.             }
  111.  
  112.             body {
  113.                 width: 100%;
  114.                 overflow-x: hidden;
  115.                 overflow-y: hidden;
  116.                 margin: 0;
  117.                 font-family: 'Raleway', sans-serif;
  118.                 color: white;
  119.                 background: linear-gradient(#2b2b2b, #0f212e);
  120.             }
  121.  
  122.             .Content {
  123.                 font-size: 20px;
  124.                 width: 100%;
  125.                 height: 100%;
  126.                 display: flex;
  127.                 flex-direction: column;
  128.             }
  129.  
  130.             .TopBar {
  131.                 height: 40px;
  132.                 background: linear-gradient(#2b2b2b, #1e1e1e);
  133.                 font-weight: bold;
  134.                 padding: 10px 10px 10px 10px;
  135.                 display: flex;
  136.                 align-items: center;
  137.                 width: 100%;
  138.                 font-size: 28px;
  139.                 flex-grow: 0;
  140.             }
  141.  
  142.             .ChatLog {
  143.                 padding: 20px;
  144.                 font-size: 20px;
  145.                 flex-grow: 1;
  146.                 color: white;
  147.                 background-color: black;
  148.                 overflow-x: hidden;
  149.                 overflow-y: scroll;
  150.                 word-wrap: break-word;
  151.             }
  152.  
  153.             .ChatLogLine {
  154.                 margin-bottom: 15px;
  155.             }
  156.  
  157.             .ChatLogLineDisplayName {
  158.                 font-weight: bold;
  159.             }
  160.  
  161.             .ChatLogLineMessage {
  162.             }
  163.  
  164.             .LogLogLine {
  165.                 margin-bottom: 15px;
  166.             }
  167.  
  168.             .LogLogLineMessage {
  169.                 font-style: italic;
  170.             }
  171.  
  172.             .ChatInput {
  173.                 display: flex;
  174.                 flex-direction: row;
  175.                 flex-grow: 0;
  176.             }
  177.  
  178.             .ChatInputText {
  179.                 padding: 20px 20px 20px 20px;
  180.                 height: 60px !important;
  181.                 font-size: 20px !important;
  182.                 flex-grow: 1;
  183.                 display: flex;
  184.                 flex-direction: column;
  185.             }
  186.             .responsive {
  187.                 width: 100%;
  188.                 max-width: 420px;
  189.                 height: auto;
  190.             }
  191.  
  192.         </style>
  193.     </head>
  194.     <body>
  195.  
  196.         <div class="Content">
  197.  
  198.             <div class="TopBar">
  199.                 <b>Chat</b>
  200.             </div>
  201.  
  202.             <div class="ChatLog" id="ChatLog"></div>
  203.  
  204.             <div class="ChatInput">
  205.               <input type="text" class="ChatInputText" id="ChatInputText" size="256" maxlength="256" />
  206.             </div>
  207.  
  208.         </div>
  209.  
  210.     </body>
  211.  
  212.     <script>
  213. //linky function
  214.  
  215. (function($) {
  216.  
  217.     "use strict";
  218.  
  219.     $.fn.linky = function(options) {
  220.         return this.each(function() {
  221.             var $el = $(this),
  222.                 linkifiedContent = _linkify($el, options);
  223.  
  224.             $el.html(linkifiedContent);
  225.         });
  226.     };
  227.  
  228.     function _linkify($el, options) {
  229.         var links = {
  230.                 twitter: {
  231.                     baseUrl: "https://twitter.com/",
  232.                     hashtagSearchUrl: "hashtag/"
  233.                 },
  234.                 instagram: {
  235.                     baseUrl: "http://instagram.com/",
  236.                     hashtagSearchUrl: null // Doesn't look like there is one?
  237.                 },
  238.                 github: {
  239.                     baseUrl: "https://github.com/",
  240.                     hashtagSearchUrl: null
  241.                 }
  242.             },
  243.             defaultOptions = {
  244.                 mentions: false,
  245.                 hashtags: false,
  246.                 urls: true,
  247.                 linkTo: "twitter" // Let's default to Twitter
  248.             },
  249.             extendedOptions = $.extend(defaultOptions, options),
  250.             elContent = $el.html(),
  251.             // Regular expression courtesy of Matthew O'Riordan, see: http://goo.gl/3syEKK
  252.             urlRegEx = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;,:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+,~%\/\.\w\-]*)?\??(?:[\-\+=&;,:%@\.\w]*)#?(?:[\.\!\/\\\w]*))?)/g,
  253.             matches;
  254.  
  255.             // Linkifying URLs
  256.             if (extendedOptions.urls) {
  257.                 matches = elContent.match(urlRegEx);
  258.                 if (matches) {
  259.                     elContent = _linkifyUrls(matches, $el);
  260.                 }
  261.             }
  262.  
  263.             // Linkifying mentions
  264.             if (extendedOptions.mentions) {
  265.                 elContent = _linkifyMentions(elContent, links[extendedOptions.linkTo].baseUrl);
  266.             }
  267.  
  268.             // Linkifying hashtags
  269.             if (extendedOptions.hashtags) {
  270.                 elContent = _linkifyHashtags(elContent, links[extendedOptions.linkTo]);
  271.             }
  272.  
  273.         return elContent;
  274.     }
  275.  
  276.     // For any URLs present, unless they are already identified within
  277.     // an `a` element, linkify them.
  278.     function _linkifyUrls(matches, $el) {
  279.         var elContent = $el.html();
  280.  
  281.         $.each(matches, function() {
  282.        
  283.             var ext = this.split('.').pop();
  284.            
  285.             switch(true){
  286.             case ext == "png":
  287.             case ext == "jpg":
  288.             case ext == "gif":
  289.             case ext == "jpeg":
  290.                 elContent = elContent.replace(this, "<img src='" + this + "'class=\"responsive\">");
  291.                 break;
  292.             case ext == "webm":
  293.                 elContent = elContent.replace(this, "<video controls class=\"responsive\"><source src='" + this + "' type='video/" + ext + "'></video>");
  294.                 break;
  295.             case !!this.match(/^(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?(?=.*v=((\w|-){11}))(?:\S+)?$/):
  296.                 var youtubeMatch = this.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);
  297.                 if(youtubeMatch && youtubeMatch[2].length == 11 && this.match(/^(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?(?=.*v=((\w|-){11}))(?:\S+)?$/)){
  298.                     elContent = "<iframe width='420' height='236' src='//www.youtube.com/embed/" + youtubeMatch[2] + "' frameborder='0'></iframe>";
  299.                     break;
  300.                 }
  301.                 // else fall through to default
  302.             default:
  303.                     elContent = elContent.replace(this, "<a href='" + this + "' target='_blank'>" + this + "</a>");
  304.                 break;
  305.             }
  306.  
  307.         });
  308.         return elContent;
  309.     }
  310.  
  311.     // Find any mentions (e.g. @andrs) and turn them into links that
  312.     // refer to the appropriate social profile (e.g. twitter or instagram).
  313.     function _linkifyMentions(text, baseUrl) {
  314.         return text.replace(/(^|\s|\(|>)@(\w+)/g, "$1<a href='" + baseUrl + "$2' target='_blank'>@$2</a>");
  315.     }
  316.  
  317.     // Find any hashtags (e.g. #linkyrocks) and turn them into links that refer
  318.     // to the appropriate social profile.
  319.     function _linkifyHashtags(text, links) {
  320.         // If there is no search URL for a hashtag, there isn't much we can do
  321.         if (links.hashtagSearchUrl === null) return text;
  322.         return text.replace(/(^|\s|\(|>)#((\w|[\u00A1-\uFFFF])+)/g, "$1<a href='" + links.baseUrl + links.hashtagSearchUrl + "$2' target='_blank'>#$2</a>");
  323.     }
  324.  
  325. }(jQuery));
  326.  
  327.         //console.log("ChatPage: loading script...");
  328.  
  329.         var messageData = {}; // The data that is sent along with the message.
  330.         var typing = false; // True while the user is typing.
  331.         var typingTimerDuration = 1; // How long to wait before ending typing, in seconds.
  332.         var typingTimer = null; // The timer to end typing.
  333.         var $ChatLog; // The scrolling chat log.
  334.         var $ChatInputText; // The text field for entering text.
  335.  
  336.         // Recreate the lines in chatLog as the DOM in $ChatLog.
  337.         function updateChatLog() {
  338.             $ChatLog.html('');
  339.             for (var i = 0, n = chatLog.length; i < n; i++) {
  340.                var a = chatLog[i];
  341.                var avatarID = a[0];
  342.                var displayName = a[1];
  343.                var message = a[2];
  344.                var data = a[3];
  345.                //console.log("updateChatLog", i, a, displayName, message);
  346.                if (avatarID) {
  347.                    receiveChatMessage(avatarID, displayName, message, data);
  348.                } else {
  349.                    logMessage(message);
  350.                }
  351.            }
  352.        }
  353.  
  354.        // Call this no every keystroke.
  355.        function type() {
  356.            beginTyping();
  357.            handleType();
  358.        }
  359.  
  360.        // Reset the typing timer, and notify if we're starting.
  361.        function beginTyping() {
  362.            if (typingTimer) {
  363.                clearTimeout(typingTimer);
  364.            }
  365.            typingTimer = setTimeout(function() {
  366.                typing = false;
  367.                handleEndTyping();
  368.            }, typingTimerDuration * 1000);
  369.            if (typing) {
  370.                return;
  371.            }
  372.            typing = true;
  373.            handleBeginTyping();
  374.        }
  375.        // Clear the typing timer and notify if we're finished.
  376.        function endTyping() {
  377.            if (typingTimer) {
  378.                clearTimeout(typingTimer);
  379.                typingTimer = null;
  380.            }
  381.  
  382.            if (!typing) {
  383.                return;
  384.            }
  385.  
  386.            typing = false;
  387.            handleEndTyping();
  388.        }
  389.  
  390.        // Notify the interface script on every keystroke.
  391.        function handleType() {
  392.            EventBridge.emitWebEvent(
  393.                JSON.stringify({
  394.                    type: "Type"
  395.                }));
  396.        }
  397.  
  398.        // Notify the interface script when we begin typing.
  399.        function handleBeginTyping() {
  400.            EventBridge.emitWebEvent(
  401.                JSON.stringify({
  402.                    type: "BeginTyping"
  403.                }));
  404.        }
  405.  
  406.        // Notify the interface script when we end typing.
  407.        function handleEndTyping() {
  408.            EventBridge.emitWebEvent(
  409.                JSON.stringify({
  410.                    type: "EndTyping"
  411.                }));
  412.        }
  413.  
  414.        // Append a chat message to $ChatLog.
  415.        function receiveChatMessage(avatarID, displayName, message, data) {
  416.            var $logLine =
  417.                $('<div/>')
  418.                     .addClass('ChatLogLine')
  419.                     .data('chat-avatarID', avatarID)
  420.                     .data('chat-displayName', displayName)
  421.                     .data('chat-message', message)
  422.                     .data('chat-data', data)
  423.                     .appendTo($ChatLog);
  424.            
  425.             var $logLineDisplayName =
  426.                 $('<span/>')
  427.                     .addClass('ChatLogLineDisplayName')
  428.                     .text(displayName + ': ')
  429.                     .on('mouseenter', function(event) {
  430.                         identifyAvatar(avatarID);
  431.                         //event.cancelBubble();
  432.                         $logLineDisplayName.css({
  433.                             color: '#00ff00',
  434.                             'text-decoration': 'underline'
  435.                         });
  436.                     })
  437.                     .on('mouseleave', function(event) {
  438.                         unidentifyAvatar(avatarID);
  439.                         //event.cancelBubble();
  440.                         $logLineDisplayName.css({
  441.                             color: 'white',
  442.                             'text-decoration': 'none'
  443.                         });
  444.                     })
  445.                     .click(function(event) {
  446.                         faceAvatar(avatarID, displayName);
  447.                         //event.cancelBubble();
  448.                     })
  449.                     .appendTo($logLine);
  450.             var $logLineMessage =
  451.                 $('<span/>')
  452.                     .addClass('ChatLogLineMessage')
  453.                     .text(message).linky()
  454.                     .appendTo($logLine);
  455.         }
  456.  
  457.         // Append a log message to $ChatLog.
  458.         function logMessage(message) {
  459.             var $logLine =
  460.                 $('<div/>')
  461.                     .addClass('LogLogLine')
  462.                     .data('chat-message', message)
  463.                     .appendTo($ChatLog);
  464.             var $logLineMessage =
  465.                 $('<span/>')
  466.                     .addClass('LogLogLineMessage')
  467.                     .text(message)
  468.                     .appendTo($logLine);
  469.         }
  470.  
  471.         // Scroll $ChatLog so the last line is visible.
  472.         function scrollChatLog() {
  473.             var $logLine = $ChatLog.children().last();
  474.             if (!$logLine || !$logLine.length) {
  475.                 return;
  476.             }
  477.             var chatLogHeight = $ChatLog.outerHeight(true);
  478.             var logLineTop = ($logLine.offset().top - $ChatLog.offset().top);
  479.             var logLineBottom = logLineTop + $logLine.outerHeight(true);
  480.             var scrollUp = logLineBottom - chatLogHeight;
  481.             if (scrollUp > 0) {
  482.                 $ChatLog.scrollTop($ChatLog.scrollTop() + scrollUp);
  483.             }
  484.         }
  485.  
  486.         // Tell the interface script we have initialized.
  487.         function emitReadyEvent() {
  488.             EventBridge.emitWebEvent(
  489.                 JSON.stringify({
  490.                     type: "Ready"
  491.                 }));
  492.         }
  493.  
  494.         // The user entered an empty chat message.
  495.         function emptyChatMessage() {
  496.             EventBridge.emitWebEvent(
  497.                 JSON.stringify({
  498.                     type: "EmptyChatMessage",
  499.                     data: null
  500.                 }));
  501.         }
  502.  
  503.         // The user entered a non-empty chat message.
  504.         function handleChatMessage(message, data) {
  505.             //console.log("handleChatMessage", message);
  506.             EventBridge.emitWebEvent(
  507.                 JSON.stringify({
  508.                     type: "HandleChatMessage",
  509.                     message: message,
  510.                     data: data
  511.                 }));
  512.         }
  513.  
  514.         // Clear the chat log, of course.
  515.         function clearChatLog() {
  516.             EventBridge.emitWebEvent(
  517.                 JSON.stringify({
  518.                     type: "ClearChatLog"
  519.                 }));
  520.         }
  521.  
  522.         // Identify an avatar.
  523.         function identifyAvatar(avatarID) {
  524.             EventBridge.emitWebEvent(
  525.                 JSON.stringify({
  526.                     type: "IdentifyAvatar",
  527.                     avatarID: avatarID
  528.                 }));
  529.         }
  530.  
  531.         // Stop identifying an avatar.
  532.         function unidentifyAvatar(avatarID) {
  533.             EventBridge.emitWebEvent(
  534.                 JSON.stringify({
  535.                     type: "UnidentifyAvatar",
  536.                     avatarID: avatarID
  537.                 }));
  538.         }
  539.  
  540.         // Face an avatar.
  541.         function faceAvatar(avatarID, displayName) {
  542.             EventBridge.emitWebEvent(
  543.                 JSON.stringify({
  544.                     type: "FaceAvatar",
  545.                     avatarID: avatarID,
  546.                     displayName: displayName
  547.                 }));
  548.         }
  549.  
  550.         // Let's get this show on the road!
  551.         function main() {
  552.  
  553.             //console.log("ChatPage: main");
  554.  
  555.             $ChatLog = $('#ChatLog');
  556.             $ChatInputText = $('#ChatInputText');
  557.  
  558.             // Whenever the chat log resizes, or the input text gets or loses focus,
  559.             // scroll the chat log to the last line.
  560.             $ChatLog.on('resize', function(event) {
  561.                 //console.log("ChatLog resize", $ChatLog, event);
  562.                 scrollChatLog();
  563.             });
  564.             $ChatInputText.on('focus blur', function(event) {
  565.                 //console.log("ChatInputText focus blur", $ChatInputText, event);
  566.                 scrollChatLog();
  567.             });
  568.  
  569.             // Track when the user is typing, and handle the message when the user hits return.
  570.             $ChatInputText.on('keydown', function(event) {
  571.                 type();
  572.                 if (event.keyCode == 13) {
  573.                     var message = $ChatInputText.val().substr(0, 256);
  574.                     $ChatInputText.val('');
  575.                     if (message == '') {
  576.                         emptyChatMessage();
  577.                     } else {
  578.                         handleChatMessage(message, messageData);
  579.                     }
  580.                     endTyping();
  581.                 }
  582.             });
  583.  
  584.             // Start out with the input text in focus.
  585.             $ChatInputText.focus();
  586.  
  587.             // Hook up a handler for events that come from hifi.
  588.             EventBridge.scriptEventReceived.connect(function (message) {
  589.  
  590.                 //console.log("ChatPage: main: scriptEventReceived", message);
  591.  
  592.                 var messageData = JSON.parse(message);
  593.                 var messageType = messageData['type'];
  594.  
  595.                 switch (messageType) {
  596.  
  597.                     case "Update":
  598.                         chatLog = messageData['chatLog'];
  599.                         updateChatLog();
  600.                         scrollChatLog();
  601.                         break;
  602.  
  603.                     case "ReceiveChatMessage":
  604.                         receiveChatMessage(messageData['avatarID'], messageData['displayName'], messageData['message'], message['data']);
  605.                         scrollChatLog();
  606.                         break;
  607.  
  608.                     case "LogMessage":
  609.                         logMessage(messageData['message']);
  610.                         scrollChatLog();
  611.                         break;
  612.  
  613.                     default:
  614.                         console.log("WEB: received unexpected script event message: " + message);
  615.                         break;
  616.  
  617.                 }
  618.             });
  619.  
  620.             emitReadyEvent();
  621.         }
  622.  
  623.         // Start up once the document is loaded.
  624.         $(document).ready(main);
  625.  
  626.     </script>
  627.  
  628. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement