/** * @return {Element!} **/ function createTypingDisplay() { var dom = document.createElement("span") ,dot1 = document.createElement("span") ,dot2 = document.createElement("span") ,dot3 = document.createElement("span"); dom.className = R.klass.typing.container; dot1.className = R.klass.typing.dot1; dot2.className = R.klass.typing.dot2; dot3.className = R.klass.typing.dot3; dot1.textContent = dot2.textContent = dot3.textContent = '.'; dom.appendChild(dot1); dom.appendChild(dot2); dom.appendChild(dot3); return dom; } /** * @param {Room} chan * @return {Element} **/ function createChanListItem(chan) { var dom = document.createElement("li") ,link = document.createElement("a"); dom.id = "room_" +chan.id; link.href = '#' +chan.id; if (chan.isPrivate) { dom.className = R.klass.chatList.entry + " " +R.klass.chatList.typePrivate; dom.dataset["count"] = Object.keys((chan.users) || {}).length; } else { dom.className = R.klass.chatList.entry + " " +R.klass.chatList.typeChannel; } if (SELECTED_ROOM === chan) dom.classList.add(R.klass.selected); link.textContent = chan.name; dom.appendChild(createTypingDisplay()); dom.appendChild(link); if (chan.lastMsg > chan.lastRead) { dom.classList.add(R.klass.unread); if (HIGHLIGHTED_CHANS.indexOf(chan) >= 0) dom.classList.add(R.klass.unreadHi); } return dom; } /** @type {function(string):Element} */ var createChanListHeader = (function() { var cache = {}; return function(title) { var dom = cache[title]; if (!dom) { dom = cache[title] = document.createElement("header"); dom.textContent = title; } return dom; }; })(); /** * @param {PrivateMessageRoom} ims * @return {Element} **/ function createImsListItem(ims) { var dom = document.createElement("li") ,link = document.createElement("a"); dom.id = "room_" +ims.id; link.href = '#' +ims.id; dom.className = R.klass.chatList.entry + " " +R.klass.chatList.typeDirect; link.textContent = ims.user.name; dom.appendChild(createTypingDisplay()); dom.appendChild(link); if (!ims.user.presence) dom.classList.add(R.klass.presenceAway); if (SELECTED_ROOM === ims) dom.classList.add(R.klass.selected); if (ims.lastMsg > ims.lastRead) { dom.classList.add(R.klass.unread); dom.classList.add(R.klass.unreadHi); // Always HI on private message } return dom; } /** * @param {string} chanId * @param {string} msgId * @param {string} reaction * @param {Array.} users * @return {Element|null} **/ function createReactionDom(chanId, msgId, reaction, users) { var emojiDom = makeEmojiDom(reaction); if (emojiDom) { var dom = document.createElement("li") ,a = document.createElement("a") ,emojiContainer = document.createElement("span") ,userList = document.createElement("span") ,userNames = []; for (var i =0, nbUser = users.length; i < nbUser; i++) { var user = DATA.context.getUser(users[i]); if (user) userNames.push(user.name); } userNames.sort(); userList.textContent = userNames.join(", "); emojiContainer.appendChild(emojiDom); emojiContainer.className = R.klass.emoji.small; a.href = "javascript:toggleReaction('" +chanId +"', '" +msgId +"', '" +reaction +"')"; a.appendChild(emojiContainer); a.appendChild(userList); dom.className = R.klass.msg.reactions.item; dom.appendChild(a); return dom; } else { console.warn("Reaction id not found: " +reaction); } return null; } /** * @param {UiMessage|UiMeMessage|UiNoticeMessage} msg * @param {boolean=} skipAttachment * @return {Element} **/ function doCreateMessageDom(msg, skipAttachment) { var channelId = msg.channelId; var dom = document.createElement("div") ,msgBlock = document.createElement("div") ,hover = document.createElement("ul") ,hoverReply = document.createElement("li") dom.attachments = document.createElement("ul"); dom.reactions = document.createElement("ul"); dom.ts = document.createElement("div"); dom.textDom = document.createElement("div"); dom.authorName = document.createElement("span"); dom.id = channelId +"_" +msg.id; dom.className = R.klass.msg.item; dom.ts.className = R.klass.msg.ts; dom.textDom.className = R.klass.msg.msg; dom.authorName.className = R.klass.msg.authorname; hover.className = R.klass.msg.hover.container; hoverReply.className = R.klass.msg.hover.reply; hover.appendChild(hoverReply); if ('makeEmoji' in window) { var hoverReaction = document.createElement("li") ,domReply = window['makeEmoji']("arrow_heading_down") ,domReaction = window['makeEmoji']("smile") ,domEdit = window['makeEmoji']("pencil2") ,domRemove = window['makeEmoji']("x"); hoverReaction.className = R.klass.msg.hover.reaction; if (domReaction) { hoverReaction.classList.add(R.klass.emoji.small); hoverReaction.appendChild(domReaction); } else { hoverReaction.style.backgroundImage = 'url("smile.svg")'; } if (domReply) { hoverReply.classList.add(R.klass.emoji.small); hoverReply.appendChild(domReply); } else { hoverReply.style.backgroundImage = 'url("repl.svg")'; } hover.appendChild(hoverReaction); if (DATA.context.isMe(msg.userId)) { var hoverEdit = document.createElement("li"); hoverEdit.className = R.klass.msg.hover.edit; if (domEdit) hoverEdit.classList.add(R.klass.emoji.small); else hoverEdit.style.backgroundImage = 'url("edit.svg")'; hoverEdit.appendChild(domEdit); hover.appendChild(hoverEdit); var hoverRemove = document.createElement("li"); hoverRemove.className = R.klass.msg.hover.remove; if (domRemove) hoverRemove.classList.add(R.klass.emoji.small); else hoverRemove.style.backgroundImage = 'url("remove.svg")'; hoverRemove.appendChild(domRemove); hover.appendChild(hoverRemove); } } else { hoverReply.style.backgroundImage = 'url("repl.svg")'; if (DATA.context.isMe(msg.userId)) { var hoverEdit = document.createElement("li"); hoverEdit.className = R.klass.msg.hover.edit; hoverEdit.style.backgroundImage = 'url("edit.svg")'; hover.appendChild(hoverEdit); var hoverRemove = document.createElement("li") hoverRemove.className = R.klass.msg.hover.remove; hoverRemove.style.backgroundImage = 'url("remove.svg")'; hover.appendChild(hoverRemove); } } msgBlock.appendChild(dom.authorName); msgBlock.appendChild(dom.textDom); msgBlock.appendChild(dom.ts); msgBlock.appendChild(dom.attachments); dom.edited = document.createElement("div"); dom.edited.className = R.klass.msg.edited; msgBlock.appendChild(dom.edited); msgBlock.appendChild(dom.reactions); msgBlock.className = R.klass.msg.content; dom.attachments.className = R.klass.msg.attachment.list; dom.reactions.className = R.klass.msg.reactions.container; dom.appendChild(msgBlock); dom.appendChild(hover); return dom; } /** * @param {Chatter} user * @param {string} userName * @return {Element} **/ function createMessageGroupDom(user, userName) { var dom = document.createElement("div") ,authorBlock = document.createElement("div") ,authorName = document.createElement("span"); dom.authorImg = document.createElement("img") dom.authorImg.className = R.klass.msg.authorAvatar; authorName.className = R.klass.msg.authorname; if (user) { authorName.textContent = user.name; dom.authorImg.src = user.getSmallIcon(); } else { authorName.textContent = userName || "?"; dom.authorImg.src = ""; } authorBlock.appendChild(dom.authorImg); authorBlock.appendChild(authorName); authorBlock.className = R.klass.msg.author; dom.className = R.klass.msg.authorGroup; dom.appendChild(authorBlock); dom.content = document.createElement("div"); dom.content.className = R.klass.msg.authorMessages; dom.appendChild(dom.content); return dom; } /** * @param {string=} colorText * @return {string} **/ function getColor(colorText) { /** @const @type {Object.} */ var colorMap = { "good": "#2fa44f" ,"warning": "#de9e31" ,"danger": "#d50200" }; if (colorText) { if (colorText[0] === '#') return colorText; else if (colorMap[colorText]) return colorMap[colorText]; } return "#e3e4e6"; } /** * @param {string} channelId * @param {UiNoticeMessage|UiMessage} msg * @param {*} attachment * @param {number} attachmentIndex * @return {Element|null} **/ function createAttachmentDom(channelId, msg, attachment, attachmentIndex) { var rootDom = document.createElement("li") ,attachmentBlock = document.createElement("div") ,pretext = document.createElement("div") ,titleBlock = document.createElement("a") ,authorBlock = document.createElement("div") ,authorImg = document.createElement("img") ,authorName = document.createElement("a") ,textBlock = document.createElement("div") ,textDom = document.createElement("div") ,thumbImgDom = document.createElement("div") ,imgDom = document.createElement("img") ,footerBlock = document.createElement("div") ; rootDom.className = R.klass.msg.attachment.container; //Color attachmentBlock.style.borderColor = getColor(attachment["color"] || ""); attachmentBlock.className = R.klass.msg.attachment.block; //Pretext pretext.className = R.klass.msg.attachment.pretext; if (attachment["pretext"]) { pretext.innerHTML = msg.formatText(attachment["pretext"]); } else { pretext.classList.add(R.klass.hidden); } //Title titleBlock.target = "_blank"; if (attachment["title"]) { titleBlock.innerHTML = msg.formatText(attachment["title"]); if (attachment["title_link"]) { titleBlock.href = attachment["title_link"]; } titleBlock.className = R.klass.msg.attachment.title; } else { titleBlock.className = R.klass.hidden + " " +R.klass.msg.attachment.title; } //Author authorName.target = "_blank"; authorBlock.className = R.klass.msg.author; if (attachment["author_name"]) { authorName.innerHTML = msg.formatText(attachment["author_name"]); authorName.href = attachment["author_link"] || ""; authorName.className = R.klass.msg.authorname; authorImg.className = R.klass.msg.authorAvatar; if (attachment["author_icon"]) { authorImg.src = attachment["author_icon"]; authorBlock.appendChild(authorImg); } authorBlock.appendChild(authorName); } // Img (small one) thumbImgDom.className = R.klass.msg.attachment.thumbImg; if (attachment["thumb_url"]) { var img = document.createElement("img"); img.src = attachment["thumb_url"]; thumbImgDom.appendChild(img); attachmentBlock.classList.add(R.klass.msg.attachment.hasThumb); if (attachment["video_html"]) thumbImgDom.dataset["video"] = attachment["video_html"]; } else { thumbImgDom.classList.add(R.klass.hidden); } //Text textBlock.className = R.klass.msg.attachment.content; var textContent = msg.formatText(attachment["text"] || ""); textDom.className = R.klass.msg.attachment.text; if (textContent && textContent != "") { textDom.innerHTML = textContent; } else { textDom.classList.add(R.klass.hidden); } textBlock.appendChild(thumbImgDom); textBlock.appendChild(textDom); if (attachment["geo"]) { var geoTileDom = makeOSMTiles(attachment["geo"]); if (geoTileDom) textBlock.appendChild(geoTileDom); } //Img (the big one) imgDom.className = R.klass.msg.attachment.img; if (attachment["image_url"]) imgDom.src = attachment["image_url"]; else imgDom.classList.add(R.klass.hidden); //Footer footerBlock.className = R.klass.msg.attachment.footer; if (attachment["footer"]) { var footerText = document.createElement("span") footerText.className = R.klass.msg.attachment.footerText; footerText.innerHTML = msg.formatText(attachment["footer"]); if (attachment["footer_icon"]) { var footerIcon = document.createElement("img") footerIcon.src = attachment["footer_icon"]; footerIcon.className = R.klass.msg.attachment.footerIcon; footerBlock.appendChild(footerIcon); } footerBlock.appendChild(footerText); } //Ts if (attachment["ts"]) { var footerTs = document.createElement("span") footerTs.className = R.klass.msg.ts; footerTs.innerHTML = locale.formatDate(attachment["ts"]); footerBlock.appendChild(footerTs); } attachmentBlock.appendChild(titleBlock); attachmentBlock.appendChild(authorBlock); attachmentBlock.appendChild(textBlock); attachmentBlock.appendChild(imgDom); // Fields if (attachment["fields"] && attachment["fields"].length) { var fieldsContainer = document.createElement("ul"); attachmentBlock.appendChild(fieldsContainer); fieldsContainer.className = R.klass.msg.attachment.field.container; attachment["fields"].forEach(function(fieldData) { var fieldDom = createFieldDom(msg, fieldData["title"] || "", fieldData["value"] || "", !!fieldData["short"]); if (fieldDom) { fieldsContainer.appendChild(fieldDom); } }); } // Buttons if (attachment["actions"] && attachment["actions"].length) { var buttons; buttons = document.createElement("ul"); buttons.className = R.klass.msg.attachment.actions +' ' +R.klass.buttonContainer; attachmentBlock.appendChild(buttons); for (var i =0, nbAttachments = attachment["actions"].length; i < nbAttachments; i++) { var action = attachment["actions"][i]; if (action) { var button = createActionButtonDom(attachmentIndex, i, action); if (button) { buttons.appendChild(button); } } } } attachmentBlock.appendChild(footerBlock); rootDom.appendChild(pretext); rootDom.appendChild(attachmentBlock); return rootDom; } /** * @param {UiMessage|UiNoticeMessage} msg * @param {string} title * @param {string} text * @param {boolean} isShort * @return {Element} **/ function createFieldDom(msg, title, text, isShort) { var fieldDom = document.createElement("li") ,titleDom = document.createElement("div") ,textDom = document.createElement("div"); fieldDom.className = R.klass.msg.attachment.field.item; if (!isShort) { fieldDom.classList.add(R.klass.msg.attachment.field.longField); } titleDom.className = R.klass.msg.attachment.field.title; titleDom.textContent = title; textDom.className = R.klass.msg.attachment.field.text; textDom.innerHTML = msg.formatText(text); fieldDom.appendChild(titleDom); fieldDom.appendChild(textDom); return fieldDom; } /** * @param {number} attachmentIndex * @param {number} actionIndex * @param {*} action * @return {Element} **/ function createActionButtonDom(attachmentIndex, actionIndex, action) { var li = document.createElement("li") ,color = getColor(action["style"]); li.textContent = action["text"]; if (color !== getColor()) li.style.color = color; li.style.borderColor = color; li.dataset["attachmentIndex"] = attachmentIndex; li.dataset["actionIndex"] = actionIndex; li.className = R.klass.msg.attachment.actionItem +' ' +R.klass.button; return li; } /** * @param {Chatter} user * @return {Element} **/ function makeUserIsTypingDom(user) { var dom = document.createElement("li") ,userName = document.createElement("span"); userName.textContent = user.name; dom.appendChild(createTypingDisplay()); dom.appendChild(userName); return dom; } /** * @param {string} servicename * @return {Element} **/ function createSlashAutocompleteHeader(servicename) { var lh = document.createElement("lh"); lh.textContent = servicename; lh.className = R.klass.commands.header; return lh; } /** * @param {Command} cmd * @return {Element} **/ function createSlashAutocompleteDom(cmd) { var li = document.createElement("li") ,name = document.createElement("span") ,usage = document.createElement("span") ,desc = document.createElement("span"); name.textContent = cmd.name; usage.textContent = cmd.usage; desc.textContent = cmd.desc; li.appendChild(name); li.appendChild(usage); li.appendChild(desc); li.className = R.klass.commands.item; name.className = R.klass.commands.name; usage.className = R.klass.commands.usage; desc.className = R.klass.commands.desc; return li; }