mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2024-10-31 14:10:08 +00:00
Rewrite frontend
With this commit pretty much the whole frontend has been rewritten. This should hopefully fix most of the issues in “exotic” styles. The changes include: - Overall cleanup - Better adaption to the WCF design - Reworked private channels menu - Reworked sidebar (may change later, currently the heights of the elements are hardcoded and not dynamic) - Working user action menu - Fixed auto scrolling - Better visual notifications - This software does not contain any easter eggs - No penguins were harmed in the production of this software Todo: - Fullscreen mode - Some language variables
This commit is contained in:
parent
4d208f8893
commit
92ed075076
@ -6,7 +6,7 @@ everything that happens in the GUI of **Tims Chat**.
|
|||||||
|
|
||||||
### Copyright Information
|
### Copyright Information
|
||||||
# @author Tim Düsterhus
|
# @author Tim Düsterhus
|
||||||
# @copyright 2010-2013 Tim Düsterhus
|
# @copyright 2010-2014 Tim Düsterhus
|
||||||
# @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
# @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
# @package be.bastelstu.chat
|
# @package be.bastelstu.chat
|
||||||
###
|
###
|
||||||
@ -25,7 +25,7 @@ enabling EMCAScript 5 strict mode and overwriting console to prepend the name of
|
|||||||
window.console.warn "[be.bastelstu.Chat] #{message}"
|
window.console.warn "[be.bastelstu.Chat] #{message}"
|
||||||
error: (message) ->
|
error: (message) ->
|
||||||
window.console.error "[be.bastelstu.Chat] #{message}"
|
window.console.error "[be.bastelstu.Chat] #{message}"
|
||||||
|
|
||||||
Continue with defining the needed variables. All variables are local to our closure and will be
|
Continue with defining the needed variables. All variables are local to our closure and will be
|
||||||
exposed by a function if necessary.
|
exposed by a function if necessary.
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ exposed by a function if necessary.
|
|||||||
Initialize **Tims Chat**. Bind needed DOM events and initialize data structures.
|
Initialize **Tims Chat**. Bind needed DOM events and initialize data structures.
|
||||||
|
|
||||||
initialized = false
|
initialized = false
|
||||||
init = (roomID, config, titleTemplate, messageTemplate, userTemplate) ->
|
init = (roomID, config, titleTemplate, messageTemplate, userTemplate, userMenuTemplate) ->
|
||||||
return false if initialized
|
return false if initialized
|
||||||
initialized = true
|
initialized = true
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ Initialize **Tims Chat**. Bind needed DOM events and initialize data structures.
|
|||||||
v.titleTemplate = titleTemplate
|
v.titleTemplate = titleTemplate
|
||||||
v.messageTemplate = messageTemplate
|
v.messageTemplate = messageTemplate
|
||||||
v.userTemplate = userTemplate
|
v.userTemplate = userTemplate
|
||||||
|
v.userMenuTemplate = userMenuTemplate
|
||||||
|
|
||||||
console.log 'Initializing'
|
console.log 'Initializing'
|
||||||
|
|
||||||
@ -117,7 +118,8 @@ Insert the appropriate smiley code into the input when a smiley is clicked.
|
|||||||
|
|
||||||
Handle private channel menu
|
Handle private channel menu
|
||||||
|
|
||||||
$('#privateChannelsMenu').on 'click', '.privateChannel', -> openPrivateChannel $(@).data 'privateChannelID'
|
$('#timsChatMessageTabMenu > .tabMenu').on 'click', '.timsChatMessageTabMenuAnchor', ->
|
||||||
|
openPrivateChannel $(@).data 'userID'
|
||||||
|
|
||||||
Handle submitting the form. The message will be validated by some basic checks, passed to the `submit` eventlisteners
|
Handle submitting the form. The message will be validated by some basic checks, passed to the `submit` eventlisteners
|
||||||
and afterwards sent to the server by an AJAX request.
|
and afterwards sent to the server by an AJAX request.
|
||||||
@ -217,9 +219,24 @@ Reset autocompleter to default status, when the input is `click`ed, as the posit
|
|||||||
value: null
|
value: null
|
||||||
caret: null
|
caret: null
|
||||||
|
|
||||||
|
Bind user menu functions
|
||||||
|
|
||||||
|
$('#dropdownMenuContainer').on 'click', '.jsTimsChatUserMenuWhisper', ->
|
||||||
|
command = "/whisper #{userList.current[$(@).parents('ul').data 'userID'].username}, "
|
||||||
|
return if $('#timsChatInput').val().match(new RegExp WCF.String.escapeRegExp("^#{command}"), 'i')
|
||||||
|
|
||||||
|
insertText command, prepend: yes
|
||||||
|
|
||||||
|
$('#dropdownMenuContainer').on 'click', '.jsTimsChatUserMenuQuery', -> openPrivateChannel $(@).parents('ul').data 'userID'
|
||||||
|
$('#dropdownMenuContainer').on 'click', '.jsTimsChatUserMenuBan', ->
|
||||||
|
command = "/ban #{userList.current[$(@).parents('ul').data 'userID'].username}, "
|
||||||
|
return if $('#timsChatInput').val().match(new RegExp WCF.String.escapeRegExp("^#{command}"), 'i')
|
||||||
|
|
||||||
|
insertText command, prepend: yes
|
||||||
|
|
||||||
Refresh the room list when the associated button is `click`ed.
|
Refresh the room list when the associated button is `click`ed.
|
||||||
|
|
||||||
$('#timsChatRoomList button').click -> do refreshRoomList
|
$('#timsChatRoomListReloadButton').click -> do refreshRoomList
|
||||||
|
|
||||||
Clear the chat by removing every single message once the clear button is `clicked`.
|
Clear the chat by removing every single message once the clear button is `clicked`.
|
||||||
|
|
||||||
@ -247,9 +264,9 @@ Mark smilies as disabled when they are disabled.
|
|||||||
|
|
||||||
$('#timsChatSmilies').click (event) ->
|
$('#timsChatSmilies').click (event) ->
|
||||||
if $(@).data 'status'
|
if $(@).data 'status'
|
||||||
$('#smilies').removeClass 'disabled'
|
$('#smilies').removeClass 'invisible'
|
||||||
else
|
else
|
||||||
$('#smilies').addClass 'disabled'
|
$('#smilies').addClass 'invisible'
|
||||||
|
|
||||||
Toggle fullscreen mode.
|
Toggle fullscreen mode.
|
||||||
|
|
||||||
@ -272,12 +289,12 @@ Toggle checkboxes.
|
|||||||
|
|
||||||
Hide topic container.
|
Hide topic container.
|
||||||
|
|
||||||
$('.jsTopicCloser').on 'click', ->
|
$('#timsChatTopicCloser').on 'click', -> $('#timsChatTopic').addClass 'invisible'
|
||||||
if $('.timsChatMessageContainer.active').data('userID') is 0
|
|
||||||
$('#timsChatTopic').addClass 'hidden'
|
Close private channels
|
||||||
else
|
|
||||||
closePrivateChannel $('.timsChatMessageContainer.active').data('userID')
|
$('#timsChatMessageTabMenu').on 'click', '.jsChannelCloser', -> closePrivateChannel $(@).parent().data 'userID'
|
||||||
|
|
||||||
Visibly mark the message once the associated checkbox is checked.
|
Visibly mark the message once the associated checkbox is checked.
|
||||||
|
|
||||||
$(document).on 'click', '.timsChatMessage :checkbox', (event) ->
|
$(document).on 'click', '.timsChatMessage :checkbox', (event) ->
|
||||||
@ -289,27 +306,20 @@ Visibly mark the message once the associated checkbox is checked.
|
|||||||
Scroll down when autoscroll is being activated.
|
Scroll down when autoscroll is being activated.
|
||||||
|
|
||||||
$('#timsChatAutoscroll').click (event) ->
|
$('#timsChatAutoscroll').click (event) ->
|
||||||
if $('#timsChatAutoscroll').data 'status'
|
if $(@).data 'status'
|
||||||
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop 'scrollHeight'
|
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop 'scrollHeight'
|
||||||
|
|
||||||
|
scrollUpNotifications = off
|
||||||
|
$("#timsChatMessageTabMenu > .tabMenu > ul > li.ui-state-active").removeClass 'notify'
|
||||||
|
$(".timsChatMessageContainer.active").removeClass 'notify'
|
||||||
|
else
|
||||||
|
scrollUpNotifications = on
|
||||||
|
|
||||||
|
Bind scroll event on predefined message containers
|
||||||
|
|
||||||
$('.timsChatMessageContainer.active').on 'scroll', (event) ->
|
$('.timsChatMessageContainer.active').on 'scroll', (event) ->
|
||||||
event.stopPropagation();
|
do event.stopPropagation
|
||||||
|
handleScroll event
|
||||||
element = $ @
|
|
||||||
scrollTop = element.scrollTop()
|
|
||||||
scrollHeight = element.prop 'scrollHeight'
|
|
||||||
height = element.height()
|
|
||||||
|
|
||||||
if scrollTop < scrollHeight - height - 25
|
|
||||||
if $('#timsChatAutoscroll').data('status') is 1
|
|
||||||
scrollUpNotifications = on
|
|
||||||
do $('#timsChatAutoscroll').click
|
|
||||||
|
|
||||||
if scrollTop > scrollHeight - height - 10
|
|
||||||
if $('#timsChatAutoscroll').data('status') is 0
|
|
||||||
scrollUpNotifications = off
|
|
||||||
$(@).removeClass 'notification'
|
|
||||||
do $('#timsChatAutoscroll').click
|
|
||||||
|
|
||||||
Enable duplicate tab detection.
|
Enable duplicate tab detection.
|
||||||
|
|
||||||
@ -384,35 +394,85 @@ Free the fish.
|
|||||||
freeTheFish = ->
|
freeTheFish = ->
|
||||||
return if $.wcfIsset 'fish'
|
return if $.wcfIsset 'fish'
|
||||||
console.warn 'Freeing the fish'
|
console.warn 'Freeing the fish'
|
||||||
fish = $ """<div id="fish">#{WCF.String.escapeHTML('><((((\u00B0>')}</div>"""
|
fish = $ """<div id="fish"><span></span></div>"""
|
||||||
|
fish.direction = 'right'
|
||||||
|
|
||||||
fish.css
|
fish.css
|
||||||
position: 'fixed'
|
position: 'fixed'
|
||||||
top: '50%'
|
top: '50%'
|
||||||
left: '50%'
|
left: '50%'
|
||||||
color: 'black'
|
zIndex: 0x7FFFFFFF
|
||||||
textShadow: '1px 1px white'
|
textShadow: '1px 1px rgb(0, 0, 0)'
|
||||||
zIndex: 9999
|
|
||||||
|
|
||||||
fish.appendTo $ 'body'
|
fish.appendTo $ 'body'
|
||||||
pe.fish = new WCF.PeriodicalExecuter ->
|
|
||||||
left = Math.random() * 100 - 50
|
fish.colors = ['78C5D6', '459ba8', '79C267', 'C5D647', 'F5D63D', 'F28C33', 'E868A2', 'BF62A6']
|
||||||
top = Math.random() * 100 - 50
|
fish.colorIndex = 0
|
||||||
fish = $ '#fish'
|
|
||||||
|
fish.texts =
|
||||||
|
right: '><((((\u00B0>'
|
||||||
|
left: '<\u00B0))))><'
|
||||||
|
fish.fishes = {}
|
||||||
|
|
||||||
|
Pre build fishes, this allows for faster animation
|
||||||
|
|
||||||
|
$.each fish.texts, (key, value) ->
|
||||||
|
fish.fishes[key] = []
|
||||||
|
index = 0
|
||||||
|
|
||||||
left *= -1 unless fish.width() < (fish.position().left + left) < ($(window).width() - fish.width())
|
while index < value.length
|
||||||
top *= -1 unless fish.height() < (fish.position().top + top) < ($(window).height() - fish.height())
|
html = $ '<span/>'
|
||||||
|
i = 0
|
||||||
if left > 0
|
$(value.split '').each (key, value) ->
|
||||||
fish.text '><((((\u00B0>' if left > 0
|
$("<span>#{value}</span>").css
|
||||||
else if left < 0
|
color: '#' + fish.colors[(i++ + index) % fish.colors.length]
|
||||||
fish.text '<\u00B0))))><'
|
textShadow: '1px 1px rgb(0, 0, 0)'
|
||||||
|
.appendTo html
|
||||||
|
fish.fishes[key][index++] = html
|
||||||
|
return
|
||||||
|
|
||||||
|
fish.find('> span').replaceWith fish.fishes[fish.direction][0]
|
||||||
|
|
||||||
|
fish.updateRainbowText = (key, value) ->
|
||||||
|
key = key || fish.direction
|
||||||
|
return unless fish.fishes[key]? || not fish.texts[key]?
|
||||||
|
value = value || fish.colorIndex++ % fish.texts[key].length
|
||||||
|
|
||||||
|
fish.find('> span').replaceWith fish.fishes[key][value]
|
||||||
|
|
||||||
|
fish.pePos = new WCF.PeriodicalExecuter ->
|
||||||
|
loops = 0
|
||||||
|
loop
|
||||||
|
++loops
|
||||||
|
|
||||||
|
left = Math.random() * 300 - 150
|
||||||
|
top = Math.random() * 300 - 150
|
||||||
|
|
||||||
|
if (fish.position().top + top) > 0 and (fish.position().left + left + fish.width()) < $(window).width() and (fish.position().top + top + fish.height()) < $(window).height() and (fish.position().left + left) > 0
|
||||||
|
break
|
||||||
|
else if loops is 10
|
||||||
|
console.log 'Magicarp used Splash for the 10th time in a row - it fainted!'
|
||||||
|
fish.css
|
||||||
|
'top': '50%'
|
||||||
|
'left': '50%'
|
||||||
|
break
|
||||||
|
|
||||||
|
if left > 0 and fish.text() isnt '><((((\u00B0>'
|
||||||
|
fish.direction = 'right'
|
||||||
|
fish.updateRainbowText null, fish.colorIndex % fish.texts.right.length
|
||||||
|
else if left < 0 and fish.text() isnt '<\u00B0))))><'
|
||||||
|
fish.direction = 'left'
|
||||||
|
fish.updateRainbowText null, fish.colorIndex % fish.texts.left.length
|
||||||
|
|
||||||
fish.animate
|
fish.animate
|
||||||
top: (fish.position().top + top)
|
top: (fish.position().top + top)
|
||||||
left: (fish.position().left + left)
|
left: (fish.position().left + left)
|
||||||
, 1e3
|
, 1e3
|
||||||
, 1.5e3
|
, 1.2e3
|
||||||
|
|
||||||
|
fish.peColor = new WCF.PeriodicalExecuter ->
|
||||||
|
do fish.updateRainbowText
|
||||||
|
, .125e3
|
||||||
|
|
||||||
Fetch new messages from the server and pass them to `handleMessages`. The userlist will be passed to `handleUsers`.
|
Fetch new messages from the server and pass them to `handleMessages`. The userlist will be passed to `handleUsers`.
|
||||||
`remainingFailures` will be decreased on failure and message loading will be entirely disabled once it reaches zero.
|
`remainingFailures` will be decreased on failure and message loading will be entirely disabled once it reaches zero.
|
||||||
@ -446,15 +506,13 @@ Prevent loading messages in parallel.
|
|||||||
Insert the given messages into the chat stream.
|
Insert the given messages into the chat stream.
|
||||||
|
|
||||||
handleMessages = (messages) ->
|
handleMessages = (messages) ->
|
||||||
$('.timsChatMessageContainer.active').trigger 'scroll'
|
|
||||||
|
|
||||||
for message in messages
|
for message in messages
|
||||||
message.isInPrivateChannel = (String(message.type) is v.config.messageTypes.WHISPER) and ($.wcfIsset("timsChatMessageContainer#{message.receiver}") or $.wcfIsset("timsChatMessageContainer#{message.sender}"))
|
message.isInPrivateChannel = (String(message.type) is v.config.messageTypes.WHISPER) and ($.wcfIsset("timsChatMessageContainer#{message.receiver}") or $.wcfIsset("timsChatMessageContainer#{message.sender}"))
|
||||||
|
|
||||||
events.newMessage.fire message
|
events.newMessage.fire message
|
||||||
|
|
||||||
createNewMessage = yes
|
createNewMessage = yes
|
||||||
if $('.timsChatMessage:last-child .text').is('ul') and lastMessage isnt null and lastMessage.type in [ 0, 7 ]
|
if $('.timsChatMessage:last-child .timsChatText').is('ul') and lastMessage isnt null and lastMessage.type in [ v.config.messageTypes.NORMAL, v.config.messageTypes.WHISPER ]
|
||||||
if lastMessage.type is message.type and lastMessage.sender is message.sender and lastMessage.receiver is message.receiver and lastMessage.isInPrivateChannel is message.isInPrivateChannel
|
if lastMessage.type is message.type and lastMessage.sender is message.sender and lastMessage.receiver is message.receiver and lastMessage.isInPrivateChannel is message.isInPrivateChannel
|
||||||
createNewMessage = no
|
createNewMessage = no
|
||||||
|
|
||||||
@ -490,11 +548,34 @@ Insert the given messages into the chat stream.
|
|||||||
else
|
else
|
||||||
messageContainerID = 0
|
messageContainerID = 0
|
||||||
|
|
||||||
$("#timsChatMessageContainer#{messageContainerID} .timsChatMessage:last-child .text").append $(output).find('.text li:last-child')
|
$("#timsChatMessageContainer#{messageContainerID} .timsChatMessage:last-child .timsChatText").append $(output).find('.timsChatText li:last-child')
|
||||||
|
|
||||||
lastMessage = message
|
lastMessage = message
|
||||||
|
|
||||||
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop('scrollHeight') if $('#timsChatAutoscroll').data('status') is 1
|
$('.timsChatMessageContainer.active').scrollTop $('.timsChatMessageContainer.active').prop('scrollHeight') if $('#timsChatAutoscroll').data('status') is 1
|
||||||
|
|
||||||
|
Handles scroll event of message containers
|
||||||
|
|
||||||
|
handleScroll = (event) ->
|
||||||
|
element = $ event.target
|
||||||
|
|
||||||
|
if element.hasClass 'active'
|
||||||
|
scrollTop = element.scrollTop()
|
||||||
|
scrollHeight = element.prop 'scrollHeight'
|
||||||
|
height = element.innerHeight()
|
||||||
|
|
||||||
|
if scrollTop < scrollHeight - height - 25
|
||||||
|
if $('#timsChatAutoscroll').data('status') is 1
|
||||||
|
scrollUpNotifications = on
|
||||||
|
do $('#timsChatAutoscroll').click
|
||||||
|
|
||||||
|
if scrollTop > scrollHeight - height - 10
|
||||||
|
if $('#timsChatAutoscroll').data('status') is 0
|
||||||
|
scrollUpNotifications = off
|
||||||
|
$("#timsChatMessageTabMenu > .tabMenu > ul > li.ui-state-active").removeClass 'notify'
|
||||||
|
$(".timsChatMessageContainer.active").removeClass 'notify'
|
||||||
|
do $('#timsChatAutoscroll').click
|
||||||
|
|
||||||
Rebuild the userlist based on the given `users`.
|
Rebuild the userlist based on the given `users`.
|
||||||
|
|
||||||
handleUsers = (users) ->
|
handleUsers = (users) ->
|
||||||
@ -545,14 +626,7 @@ Build HTML of the user and insert it into the list, if the users was not found i
|
|||||||
|
|
||||||
li.append v.userTemplate.fetch user
|
li.append v.userTemplate.fetch user
|
||||||
|
|
||||||
menu = $ '<ul></ul>'
|
menu = $(v.userMenuTemplate.fetch user)
|
||||||
unless user.userID is WCF.User.userID
|
|
||||||
menu.append $("<li><a>#{WCF.Language.get('chat.general.query')}</a></li>").click -> openPrivateChannel user.userID
|
|
||||||
menu.append $ "<li><a>#{WCF.Language.get('chat.general.kick')}</a></li>"
|
|
||||||
menu.append $ "<li><a>#{WCF.Language.get('chat.general.ban')}</a></li>"
|
|
||||||
menu.append $ """<li><a href="#{user.link}">#{WCF.Language.get('chat.general.profile')}</a></li>"""
|
|
||||||
|
|
||||||
events.userMenu.fire user, menu
|
|
||||||
|
|
||||||
if menu.find('li').length
|
if menu.find('li').length
|
||||||
li.append menu
|
li.append menu
|
||||||
@ -560,7 +634,6 @@ Build HTML of the user and insert it into the list, if the users was not found i
|
|||||||
li.addClass 'dropdown'
|
li.addClass 'dropdown'
|
||||||
|
|
||||||
li.appendTo $ '#timsChatUserList > ul'
|
li.appendTo $ '#timsChatUserList > ul'
|
||||||
|
|
||||||
foundUsers[id] = true
|
foundUsers[id] = true
|
||||||
|
|
||||||
Remove all users that left the chat.
|
Remove all users that left the chat.
|
||||||
@ -578,12 +651,17 @@ Insert the given `text` into the input. If `options.append` is true the given `t
|
|||||||
the existing text. If `options.submit` is true the message will be sent to the server afterwards.
|
the existing text. If `options.submit` is true the message will be sent to the server afterwards.
|
||||||
|
|
||||||
insertText = (text, options = { }) ->
|
insertText = (text, options = { }) ->
|
||||||
|
options.append = false if options.prepend? and options.prepend and not options.append?
|
||||||
|
|
||||||
options = $.extend
|
options = $.extend
|
||||||
|
prepend: false
|
||||||
append: true
|
append: true
|
||||||
submit: false
|
submit: false
|
||||||
, options
|
, options
|
||||||
|
|
||||||
|
text = text + $('#timsChatInput').val() if options.prepend
|
||||||
text = $('#timsChatInput').val() + text if options.append
|
text = $('#timsChatInput').val() + text if options.append
|
||||||
|
|
||||||
$('#timsChatInput').val text
|
$('#timsChatInput').val text
|
||||||
do $('#timsChatInput').keyup
|
do $('#timsChatInput').keyup
|
||||||
|
|
||||||
@ -595,19 +673,21 @@ the existing text. If `options.submit` is true the message will be sent to the s
|
|||||||
Send out notifications for the given `message`. The number of unread messages will be prepended to `document.title` and if available desktop notifications will be sent.
|
Send out notifications for the given `message`. The number of unread messages will be prepended to `document.title` and if available desktop notifications will be sent.
|
||||||
|
|
||||||
notify = (message) ->
|
notify = (message) ->
|
||||||
if scrollUpNotifications
|
return if message.sender is WCF.User.userID
|
||||||
$('.timsChatMessageContainer.active').addClass 'notification'
|
|
||||||
|
|
||||||
if message.isInPrivateChannel
|
if scrollUpNotifications
|
||||||
if message.sender is WCF.User.userID
|
$("#timsChatMessageTabMenu > .tabMenu > ul > li.ui-state-active").addClass 'notify'
|
||||||
privateChannelID = message.receiver
|
$(".timsChatMessageContainer.active").addClass 'notify'
|
||||||
else
|
|
||||||
privateChannelID = message.sender
|
|
||||||
|
|
||||||
if $('.timsChatMessageContainer.active').data('userID') isnt privateChannelID
|
if message.isInPrivateChannel
|
||||||
$("#privateChannel#{privateChannelID}").addClass 'notify'
|
id = if message.sender is WCF.User.userID then message.receiver else message.sender
|
||||||
|
|
||||||
|
if $('.timsChatMessageContainer.active').data('userID') isnt id
|
||||||
|
$("#timsChatMessageTabMenuAnchor#{id}").parent().addClass 'notify'
|
||||||
|
$("#timsChatMessageContainer#{id}").addClass 'notify'
|
||||||
else if $('.timsChatMessageContainer.active').data('userID') isnt 0
|
else if $('.timsChatMessageContainer.active').data('userID') isnt 0
|
||||||
$("#privateChannel0").addClass 'notify'
|
$("#timsChatMessageTabMenuAnchor0").parent().addClass 'notify'
|
||||||
|
$("#timsChatMessageContainer0").addClass 'notify'
|
||||||
|
|
||||||
return if isActive or $('#timsChatNotify').data('status') is 0
|
return if isActive or $('#timsChatNotify').data('status') is 0
|
||||||
|
|
||||||
@ -645,8 +725,9 @@ Fetch the roomlist from the server and update it in the GUI.
|
|||||||
|
|
||||||
for room in data.returnValues
|
for room in data.returnValues
|
||||||
li = $ '<li></li>'
|
li = $ '<li></li>'
|
||||||
|
li.addClass('timsChatRoom').data('roomID', room.roomID)
|
||||||
li.addClass 'active' if room.active
|
li.addClass 'active' if room.active
|
||||||
$("""<a href="#{room.link}">#{WCF.String.escapeHTML(room.title)} <span class="badge">#{WCF.String.formatNumeric room.userCount}</span></a>""").addClass('timsChatRoom').data('roomID', room.roomID).appendTo li
|
$("""<a href="#{room.link}">#{WCF.String.escapeHTML(room.title)}</a> <span class="badge">#{WCF.String.formatNumeric room.userCount}</span>""").appendTo li
|
||||||
$('#timsChatRoomList ul').append li
|
$('#timsChatRoomList ul').append li
|
||||||
|
|
||||||
if window.history?.replaceState?
|
if window.history?.replaceState?
|
||||||
@ -702,7 +783,7 @@ Joins a room.
|
|||||||
success: (data) ->
|
success: (data) ->
|
||||||
loading = false
|
loading = false
|
||||||
|
|
||||||
$('#timsChatTopic').removeClass 'hidden'
|
$('#timsChatTopic').removeClass 'invisible'
|
||||||
currentRoom = data.returnValues
|
currentRoom = data.returnValues
|
||||||
currentRoom.roomID = roomID
|
currentRoom.roomID = roomID
|
||||||
|
|
||||||
@ -734,66 +815,72 @@ Open private channel
|
|||||||
div = $ '<div>'
|
div = $ '<div>'
|
||||||
div.attr 'id', "timsChatMessageContainer#{userID}"
|
div.attr 'id', "timsChatMessageContainer#{userID}"
|
||||||
div.data 'userID', userID
|
div.data 'userID', userID
|
||||||
|
div.addClass 'tabMenuContent'
|
||||||
div.addClass 'timsChatMessageContainer'
|
div.addClass 'timsChatMessageContainer'
|
||||||
div.addClass 'marginTop'
|
|
||||||
div.addClass 'container'
|
div.addClass 'container'
|
||||||
div.wrapInner '<ul>'
|
div.addClass 'containerPadding'
|
||||||
|
div.wrapInner "<ul></ul>"
|
||||||
|
div.on 'scroll', (event) ->
|
||||||
|
do event.stopPropagation
|
||||||
|
handleScroll event
|
||||||
|
|
||||||
$('#timsChatMessageContainer0').after div
|
$('#timsChatMessageContainer0').after div
|
||||||
|
|
||||||
$('.privateChannel').removeClass 'active'
|
|
||||||
|
|
||||||
if userID isnt 0
|
if userID isnt 0
|
||||||
$('#timsChatTopic').removeClass 'hidden empty'
|
$('#timsChatTopic').removeClass 'empty'
|
||||||
$('#timsChatTopic > .topic').html WCF.Language.get 'chat.general.privateChannelTopic', {username: userList.allTime[userID].username}
|
$('#timsChatTopic > .topic').html WCF.Language.get 'chat.general.privateChannelTopic', {username: userList.allTime[userID].username}
|
||||||
$('#timsChatTopic > .jsTopicCloser').attr 'title', WCF.Language.get 'chat.general.closePrivateChannel'
|
$('#timsChatMessageTabMenu').removeClass 'singleTab'
|
||||||
|
|
||||||
unless $.wcfIsset "privateChannel#{userID}"
|
unless $.wcfIsset "timsChatMessageTabMenuAnchor#{userID}"
|
||||||
li = $ '<li>'
|
li = $ '<li>'
|
||||||
li.attr 'id', "privateChannel#{userID}"
|
|
||||||
li.data 'privateChannelID', userID
|
|
||||||
li.addClass 'privateChannel'
|
|
||||||
|
|
||||||
span = $ '<span class="userAvatar framed" />'
|
anchor = $ """<a id="timsChatMessageTabMenuAnchor#{userID}" class="timsChatMessageTabMenuAnchor" href="#{window.location.toString().replace /#.+$/, ''}#timsChatMessageContainer#{userID}" />"""
|
||||||
|
anchor.data 'userID', userID
|
||||||
|
|
||||||
avatar = $ userList.allTime[userID].avatar[16]
|
avatar = $ userList.allTime[userID].avatar[16]
|
||||||
avatar.addClass 'jsTooltip'
|
avatar = $('<span class="userAvatar framed" />').wrapInner avatar
|
||||||
avatar.attr 'title', userList.allTime[userID].username
|
avatar.append "<span>#{userList.allTime[userID].username}</span>"
|
||||||
avatar.wrap span
|
|
||||||
li.append avatar.parent().addClass 'small'
|
|
||||||
|
|
||||||
avatar = $ userList.allTime[userID].avatar[32]
|
anchor.wrapInner avatar
|
||||||
avatar.addClass 'jsTooltip'
|
anchor.prepend '<span class="icon icon16 icon-warning-sign notifyIcon"></span>'
|
||||||
avatar.attr 'title', userList.allTime[userID].username
|
anchor.append """<span class="jsChannelCloser icon icon16 icon-remove jsTooltip" title="#{WCF.Language.get('chat.global.closePrivateChannel')}" />"""
|
||||||
avatar.wrap span
|
|
||||||
li.append avatar.parent().addClass 'large'
|
|
||||||
|
|
||||||
$('#privateChannelsMenu ul').append li
|
li.append anchor
|
||||||
|
|
||||||
$('#privateChannelsMenu').addClass 'shown'
|
$('#timsChatMessageTabMenu > .tabMenu > ul').append li
|
||||||
|
$('#timsChatMessageTabMenu').wcfTabs 'refresh'
|
||||||
|
WCF.System.FlexibleMenu.rebuild $('#timsChatMessageTabMenu > .tabMenu').attr 'id'
|
||||||
else
|
else
|
||||||
$('#timsChatTopic > .topic').text currentRoom.topic
|
$('#timsChatTopic > .topic').text currentRoom.topic
|
||||||
$('#timsChatTopic > .jsTopicCloser').attr 'title', WCF.Language.get 'chat.general.closeTopic'
|
|
||||||
if currentRoom.topic.trim() is ''
|
if currentRoom.topic.trim() is ''
|
||||||
$('#timsChatTopic').addClass 'empty'
|
$('#timsChatTopic').addClass 'empty'
|
||||||
else
|
else
|
||||||
$('#timsChatTopic').removeClass 'empty'
|
$('#timsChatTopic').removeClass 'empty'
|
||||||
|
|
||||||
do WCF.DOMNodeInsertedHandler.execute
|
|
||||||
|
|
||||||
$('.timsChatMessageContainer').removeClass 'active'
|
$('.timsChatMessageContainer').removeClass 'active'
|
||||||
$("#timsChatMessageContainer#{userID}").addClass 'active'
|
$("#timsChatMessageContainer#{userID}").addClass 'active'
|
||||||
$("#privateChannel#{userID}").addClass('active').removeClass 'notify'
|
$("#timsChatMessageTabMenuAnchor#{userID}").parent().removeClass 'notify'
|
||||||
|
$("#timsChatMessageContainer#{userID}").removeClass 'notify'
|
||||||
|
if $('#timsChatAutoscroll').data('status')
|
||||||
|
do $('#timsChatAutoscroll').click
|
||||||
|
scrollUpNotifications = on
|
||||||
|
|
||||||
|
$('#timsChatMessageTabMenu').wcfTabs 'select', $("#timsChatMessageTabMenuAnchor#{userID}").parent().index()
|
||||||
|
do WCF.DOMNodeInsertedHandler.execute
|
||||||
|
|
||||||
openChannel = userID
|
openChannel = userID
|
||||||
|
|
||||||
Close private channel
|
Close private channel
|
||||||
|
|
||||||
closePrivateChannel = (userID) ->
|
closePrivateChannel = (userID) ->
|
||||||
unless userID is 0
|
unless userID is 0
|
||||||
do $("#privateChannel#{userID}").remove
|
do $("#timsChatMessageTabMenuAnchor#{userID}").parent().remove
|
||||||
do $("#timsChatMessageContainer#{userID}").remove
|
do $("#timsChatMessageContainer#{userID}").remove
|
||||||
|
$('#timsChatMessageTabMenu').wcfTabs 'refresh'
|
||||||
|
WCF.System.FlexibleMenu.rebuild $('#timsChatMessageTabMenu > .tabMenu').wcfIdentify()
|
||||||
|
|
||||||
if $('#privateChannelsMenu li').length <= 1
|
if $('#timsChatMessageTabMenu > .tabMenu > ul > li').length <= 1
|
||||||
$('#privateChannelsMenu').removeClass 'shown'
|
$('#timsChatMessageTabMenu').addClass 'singleTab'
|
||||||
|
|
||||||
openPrivateChannel 0
|
openPrivateChannel 0
|
||||||
|
|
||||||
@ -965,7 +1052,7 @@ Create a message containing the uploaded attachment
|
|||||||
unless parseInt(data.returnValues.attachments[internalFileID].isImage) is 0
|
unless parseInt(data.returnValues.attachments[internalFileID].isImage) is 0
|
||||||
link.addClass('jsImageViewer')
|
link.addClass('jsImageViewer')
|
||||||
|
|
||||||
if !data.returnValues.attachments[internalFileID].tinyURL
|
unless data.returnValues.attachments[internalFileID].tinyURL
|
||||||
li.find('.box32 > div.attachmentImageContainer > .icon-paper-clip').replaceWith $("""<img src="#{data.returnValues.attachments[internalFileID].url}'" alt="" class="attachmentTinyThumbnail" style="width: 32px; height: 32px;" />""")
|
li.find('.box32 > div.attachmentImageContainer > .icon-paper-clip').replaceWith $("""<img src="#{data.returnValues.attachments[internalFileID].url}'" alt="" class="attachmentTinyThumbnail" style="width: 32px; height: 32px;" />""")
|
||||||
|
|
||||||
li.find('.attachmentTinyThumbnail').wrap link
|
li.find('.attachmentTinyThumbnail').wrap link
|
||||||
|
@ -1,11 +1,42 @@
|
|||||||
/**
|
/**
|
||||||
* Styles for Tims Chat
|
* Styles for Tim’s Chat
|
||||||
*
|
*
|
||||||
* @author Tim Düsterhus, Maximilian Mader
|
* @author Tim Düsterhus, Maximilian Mader
|
||||||
* @copyright 2010-2013 Tim Düsterhus
|
* @copyright 2010-2014 Tim Düsterhus
|
||||||
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
* @license Creative Commons Attribution-NonCommercial-ShareAlike <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
|
||||||
* @package be.bastelstu.chat
|
* @package be.bastelstu.chat
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@-webkit-keyframes timsChatNotify {
|
||||||
|
from {
|
||||||
|
border-color: @wcfContainerBorderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
border-color: @wcfInputHoverBorderColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-moz-keyframes timsChatNotify {
|
||||||
|
from {
|
||||||
|
border-color: @wcfContainerBorderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
border-color: @wcfInputHoverBorderColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-o-keyframes timsChatNotify {
|
||||||
|
from {
|
||||||
|
border-color: @wcfContainerBorderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
border-color: @wcfInputHoverBorderColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes timsChatNotify {
|
@keyframes timsChatNotify {
|
||||||
from {
|
from {
|
||||||
border-color: @wcfContainerBorderColor;
|
border-color: @wcfContainerBorderColor;
|
||||||
@ -16,365 +47,400 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.__bubbleArrow {
|
// only apply styles to Tim’s Chat
|
||||||
border-color: transparent @wcfContainerBorderColor;
|
|
||||||
left: -6px;
|
|
||||||
top: 5px;
|
|
||||||
border-width: 6px 6px 6px 0;
|
|
||||||
border-style: solid;
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tplChat {
|
#tplChat {
|
||||||
#timsChatTopic {
|
#content {
|
||||||
padding: @wcfGapTiny;
|
// styles related to the topic container
|
||||||
.transition(height, .2s);
|
#timsChatTopic {
|
||||||
.transition(padding-top, .2s);
|
position: relative;
|
||||||
.transition(padding-bottom, .2s);
|
|
||||||
|
|
||||||
&.empty, &.hidden {
|
|
||||||
height: 0px;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jsTopicCloser {
|
|
||||||
cursor: pointer;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#privateChannelsMenu {
|
|
||||||
.transition(opacity, .2s);
|
|
||||||
.marginTop;
|
|
||||||
z-index: -1;
|
|
||||||
position: absolute;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
&.shown {
|
|
||||||
opacity: 1;
|
|
||||||
z-index: 130;
|
|
||||||
|
|
||||||
~ .timsChatMessageContainer {
|
#timsChatTopicCloser {
|
||||||
margin-left: 35px;
|
position: absolute;
|
||||||
border-top-left-radius: 0;
|
top: @wcfGapSmall;
|
||||||
|
right: @wcfGapSmall;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @wcfLinkColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> ul {
|
#timsChatMessageTabMenu {
|
||||||
text-align: right;
|
&.singleTab {
|
||||||
|
> nav.tabMenu {
|
||||||
> li:first-child {
|
// hide tab menu when single tabbed
|
||||||
> .userAvatar.framed {
|
// this is “a bit” hacky
|
||||||
img, > canvas, > .icon {
|
display: none !important;
|
||||||
border-radius: @wcfContainerBorderRadius 0 0 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> li:last-child {
|
|
||||||
> .userAvatar.framed {
|
|
||||||
img, > canvas, > .icon {
|
|
||||||
border-radius: 0 0 0 @wcfContainerBorderRadius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> li {
|
|
||||||
margin-bottom: -1px;
|
|
||||||
background-color: @wcfContainerBackgroundColor;
|
|
||||||
|
|
||||||
> .userAvatar, .userAvatar > .icon {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .userAvatar {
|
// overwrite WCF margin overwrite on tab menu content with WCF marginTop like margin
|
||||||
&.large {
|
// this is “a bit” hacky
|
||||||
display: none;
|
margin-top: @wcfGapMedium !important;
|
||||||
}
|
|
||||||
|
> .tabMenuContent {
|
||||||
&.small {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
.timsChatMessageContainer {
|
||||||
> .userAvatar {
|
&.notify {
|
||||||
&.large {
|
-webkit-animation-duration: .2s;
|
||||||
display: block;
|
-webkit-animation-name: timsChatNotify;
|
||||||
}
|
-webkit-animation-iteration-count: 5;
|
||||||
|
-webkit-animation-direction: alternate;
|
||||||
|
-webkit-animation-timing-function: linear;
|
||||||
|
|
||||||
&.small {
|
-moz-animation-duration: .2s;
|
||||||
display: none;
|
-moz-animation-name: timsChatNotify;
|
||||||
}
|
-moz-animation-iteration-count: 5;
|
||||||
|
-moz-animation-direction: alternate;
|
||||||
|
-moz-animation-timing-function: linear;
|
||||||
|
|
||||||
&.framed {
|
-o-animation-duration: .2s;
|
||||||
> img, > canvas, > .icon {
|
-o-animation-name: timsChatNotify;
|
||||||
border-right-color: @wcfContentBackgroundColor;
|
-o-animation-iteration-count: 5;
|
||||||
|
-o-animation-direction: alternate;
|
||||||
border-radius: @wcfContainerBorderRadius 0 0 @wcfContainerBorderRadius;
|
-o-animation-timing-function: linear;
|
||||||
|
|
||||||
|
animation-duration: .2s;
|
||||||
|
animation-name: timsChatNotify;
|
||||||
|
animation-iteration-count: 5;
|
||||||
|
animation-direction: alternate;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
|
||||||
|
border-color: @wcfInputHoverBorderColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> nav.tabMenu {
|
||||||
|
> ul {
|
||||||
|
> li {
|
||||||
|
> a {
|
||||||
|
.notifyIcon {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.notify {
|
|
||||||
> .userAvatar {
|
|
||||||
> * {
|
|
||||||
// TODO
|
|
||||||
opacity: .4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.timsChatMessageContainer {
|
|
||||||
height: 320px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.markEnabled {
|
|
||||||
ul {
|
|
||||||
.timsChatMessage {
|
|
||||||
&.jsMarked {
|
|
||||||
background-color: @wcfSelectedBackgroundColor;
|
|
||||||
color: @wcfSelectedColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .innerMessageContainer {
|
|
||||||
.markContainer {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
.timsChatMessage {
|
|
||||||
min-height: 20px;
|
|
||||||
clear: both;
|
|
||||||
.transition(opacity, .2s);
|
|
||||||
|
|
||||||
&.unloaded {
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(even) {
|
|
||||||
> .innerMessageContainer.bubble .innerMessage {
|
|
||||||
background-color: @wcfContainerAccentBackgroundColor;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
border-color: transparent @wcfContainerAccentBackgroundColor !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.messageIcon {
|
|
||||||
float: left;
|
|
||||||
padding: 8px 0 0 4px;
|
|
||||||
margin-right: -16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .innerMessageContainer {
|
|
||||||
padding: 5px 20px 5px 5px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> div.avatarContainer {
|
|
||||||
position: relative;
|
|
||||||
float: left;
|
|
||||||
margin-left: 16px;
|
|
||||||
|
|
||||||
> .avatarExtra {
|
|
||||||
box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.3);
|
|
||||||
position: absolute;
|
|
||||||
left: 24px;
|
|
||||||
bottom: -2px;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.innerMessage {
|
|
||||||
margin-left: 46px;
|
|
||||||
padding: 2px 5px 5px;
|
|
||||||
|
|
||||||
time {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .text {
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.bubble {
|
|
||||||
> div.avatarContainer {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.innerMessage {
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: @wcfContainerBorderColor;
|
|
||||||
border-radius: @wcfContainerBorderRadius;
|
|
||||||
background-color: @wcfContainerBackgroundColor;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> ul.text {
|
> .icon, img {
|
||||||
li {
|
// fix vertical alignment of images in tabs
|
||||||
.clearfix;
|
vertical-align: middle;
|
||||||
border-style: solid;
|
margin-right: @wcfGapTiny;
|
||||||
border-width: 0 0 1px 0;
|
}
|
||||||
border-color: @wcfContainerBorderColor;
|
|
||||||
padding: 3px 0 4px;
|
// styles related to the close button of private channels in tabs
|
||||||
|
.jsChannelCloser {
|
||||||
&:last-child {
|
&:hover {
|
||||||
border-style: none;
|
color: @wcfLinkColor;
|
||||||
padding: 3px 0 0 0;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.notify {
|
||||||
|
.notifyIcon {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.timsChatMessageContainer {
|
||||||
|
height: 300px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
.timsChatMarkContainer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
> .timsChatMessage {
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
&.unloaded {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .timsChatMessageIcon {
|
||||||
|
float: left;
|
||||||
|
margin-right: -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .timsChatInnerMessageContainer {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> .timsChatAvatarContainer {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
margin-left: 16px;
|
||||||
|
|
||||||
|
> .timsChatAvatarExtraIcon {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -8px;
|
||||||
|
right: -8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.timsChatInnerMessage {
|
||||||
|
margin-left: 32 + @wcfGapMedium; // size of avatars + a small gap
|
||||||
|
padding-right: @wcfGapSmall;
|
||||||
|
|
||||||
|
.timsChatUsernameContainer {
|
||||||
|
// sender username
|
||||||
|
> span:first-child {
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
time {
|
||||||
.__bubbleArrow;
|
float: right;
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
.__bubbleArrow;
|
|
||||||
border-color: transparent @wcfContainerBackgroundColor;
|
|
||||||
left: -5px;
|
|
||||||
top: 6px;
|
|
||||||
border-width: 5px 5px 5px 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.right {
|
&.bubble {
|
||||||
.avatarContainer {
|
> .timsChatAvatarContainer {
|
||||||
float: right;
|
margin-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.innerMessage {
|
.timsChatInnerMessage {
|
||||||
margin-right: 46px;
|
position: relative;
|
||||||
margin-left: 0px;
|
|
||||||
|
|
||||||
&:before {
|
padding: @wcfGapSmall;
|
||||||
.__bubbleArrow;
|
border-radius: @wcfContainerBorderRadius;
|
||||||
left: auto;
|
border-style: solid;
|
||||||
right: -6px;
|
border-width: 1px;
|
||||||
border-width: 6px 0 6px 6px;
|
border-color: @wcfContainerBorderColor;
|
||||||
|
|
||||||
|
> .timsChatText {
|
||||||
|
li {
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
border-color: @wcfContainerBorderColor;
|
||||||
|
padding: (@wcfGapTiny - 1) 0 @wcfGapTiny;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-style: none;
|
||||||
|
padding: (@wcfGapTiny - 1) 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// :before and :after are used to create the little arrows on the “speech bubble containers”
|
||||||
|
&:before, &:after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before{
|
||||||
|
border-color: transparent @wcfContainerBorderColor;
|
||||||
|
left: -@wcfGapSmall;
|
||||||
|
top: @wcfGapSmall;
|
||||||
|
border-width: @wcfGapSmall @wcfGapSmall @wcfGapSmall 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
.__bubbleArrow;
|
|
||||||
border-color: transparent @wcfContainerBackgroundColor;
|
border-color: transparent @wcfContainerBackgroundColor;
|
||||||
left: auto;
|
left: -@wcfGapSmall + 1;
|
||||||
right: -5px;
|
top: @wcfGapSmall + 1;
|
||||||
top: 6px;
|
border-width: (@wcfGapSmall - 1) (@wcfGapSmall - 1) (@wcfGapSmall - 1) 0;
|
||||||
border-width: 5px 0 5px 5px;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
> .timsChatAvatarContainer {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timsChatInnerMessage {
|
||||||
|
margin-right: 32 + @wcfGapMedium;
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
&:before{
|
||||||
|
border-color: transparent @wcfContainerBorderColor;
|
||||||
|
left: auto;
|
||||||
|
right: -@wcfGapSmall;
|
||||||
|
top: @wcfGapSmall;
|
||||||
|
border-width: @wcfGapSmall 0 @wcfGapSmall @wcfGapSmall;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-color: transparent @wcfContainerBackgroundColor;
|
||||||
|
left: auto;
|
||||||
|
right: -@wcfGapSmall + 1;
|
||||||
|
top: @wcfGapSmall + 1;
|
||||||
|
border-width: (@wcfGapSmall - 1) 0 (@wcfGapSmall - 1) (@wcfGapSmall - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .markContainer {
|
&:nth-child(even) {
|
||||||
display: none;
|
> .timsChatInnerMessageContainer {
|
||||||
position: absolute;
|
&.bubble {
|
||||||
right: 0px;
|
.timsChatInnerMessage {
|
||||||
top: 6px;
|
background-color: @wcfContainerAccentBackgroundColor;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-color: transparent @wcfContainerAccentBackgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
> .timsChatInnerMessageContainer {
|
||||||
|
margin-bottom: @wcfGapSmall;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.markEnabled {
|
||||||
|
> ul {
|
||||||
|
> .timsChatMessage {
|
||||||
|
&.jsMarked {
|
||||||
|
> .timsChatInnerMessageContainer {
|
||||||
|
.timsChatInnerMessage {
|
||||||
|
background-color: @wcfSelectedBackgroundColor;
|
||||||
|
color: @wcfSelectedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bubble {
|
||||||
|
.timsChatInnerMessage {
|
||||||
|
&:after {
|
||||||
|
border-color: transparent @wcfSelectedBackgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
.timsChatInnerMessage {
|
||||||
|
&:after {
|
||||||
|
border-color: transparent @wcfSelectedBackgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .timsChatInnerMessageContainer {
|
||||||
|
.timsChatMarkContainer {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
right: -@wcfGapLarge;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#smilies {
|
||||||
|
.marginTop();
|
||||||
|
|
||||||
|
// don't display the smiley box on low resolution devices as a button will be shown instead
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&, &.invisible {
|
||||||
|
-webkit-transition: opacity .2s ease-in-out;
|
||||||
|
-moz-transition: opacity .2s ease-in-out;
|
||||||
|
-ms-transition: opacity .2s ease-in-out;
|
||||||
|
-o-transition: opacity .2s ease-in-out;
|
||||||
|
transition: opacity .2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.invisible {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#timsChatOptions {
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
// styles related to the smiley button that replaces the smiley box on low resolution devices
|
||||||
|
#timsChatSmileyPopupButton {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix option buttons on low resolution devices, it will become a dropup not a dropdown
|
||||||
|
> nav.buttonGroupNavigation {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 800px) {
|
||||||
|
margin-right: @wcfGapSmall;
|
||||||
|
|
||||||
|
> ul {
|
||||||
|
right: 1px;
|
||||||
|
top: auto;
|
||||||
|
bottom: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the float on the first element after the option container, maybe someone alters their templates and puts an element down there ;)
|
||||||
|
+ * {
|
||||||
|
clear: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
padding-top: 0px !important;
|
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
height: 400px;
|
> fieldset{
|
||||||
overflow: auto !important;
|
padding-right: @wcfGapTiny;
|
||||||
> .chatTabMenuContainer {
|
|
||||||
padding: 14px 0 21px;
|
|
||||||
|
|
||||||
> .chatSidebarMenu {
|
> div {
|
||||||
background: @wcfContentBackgroundColor;
|
overflow-y: auto;
|
||||||
margin: -14px 0 0;
|
|
||||||
border-radius: 0px;
|
> ul {
|
||||||
|
padding-right: @wcfGapSmall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&#timsChatUserListContainer {
|
||||||
|
> div {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&#timsChatRoomListContainer {
|
||||||
|
> div#timsChatRoomList {
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebarContent {
|
#timsChatUserList {
|
||||||
fieldset {
|
> ul {
|
||||||
padding-top: 0px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
ul {
|
|
||||||
> li {
|
|
||||||
> a {
|
|
||||||
padding: @wcfGapTiny @wcfGapMedium @wcfGapTiny @wcfGapLarge;
|
|
||||||
height: 24px; // height of avatar image
|
|
||||||
}
|
|
||||||
|
|
||||||
> a:before {
|
|
||||||
display: inline-block;
|
|
||||||
content: "";
|
|
||||||
height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
> &.active {
|
|
||||||
margin-top: @wcfGapSmall;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul:not(.dropdownMenu) {
|
|
||||||
> li {
|
> li {
|
||||||
margin-top: @wcfGapSmall;
|
&.you {
|
||||||
}
|
a {
|
||||||
}
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
#timsChatUserList {
|
cursor: default;
|
||||||
.timsChatUser {
|
}
|
||||||
> a {
|
|
||||||
background: @wcfContentBackgroundColor;
|
|
||||||
|
|
||||||
img {
|
|
||||||
margin-right: @wcfGapSmall;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.away {
|
a {
|
||||||
opacity: .5;
|
img {
|
||||||
}
|
margin-right: @wcfGapTiny;
|
||||||
|
}
|
||||||
&.suspended a {
|
|
||||||
text-decoration: line-through;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,116 +457,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#timsChatRoomList {
|
#timsChatCopyrightDialog {
|
||||||
> div {
|
> div {
|
||||||
> div {
|
background-repeat: no-repeat;
|
||||||
text-align: center;
|
background-position: right top;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#smilies {
|
#fish {
|
||||||
margin-top: @wcfGapMedium;
|
font-size: 2rem;
|
||||||
|
|
||||||
li {
|
|
||||||
.transition(opacity, .2s);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
li {
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#timsChatOptions {
|
|
||||||
> ul {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#timsChatCopyrightDialog > div {
|
|
||||||
background-position: right center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
min-height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notification {
|
|
||||||
animation-duration: .2s;
|
|
||||||
animation-name: timsChatNotify;
|
|
||||||
animation-iteration-count: 5;
|
|
||||||
animation-direction: alternate;
|
|
||||||
animation-timing-function: linear;
|
|
||||||
border-color: @wcfInputHoverBorderColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 800px) {
|
|
||||||
.timsChatMessage .text li > time, #smilies {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
html.fullscreen {
|
html.fullscreen {
|
||||||
#top {
|
&,
|
||||||
height: 0px;
|
body,
|
||||||
}
|
#tplChat #main,
|
||||||
|
#tplChat #main > div,
|
||||||
height: 100%;
|
#tplChat #main > div > div,
|
||||||
overflow: hidden;
|
#tplChat #content {
|
||||||
|
width: 100%;
|
||||||
#content {
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
-moz-box-sizing: border-box;
|
max-height: 100%;
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
display: -moz-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-moz-box-orient: vertical;
|
|
||||||
-webkit-box-direction: normal;
|
|
||||||
-moz-box-direction: normal;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.timsChatMessageContainer {
|
|
||||||
-webkit-box-flex: 1;
|
|
||||||
-moz-box-flex: 1;
|
|
||||||
-webkit-flex: 1 0 auto;
|
|
||||||
-ms-flex: 1 0 auto;
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#timsChatOptions {
|
#top,
|
||||||
margin-bottom: @wcfGapMedium;
|
#pageHeader,
|
||||||
}
|
#pageFooter {
|
||||||
|
display: none;
|
||||||
#tplChat {
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
#pageHeader, #pageFooter {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main {
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
max-width: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
> div, .sidebar, #sidebarContainer {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,10 @@
|
|||||||
<dd>
|
<dd>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://www.wbbaddons.de/user/2020-noone/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>-noone-</a></li>
|
<li><a href="http://www.wbbaddons.de/user/2020-noone/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>-noone-</a></li>
|
||||||
<li><a href="https://github.com/Gabbid" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Gabi</a></li>
|
<li>Gabi</li>
|
||||||
<li>Alexandra Glass</li>
|
<li>Alexandra Glass</li>
|
||||||
<li><a href="https://github.com/Leon-" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>Stefan Hahn</a></li>
|
<li><a href="https://github.com/Leon-" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>Stefan Hahn</a></li>
|
||||||
<li><a href="https://kittblog.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Matthias Kittsteiner</a></li>
|
<li><a href="http://kittmedia.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Matthias Kittsteiner</a></li>
|
||||||
<li><a href="http://www.wbbaddons.de" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Martin Schwendowius</a></li>
|
<li><a href="http://www.wbbaddons.de" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Martin Schwendowius</a></li>
|
||||||
<li><a href="http://www.cls-design.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Tom</a></li>
|
<li><a href="http://www.cls-design.com/" class="externalURL" {if EXTERNAL_LINK_TARGET_BLANK}target="_blank"{/if}>Tom</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -10,39 +10,44 @@
|
|||||||
(function ($, window) {
|
(function ($, window) {
|
||||||
$(function(){
|
$(function(){
|
||||||
WCF.Language.addObject({
|
WCF.Language.addObject({
|
||||||
'chat.general.query': '{lang}chat.general.query{/lang}',
|
|
||||||
'chat.general.kick': '{lang}chat.general.kick{/lang}',
|
|
||||||
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
'chat.general.ban': '{lang}chat.general.ban{/lang}',
|
||||||
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
|
||||||
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
|
||||||
'chat.general.privateChannelTopic': '{lang}chat.general.privateChannelTopic{/lang}',
|
|
||||||
'chat.general.closePrivateChannel': '{lang}chat.general.closePrivateChannel{/lang}',
|
'chat.general.closePrivateChannel': '{lang}chat.general.closePrivateChannel{/lang}',
|
||||||
'chat.general.closeTopic': '{lang}chat.general.closeTopic{/lang}',
|
'chat.general.closeTopic': '{lang}chat.general.closeTopic{/lang}',
|
||||||
'chat.error.onMessageLoad': '{@"chat.error.onMessageLoad"|language|encodeJS}',
|
'chat.general.notify.title': '{lang}chat.general.notify.title{/lang}',
|
||||||
|
'chat.general.privateChannelTopic': '{lang}chat.general.privateChannelTopic{/lang}',
|
||||||
|
'chat.general.profile': '{lang}chat.general.profile{/lang}',
|
||||||
|
'chat.general.query': '{lang}chat.general.query{/lang}',
|
||||||
|
'chat.general.whisper': '{lang}chat.general.whisper{/lang}',
|
||||||
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
'chat.error.duplicateTab': '{lang}chat.error.duplicateTab{/lang}',
|
||||||
'chat.error.join': '{lang}chat.error.join{/lang}',
|
'chat.error.join': '{lang}chat.error.join{/lang}',
|
||||||
|
'chat.error.onMessageLoad': '{@"chat.error.onMessageLoad"|language|encodeJS}',
|
||||||
'chat.error.reload': '{lang}chat.error.reload{/lang}',
|
'chat.error.reload': '{lang}chat.error.reload{/lang}',
|
||||||
|
'chat.message.{$messageTypes[TYPE_ATTACHMENT]}': '{lang}chat.message.{$messageTypes[TYPE_ATTACHMENT]}{/lang}',
|
||||||
|
'wcf.attachment.insert': '{lang}wcf.attachment.insert{/lang}',
|
||||||
|
'wcf.attachment.delete.sure': '{lang}wcf.attachment.delete.sure{/lang}',
|
||||||
'wcf.attachment.upload.error.invalidExtension': '{lang}wcf.attachment.upload.error.invalidExtension{/lang}',
|
'wcf.attachment.upload.error.invalidExtension': '{lang}wcf.attachment.upload.error.invalidExtension{/lang}',
|
||||||
'wcf.attachment.upload.error.tooLarge': '{lang}wcf.attachment.upload.error.tooLarge{/lang}',
|
'wcf.attachment.upload.error.tooLarge': '{lang}wcf.attachment.upload.error.tooLarge{/lang}',
|
||||||
'wcf.attachment.upload.error.reachedLimit': '{lang}wcf.attachment.upload.error.reachedLimit{/lang}',
|
'wcf.attachment.upload.error.reachedLimit': '{lang}wcf.attachment.upload.error.reachedLimit{/lang}',
|
||||||
'wcf.attachment.upload.error.reachedRemainingLimit': '{lang}wcf.attachment.upload.error.reachedRemainingLimit{/lang}',
|
'wcf.attachment.upload.error.reachedRemainingLimit': '{lang}wcf.attachment.upload.error.reachedRemainingLimit{/lang}',
|
||||||
'wcf.attachment.upload.error.uploadFailed': '{lang}wcf.attachment.upload.error.uploadFailed{/lang}',
|
'wcf.attachment.upload.error.uploadFailed': '{lang}wcf.attachment.upload.error.uploadFailed{/lang}',
|
||||||
'wcf.global.button.upload': '{lang}wcf.global.button.upload{/lang}',
|
'wcf.global.button.upload': '{lang}wcf.global.button.upload{/lang}'
|
||||||
'wcf.attachment.insert': '{lang}wcf.attachment.insert{/lang}',
|
|
||||||
'wcf.attachment.delete.sure': '{lang}wcf.attachment.delete.sure{/lang}',
|
|
||||||
'chat.message.{$messageTypes[TYPE_ATTACHMENT]}': '{lang}chat.message.{$messageTypes[TYPE_ATTACHMENT]}{/lang}'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Boot the chat
|
// Boot the chat
|
||||||
{if MODULE_SMILEY}WCF.TabMenu.init();{/if}
|
|
||||||
{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}
|
{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}
|
||||||
new be.bastelstu.Chat.Attachment();
|
new be.bastelstu.Chat.Attachment();
|
||||||
new be.bastelstu.Chat.Action.Delete('wcf\\data\\attachment\\AttachmentAction', '#timsChatUploadDropdownMenu > li');
|
new be.bastelstu.Chat.Action.Delete('wcf\\data\\attachment\\AttachmentAction', '#timsChatUploadDropdownMenu > li');
|
||||||
{/if}
|
{/if}
|
||||||
new WCF.Message.Smilies();
|
|
||||||
|
WCF.TabMenu.init();
|
||||||
|
|
||||||
|
{if MODULE_SMILEY}
|
||||||
|
new WCF.Message.Smilies();
|
||||||
|
{/if}
|
||||||
|
|
||||||
{capture assign='messageTemplate'}{include application='chat' file='message'}{/capture}
|
{capture assign='messageTemplate'}{include application='chat' file='message'}{/capture}
|
||||||
{capture assign='userTemplate'}{include application='chat' file='userListUser'}{/capture}
|
{capture assign='userTemplate'}{include application='chat' file='userListUser'}{/capture}
|
||||||
|
{capture assign='userMenuTemplate'}{include application='chat' file='userListUserMenu'}{/capture}
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
reloadTime: {@CHAT_RELOADTIME},
|
reloadTime: {@CHAT_RELOADTIME},
|
||||||
@ -58,12 +63,13 @@
|
|||||||
config,
|
config,
|
||||||
new WCF.Template('{literal}{if $newMessageCount}({#$newMessageCount}) {/if}{$title} - {/literal}{"chat.general.title"|language|encodeJS} - {PAGE_TITLE|language|encodeJS}'),
|
new WCF.Template('{literal}{if $newMessageCount}({#$newMessageCount}) {/if}{$title} - {/literal}{"chat.general.title"|language|encodeJS} - {PAGE_TITLE|language|encodeJS}'),
|
||||||
new WCF.Template('{@$messageTemplate|encodeJS}'),
|
new WCF.Template('{@$messageTemplate|encodeJS}'),
|
||||||
new WCF.Template('{@$userTemplate|encodeJS}')
|
new WCF.Template('{@$userTemplate|encodeJS}'),
|
||||||
|
new WCF.Template('{@$userMenuTemplate|encodeJS}')
|
||||||
);
|
);
|
||||||
|
|
||||||
{event name='afterInit'}
|
{event name='afterInit'}
|
||||||
|
|
||||||
$('#timsChatCopyright').click(function (event) {
|
$('#timsChatCopyright a').click(function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (!$.wcfIsset('timsChatCopyrightDialog')) $('<div id="timsChatCopyrightDialog"></div>').appendTo('body');
|
if (!$.wcfIsset('timsChatCopyrightDialog')) $('<div id="timsChatCopyrightDialog"></div>').appendTo('body');
|
||||||
$('#timsChatCopyrightDialog').load('{link application="chat" controller="Copyright"}{/link}').wcfDialog({
|
$('#timsChatCopyrightDialog').load('{link application="chat" controller="Copyright"}{/link}').wcfDialog({
|
||||||
@ -80,78 +86,118 @@
|
|||||||
{capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture}
|
{capture assign='sidebar'}{include application='chat' file='sidebar'}{/capture}
|
||||||
{include file='header' sandbox=false sidebarOrientation='right'}
|
{include file='header' sandbox=false sidebarOrientation='right'}
|
||||||
|
|
||||||
<div id="timsChatTopic" class="marginTop container{if $room->topic|language === ''} empty{/if}">
|
<div class="clearfix">
|
||||||
<span class="icon icon16 icon-remove jsTopicCloser jsTooltip" title="{lang}chat.general.closeTopic{/lang}"></span>
|
<div id="timsChatTopic" class="container containerPadding marginTop{if $room->topic|language === ''} empty{/if}">
|
||||||
<span class="topic">{$room->topic|language}</span>
|
<span id="timsChatTopicCloser" class="icon icon16 icon-remove jsTooltip" title="{lang}chat.general.closeTopic{/lang}"></span>
|
||||||
</div>
|
<span class="topic">{$room->topic|language}</span>
|
||||||
|
</div>
|
||||||
<div id="privateChannelsMenu">
|
|
||||||
<ul>
|
<div id="timsChatMessageTabMenu" class="tabMenuContainer singleTab" data-active="timsChatMessageContainer0">
|
||||||
<li id="privateChannel0" class="privateChannel active" data-private-channel-id="0">
|
<nav class="tabMenu">
|
||||||
<span class="userAvatar framed small">
|
<ul>
|
||||||
<span class="icon icon16 icon-comment-alt jsTooltip" title="{lang}chat.general.room{/lang}"></span>
|
<li>
|
||||||
</span>
|
<a id="timsChatMessageTabMenuAnchor0" href="{$__wcf->getAnchor('timsChatMessageContainer0')}" class="timsChatMessageTabMenuAnchor" data-user-id="0">
|
||||||
<span class="userAvatar framed large">
|
<span class="icon icon16 icon-warning-sign notifyIcon"></span>{*
|
||||||
<span class="icon icon32 icon-comment-alt jsTooltip" title="{lang}chat.general.room{/lang}"></span>
|
*}<span class="userAvatar framed">
|
||||||
</span>
|
<span class="icon icon16 icon-group"></span>
|
||||||
</li>
|
</span>{*
|
||||||
</ul>
|
*}<span>{$room}</span>
|
||||||
</div>
|
</a>
|
||||||
|
|
||||||
<div id="timsChatMessageContainer0" class="timsChatMessageContainer marginTop container active" data-user-id="0">
|
|
||||||
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
|
||||||
<ul>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form id="timsChatForm" action="{link application='chat' controller='Chat' action='Send'}{/link}" method="post">
|
|
||||||
<fieldset>
|
|
||||||
<dl class="wide" id="timsChatInputContainer">
|
|
||||||
<dt>
|
|
||||||
{lang}chat.general.message{/lang}
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
<input id="timsChatInput" accesskey="w" type="text" class="inputText long" name="text" autocomplete="off" maxlength="{@CHAT_MAX_LENGTH}" disabled="disabled" placeholder="{lang}chat.general.submit.default{/lang}" />
|
|
||||||
<small class="innerError" style="display: none;">Lorem ipsum dolor sit amet.</small>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</fieldset>
|
|
||||||
<button type="submit" class="invisible" accesskey="s"></button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{if MODULE_SMILEY && $smileyCategories|count}
|
|
||||||
{include file='messageFormSmilies' wysiwygSelector=''}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<nav id="timsChatOptions" class="marginTop jsMobileNavigation buttonGroupNavigation">
|
|
||||||
<span class="invisible">{lang}chat.general.controls{/lang}</span>
|
|
||||||
<ul class="smallButtons buttonGroup">
|
|
||||||
<li><a id="timsChatAutoscroll" accesskey="d" class="button active timsChatToggle jsTooltip" title="{lang}chat.general.scroll{/lang}" data-status="1"><span class="icon icon16 icon-arrow-down"></span><span class="invisible">{lang}chat.general.scroll{/lang}</span></a></li>{*
|
|
||||||
|
|
||||||
*}<li><a id="timsChatFullscreen" accesskey="f" class="button timsChatToggle jsTooltip" title="{lang}chat.general.fullscreen{/lang}" data-status="0"><span class="icon icon16 icon-fullscreen"></span><span class="invisible">{lang}chat.general.fullscreen{/lang}</span></a></li>{*
|
|
||||||
|
|
||||||
*}<li><a id="timsChatNotify" accesskey="n" class="button timsChatToggle jsTooltip" title="{lang}chat.general.notify{/lang}" data-status="0"><span class="icon icon16 icon-bell-alt"></span><span class="invisible">{lang}chat.general.notify{/lang}</span></a></li>{*
|
|
||||||
|
|
||||||
*}<li{if !MODULE_SMILEY || !$smileyCategories|count} style="display: none;"{/if}><a id="timsChatSmilies" accesskey="e" class="button{if ENABLE_SMILIES_DEFAULT_VALUE} active{/if} timsChatToggle jsTooltip" title="{lang}chat.general.smilies{/lang}" data-status="{@ENABLE_SMILIES_DEFAULT_VALUE}"><span class="icon icon16 icon-smile"></span><span class="invisible">{lang}chat.general.smilies{/lang}</span></a></li>{*
|
|
||||||
|
|
||||||
*}{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}{*
|
|
||||||
*}<li id="timsChatUploadContainer" class="dropdown" data-max-size="{$attachmentHandler->getMaxSize()}">
|
|
||||||
<a id="timsChatUpload" class="dropdownToggle button jsTooltip" title="{lang}wcf.attachment.attachments{/lang}" data-toggle="timsChatUploadContainer">
|
|
||||||
<span class="icon icon16 icon-paper-clip"></span>
|
|
||||||
<span class="invisible">{lang}wcf.attachment.attachments{/lang}</span>
|
|
||||||
</a>
|
|
||||||
<ul id="timsChatUploadDropdownMenu" class="dropdownMenu">
|
|
||||||
<li class="uploadButton" style="margin-top: 0;">
|
|
||||||
<span><label for="timsChatUploadInput">{lang}wcf.global.button.upload{/lang}</label></span>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>{/if}{*
|
</nav>
|
||||||
|
|
||||||
*}<li><a id="timsChatClear" class="button jsTooltip" title="{lang}chat.general.clear{/lang}"><span class="icon icon16 icon-remove"></span><span class="invisible">{lang}chat.general.clear{/lang}</span></a></li>{*
|
<div id="timsChatMessageContainer0" class="tabMenuContent timsChatMessageContainer container containerPadding active" data-user-id="0">
|
||||||
|
<p class="error noJsOnly" style="display: none;">{lang}chat.general.noJs{/lang}</p>
|
||||||
|
<ul></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form id="timsChatForm" action="{link application='chat' controller='Chat' action='Send'}{/link}" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<dl class="wide" id="timsChatInputContainer">
|
||||||
|
<dt>
|
||||||
|
{lang}chat.general.message{/lang}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<input id="timsChatInput" accesskey="w" type="text" class="inputText long" name="text" autocomplete="off" maxlength="{@CHAT_MAX_LENGTH}" disabled="disabled" placeholder="{lang}chat.general.submit.default{/lang}" />
|
||||||
|
<small class="innerError" style="display: none;">Lorem ipsum dolor sit amet.</small>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</fieldset>
|
||||||
|
<button type="submit" class="marginTop invisible" accesskey="s">{lang}wcf.global.button.submit{/lang}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{if MODULE_SMILEY && $smileyCategories|count}
|
||||||
|
{include file='messageFormSmilies' wysiwygSelector=''}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div id="timsChatOptions" class="marginTop">
|
||||||
|
<span id="timsChatSmileyPopupButton" class="button smallButtons">
|
||||||
|
<span class="icon icon16 icon-smile"></span>
|
||||||
|
<span>{lang}chat.general.smilies{/lang}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
*}<li><a id="timsChatMark" class="button timsChatToggle jsTooltip" title="{lang}chat.general.mark{/lang}" data-status="0"><span class="icon icon16 icon-check"></span><span class="invisible">{lang}chat.general.mark{/lang}</span></a></li>
|
<nav class="jsMobileNavigation buttonGroupNavigation">
|
||||||
</ul>
|
<ul class="buttonGroup">
|
||||||
</nav>
|
<li>
|
||||||
|
<a id="timsChatAutoscroll" accesskey="d" class="button active timsChatToggle jsTooltip" title="{lang}chat.general.scroll{/lang}" data-status="1">
|
||||||
|
<span class="icon icon16 icon-arrow-down"></span>
|
||||||
|
<span class="invisible">{lang}chat.general.scroll{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a id="timsChatFullscreen" accesskey="f" class="button timsChatToggle jsTooltip" title="{lang}chat.general.fullscreen{/lang}" data-status="0">
|
||||||
|
<span class="icon icon16 icon-fullscreen"></span>
|
||||||
|
<span class="invisible">{lang}chat.general.fullscreen{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a id="timsChatNotify" accesskey="n" class="button timsChatToggle jsTooltip" title="{lang}chat.general.notify{/lang}" data-status="0">
|
||||||
|
<span class="icon icon16 icon-bell-alt"></span>
|
||||||
|
<span class="invisible">{lang}chat.general.notify{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{if MODULE_SMILEY && $smileyCategories|count}
|
||||||
|
<li>
|
||||||
|
<a id="timsChatSmilies" accesskey="e" class="button{if ENABLE_SMILIES_DEFAULT_VALUE} active{/if} timsChatToggle jsTooltip" title="{lang}chat.general.smilies{/lang}" data-status="{@ENABLE_SMILIES_DEFAULT_VALUE}">
|
||||||
|
<span class="icon icon16 icon-smile"></span>
|
||||||
|
<span class="invisible">{lang}chat.general.smilies{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{if MODULE_ATTACHMENT && $__wcf->session->getPermission('user.chat.canUploadAttachment')}
|
||||||
|
<li id="timsChatUploadContainer" class="dropdown" data-max-size="{$attachmentHandler->getMaxSize()}">
|
||||||
|
<a id="timsChatUpload" class="dropdownToggle button jsTooltip" title="{lang}wcf.attachment.attachments{/lang}" data-toggle="timsChatUploadContainer">
|
||||||
|
<span class="icon icon16 icon-paper-clip"></span>
|
||||||
|
<span class="invisible">{lang}wcf.attachment.attachments{/lang}</span>
|
||||||
|
</a>
|
||||||
|
<ul id="timsChatUploadDropdownMenu" class="dropdownMenu">
|
||||||
|
<li class="uploadButton" style="margin-top: 0;">
|
||||||
|
<span><label for="timsChatUploadInput" class="pointer">{lang}wcf.global.button.upload{/lang}</label></span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a id="timsChatClear" class="button jsTooltip" title="{lang}chat.general.clear{/lang}">
|
||||||
|
<span class="icon icon16 icon-remove"></span>
|
||||||
|
<span class="invisible">{lang}chat.general.clear{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a id="timsChatMark" class="button timsChatToggle jsTooltip" title="{lang}chat.general.mark{/lang}" data-status="0">
|
||||||
|
<span class="icon icon16 icon-check"></span>
|
||||||
|
<span class="invisible">{lang}chat.general.mark{/lang}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{include file='footer' sandbox=false}
|
{include file='footer' sandbox=false}
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{literal}
|
{literal}
|
||||||
{if $message.type == $messageTypes.LEAVE || $message.type == $messageTypes.JOIN}
|
{if $message.type == $messageTypes.JOIN || $message.type == $messageTypes.LEAVE}
|
||||||
<div class="messageIcon">
|
<div class="timsChatMessageIcon">
|
||||||
<span class="icon icon16 icon-{if $message.type == $messageTypes.LEAVE}signout{elseif $message.type == $messageTypes.JOIN}signin{/if}"></span>
|
<span class="icon icon16 icon-{if $message.type == $messageTypes.JOIN}signin{else}signout{/if}"></span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="innerMessageContainer{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.INFORMATION || $message.type == $messageTypes.ATTACHMENT} bubble{/if}{if $message.type == $messageTypes.WHISPER && $message.sender != $__wcf.User.userID} right{/if}">
|
<div class="timsChatInnerMessageContainer{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.INFORMATION || $message.type == $messageTypes.ATTACHMENT} bubble{/if}{if $message.type == $messageTypes.WHISPER && $message.sender != $__wcf.User.userID} right{/if}">
|
||||||
<div class="avatarContainer">
|
<div class="timsChatAvatarContainer">
|
||||||
<div class="userAvatar{if $message.type != $messageTypes.INFORMATION} framed{/if}">
|
<div class="userAvatar framed">
|
||||||
{if $message.type != $messageTypes.INFORMATION}
|
{if $message.type != $messageTypes.INFORMATION}
|
||||||
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.ATTACHMENT}
|
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.ATTACHMENT}
|
||||||
{@$message.avatar[32]}
|
{@$message.avatar[32]}
|
||||||
@ -18,46 +18,38 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{if $message.type == $messageTypes.ATTACHMENT}
|
{if $message.type == $messageTypes.ATTACHMENT}
|
||||||
<small class="framed avatarExtra">
|
<small class="framed timsChatAvatarExtraIcon">
|
||||||
<span class="icon icon16 icon-paperclip"></span>
|
<span class="icon icon16 icon-paperclip"></span>
|
||||||
</small>
|
</small>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="innerMessage">
|
<div class="timsChatInnerMessage">
|
||||||
<span class="username">
|
<span class="timsChatUsernameContainer">
|
||||||
{if ($message.type == $messageTypes.WHISPER && $message.sender == WCF.User.userID) || $message.type != $messageTypes.WHISPER}
|
|
||||||
{@$message.formattedUsername}
|
{@$message.formattedUsername}
|
||||||
{else}
|
|
||||||
{$message.additionalData.receiverUsername}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{if $message.type == $messageTypes.WHISPER}
|
{if $message.type == $messageTypes.WHISPER}
|
||||||
<span class="icon icon16 icon-double-angle-{if $message.sender == WCF.User.userID}right{else}left{/if} jsTooltip" title="{/literal}{lang}chat.ui.whispers{/lang}{literal}" onclick="be.bastelstu.Chat.insertText('/whisper {if $message.receiver == WCF.User.userID}{$message.username.replace("\\", "\\\\").replace("'", "\\'")}{else}{$message.additionalData.receiverUsername.replace("\\", "\\\\").replace("'", "\\'")}{/if}, ', { append: false });"></span>
|
<span class="icon icon16 icon-double-angle-right jsTooltip" title="{/literal}{lang}chat.general.whisper{/lang}{literal}" onclick="be.bastelstu.Chat.insertText('/whisper {if $message.receiver == WCF.User.userID}{$message.username.replace("\\", "\\\\").replace("'", "\\'")}{else}{$message.additionalData.receiverUsername.replace("\\", "\\\\").replace("'", "\\'")}{/if}, ', { append: false });"></span>
|
||||||
{if ($message.type == $messageTypes.WHISPER && $message.sender == WCF.User.userID) || $message.type != $messageTypes.WHISPER}
|
<span class="reciever">{$message.additionalData.receiverUsername}</span>
|
||||||
{$message.additionalData.receiverUsername}
|
|
||||||
{else}
|
|
||||||
{@$message.formattedUsername}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<time>{@$message.formattedTime}</time>
|
<time>{@$message.formattedTime}</time>
|
||||||
|
|
||||||
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.ATTACHMENT}
|
{if $message.type == $messageTypes.NORMAL || $message.type == $messageTypes.WHISPER || $message.type == $messageTypes.ATTACHMENT}
|
||||||
{if $message.type == $messageTypes.ATTACHMENT}<span>{lang}chat.message.{$messageTypes.ATTACHMENT}{/lang}</span>{/if}
|
{if $message.type == $messageTypes.ATTACHMENT}<span>{lang}chat.message.{$messageTypes.ATTACHMENT}{/lang}</span>{/if}
|
||||||
<ul class="text">
|
<ul class="timsChatText">
|
||||||
<li>
|
<li>
|
||||||
{if $message.isFollowUp} <time>{@$message.formattedTime}</time>{/if}
|
{if $message.isFollowUp} <time>{@$message.formattedTime}</time>{/if}
|
||||||
{@$message.formattedMessage}
|
{@$message.formattedMessage}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{elseif $message.type == $messageTypes.INFORMATION}
|
{elseif $message.type == $messageTypes.INFORMATION}
|
||||||
<div class="text">{@$message.formattedMessage}</div>
|
<div class="timsChatText">{@$message.formattedMessage}</div>
|
||||||
{else}
|
{else}
|
||||||
<span class="text">{@$message.formattedMessage}</span>
|
<span class="timsChatText">{@$message.formattedMessage}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<span class="markContainer">
|
<span class="timsChatMarkContainer">
|
||||||
<input type="checkbox" value="{@$message.messageID}" />
|
<input type="checkbox" value="{@$message.messageID}" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,29 +1,19 @@
|
|||||||
<div class="tabMenuContainer chatTabMenuContainer containerPadding">
|
<fieldset id="timsChatUserListContainer">
|
||||||
<nav class="menu chatSidebarMenu">
|
<legend>{lang}chat.general.users{/lang}</legend>
|
||||||
<ul>
|
<div id="timsChatUserList">
|
||||||
<li id="toggleUsers" class="ui-state-active"><a href="{@$__wcf->getAnchor('timsChatUserList')}" title="{lang}chat.general.users{/lang}">{lang}chat.general.users{/lang} <span class="badge">0</span></a></li>
|
<ul class="sidebarNestedCategoryList">
|
||||||
<li id="toggleRooms"><a href="{@$__wcf->getAnchor('timsChatRoomList')}" title="{lang}chat.general.rooms{/lang}">{lang}chat.general.rooms{/lang} <span class="badge">0</span></a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</div>
|
||||||
|
</fieldset>
|
||||||
<section id="sidebarContent" class="tabMenuContent">
|
<fieldset id="timsChatRoomListContainer">
|
||||||
<fieldset>
|
<legend>{lang}chat.general.rooms{/lang}</legend>
|
||||||
<nav id="timsChatUserList">
|
<div id="timsChatRoomList">
|
||||||
<ul>
|
<ul class="sidebarNestedCategoryList">
|
||||||
</ul>
|
|
||||||
</nav>
|
</ul>
|
||||||
</fieldset>
|
</div>
|
||||||
|
<div class="marginTop">
|
||||||
<fieldset>
|
<a id="timsChatRoomListReloadButton" class="button small jsOnly">{lang}chat.general.forceRefresh{/lang}</a>
|
||||||
<nav id="timsChatRoomList" style="display: none;">
|
</div>
|
||||||
<div>
|
</fieldset>
|
||||||
<ul>
|
|
||||||
</ul>
|
|
||||||
<div class="marginTop">
|
|
||||||
<button type="button">{lang}chat.general.forceRefresh{/lang}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</fieldset>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
@ -1 +1 @@
|
|||||||
{literal}<a{if $userID != $__wcf.User.userID} class="dropdownToggle"{/if} data-user-id="{$userID.toString()}">{@$avatar['24']}{$username}</a>{/literal}
|
{literal}<a{if $userID != $__wcf.User.userID} class="dropdownToggle"{/if} data-user-id="{$userID.toString()}"><span class="framed">{@$avatar['24']}</span>{$username}</a>{/literal}
|
||||||
|
8
template/userListUserMenu.tpl
Normal file
8
template/userListUserMenu.tpl
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{literal}
|
||||||
|
<ul data-user-id="{$userID}">
|
||||||
|
<li><a class="jsTimsChatUserMenuWhisper">{lang}chat.general.whisper{/lang}</a></li>
|
||||||
|
<li><a class="jsTimsChatUserMenuQuery">{lang}chat.general.query{/lang}</a></li>
|
||||||
|
<li><a class="jsTimsChatUserMenuBan">{lang}chat.general.ban{/lang}</a></li>
|
||||||
|
<li><a href="{$link}" class="userLink" data-user-id="{$userID}">{lang}chat.general.profile{/lang}</a></li>
|
||||||
|
</ul>
|
||||||
|
{/literal}
|
Loading…
Reference in New Issue
Block a user