Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Initial work on context menus #613

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions client/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ button, .user {
top: 2px;
right: 3px;
}
#sidebar, #footer {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#footer {
background: rgba(0, 0, 0, .06);
border-radius: 2px;
Expand Down Expand Up @@ -982,6 +988,57 @@ button, .user {
width: 58px;
}

#context-menu-container {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background: transparent;
}
#context-menu {
position: absolute;
list-style: none;
margin: 0;
padding: 0;
min-width: 160px;
font-size: 14px;
background-color: #fff;
box-shadow: 0px 1px 2px rgba(0,0,0,0.1);
border: 1px solid rgba(61,70,77,0.1);
}

.context-menu-item:first-child {
border-bottom: 1px solid rgba(61,70,77,0.1);
}
.context-menu-item {
cursor: pointer;
display: block;
padding: 6px 8px;
color: #333;
}
.context-menu-item:hover {
background-color: #e3f2ff;
}
.context-menu-item:before {
font-family: FontAwesome;
width: 20px;
display: inline-block;
}
.context-menu-user:before {
content: "\f007";
}
.context-menu-chan:before {
content: "\f0f6";
}
.context-menu-close:before {
content: "\f057";
}
.context-menu-settings:before {
content: "\f013";
}

/**
* IRC Message Styling
Expand Down
4 changes: 4 additions & 0 deletions client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ <h2>About Shout</h2>
</div>
</div>

<div id="context-menu-container">
<ul id="context-menu"></ul>
</div>

<script src="js/libs.min.js"></script>
<script src="js/shout.templates.js"></script>
<script src="js/shout.js"></script>
Expand Down
89 changes: 89 additions & 0 deletions client/js/shout.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,8 @@ $(function() {
});

var viewport = $("#viewport");
var contextMenuContainer = $("#context-menu-container");
var contextMenu = $("#context-menu");

viewport.on("click", ".lt, .rt", function(e) {
var self = $(this);
Expand All @@ -475,6 +477,70 @@ $(function() {
}
});

function positionContextMenu(e) {
var top, left;
var menuWidth = contextMenu.offsetWidth + 4;
var menuHeight = contextMenu.offsetHeight + 4;

if ((window.innerWidth - e.pageX) < menuWidth) {
left = window.innerWidth - menuWidth;
} else {
left = e.pageX;
}

if ((window.innerHeight - e.pageY) < menuHeight) {
top = window.innerHeight - menuHeight;
} else {
top = e.pageY;
}

return {left: left, top: top};
}

viewport.on("contextmenu", ".user, .network .chan", function(e) {
var target = $(e.currentTarget);
var output = "";

if (target.hasClass("user")) {
output = render("contextmenu_item", {
class: "user",
text: target.text(),
data: target.data("name")
});
}
else if (target.hasClass("chan")) {
output = render("contextmenu_item", {
class: "chan",
text: target.data("title"),
data: target.data("target")
});
if (target.hasClass("channel")) {
output += render("contextmenu_item", {
class: "settings",
text: "Settings",
data: target.data("target")
});
}
output += render("contextmenu_item", {
class: "close",
text: target.hasClass("lobby") ? "Disconnect" : target.hasClass("query") ? "Close" : "Leave",
data: target.data("target")
});
}

contextMenu
.html(output)
.css(positionContextMenu(e));
contextMenuContainer.show();

return false;
});

contextMenuContainer.on("mousedown", function() {
contextMenuContainer.hide();
return false;
});

var input = $("#input")
.history()
.tab(complete, {hint: false});
Expand Down Expand Up @@ -603,6 +669,23 @@ $(function() {
return false;
});

contextMenu.on("click", ".context-menu-item", function() {
switch ($(this).data("action")) {
case "close":
$(".networks .chan[data-target=" + $(this).data("data") + "] .close").click();
break;
case "chan":
$(".networks .chan[data-target=" + $(this).data("data") + "]").click();
break;
case "user":
$(".channel.active .users .user[data-name=" + $(this).data("data") + "]").click();
break;
case "settings":
alert("Not yet supported!");
break;
}
});

chat.on("input", ".search", function() {
var value = $(this).val().toLowerCase();
var names = $(this).closest(".users").find(".names");
Expand Down Expand Up @@ -813,6 +896,12 @@ $(function() {
}
});

Mousetrap.bind([
"escape"
], function() {
contextMenuContainer.hide();
});

setInterval(function() {
chat.find(".chan:not(.active)").each(function() {
var chan = $(this);
Expand Down
25 changes: 24 additions & 1 deletion client/js/shout.templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,31 @@ templates['chat'] = template({"1":function(depth0,helpers,partials,data) {
if (stack1 != null) { buffer += stack1; }
return buffer;
},"useData":true});
templates['contextmenu_item'] = template({"1":function(depth0,helpers,partials,data) {
var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression;
return " data-data=\""
+ escapeExpression(((helper = (helper = helpers.data || (depth0 != null ? depth0.data : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"data","hash":{},"data":data}) : helper)))
+ "\"";
},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "<li class=\"context-menu-item context-menu-"
+ escapeExpression(((helper = (helper = helpers['class'] || (depth0 != null ? depth0['class'] : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"class","hash":{},"data":data}) : helper)))
+ "\" data-action=\""
+ escapeExpression(((helper = (helper = helpers['class'] || (depth0 != null ? depth0['class'] : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"class","hash":{},"data":data}) : helper)))
+ "\"";
stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.data : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data});
if (stack1 != null) { buffer += stack1; }
return buffer + ">\n "
+ escapeExpression(((helper = (helper = helpers.text || (depth0 != null ? depth0.text : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"text","hash":{},"data":data}) : helper)))
+ "\n</li>\n";
},"useData":true});
templates['msg'] = template({"1":function(depth0,helpers,partials,data) {
return "self";
},"3":function(depth0,helpers,partials,data) {
var helper, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, functionType="function";
return " <a href=\"#\" class=\"user\" style=\"color: #"
+ escapeExpression(((helpers.stringcolor || (depth0 && depth0.stringcolor) || helperMissing).call(depth0, (depth0 != null ? depth0.from : depth0), {"name":"stringcolor","hash":{},"data":data})))
+ "\" data-name=\""
+ escapeExpression(((helper = (helper = helpers.from || (depth0 != null ? depth0.from : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"from","hash":{},"data":data}) : helper)))
+ "\">"
+ escapeExpression(((helper = (helper = helpers.mode || (depth0 != null ? depth0.mode : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"mode","hash":{},"data":data}) : helper)))
+ escapeExpression(((helper = (helper = helpers.from || (depth0 != null ? depth0.from : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"from","hash":{},"data":data}) : helper)))
Expand Down Expand Up @@ -125,7 +144,9 @@ templates['msg_action'] = template({"1":function(depth0,helpers,partials,data) {
if (stack1 != null) { buffer += stack1; }
buffer += "\">\n <span class=\"time\">\n "
+ escapeExpression(((helpers.tz || (depth0 && depth0.tz) || helperMissing).call(depth0, (depth0 != null ? depth0.time : depth0), {"name":"tz","hash":{},"data":data})))
+ "\n </span>\n <span class=\"from\"></span>\n <span class=\"text\">\n <a href=\"#\" class=\"user\">"
+ "\n </span>\n <span class=\"from\"></span>\n <span class=\"text\">\n <a href=\"#\" class=\"user\" data-name=\""
+ escapeExpression(((helper = (helper = helpers.from || (depth0 != null ? depth0.from : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"from","hash":{},"data":data}) : helper)))
+ "\">"
+ escapeExpression(((helper = (helper = helpers.mode || (depth0 != null ? depth0.mode : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"mode","hash":{},"data":data}) : helper)))
+ escapeExpression(((helper = (helper = helpers.from || (depth0 != null ? depth0.from : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"from","hash":{},"data":data}) : helper)))
+ "</a>\n "
Expand Down Expand Up @@ -201,6 +222,8 @@ templates['user'] = template({"1":function(depth0,helpers,partials,data) {
if (stack1 != null) { buffer += stack1; }
return buffer + " <button class=\"user\" style=\"color: #"
+ escapeExpression(((helpers.stringcolor || (depth0 && depth0.stringcolor) || helperMissing).call(depth0, (depth0 != null ? depth0.name : depth0), {"name":"stringcolor","hash":{},"data":data})))
+ "\" data-name=\""
+ escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper)))
+ "\">"
+ escapeExpression(((helper = (helper = helpers.mode || (depth0 != null ? depth0.mode : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"mode","hash":{},"data":data}) : helper)))
+ escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper)))
Expand Down
3 changes: 3 additions & 0 deletions client/views/contextmenu_item.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<li class="context-menu-item context-menu-{{class}}" data-action="{{class}}"{{#if data}} data-data="{{data}}"{{/if}}>
{{text}}
</li>
2 changes: 1 addition & 1 deletion client/views/msg.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</span>
<span class="from">
{{#if from}}
<a href="#" class="user" style="color: #{{stringcolor from}}">{{mode}}{{from}}</a>
<a href="#" class="user" style="color: #{{stringcolor from}}" data-name="{{from}}">{{mode}}{{from}}</a>
{{/if}}
</span>
<span class="text">
Expand Down
2 changes: 1 addition & 1 deletion client/views/msg_action.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</span>
<span class="from"></span>
<span class="text">
<a href="#" class="user">{{mode}}{{from}}</a>
<a href="#" class="user" data-name="{{from}}">{{mode}}{{from}}</a>
{{formattedAction}}
{{{parse text}}}
</span>
Expand Down
2 changes: 1 addition & 1 deletion client/views/user.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{{/unless}}
<div class="user-mode {{modes mode}}">
{{/diff}}
<button class="user" style="color: #{{stringcolor name}}">{{mode}}{{name}}</button>
<button class="user" style="color: #{{stringcolor name}}" data-name="{{name}}">{{mode}}{{name}}</button>
{{/each}}
</div>
</div>
Expand Down