I am using JWplayer 7 (HTML5 render mode) in my site.
I created a player with custom playlist, but cannot highlight current playing video when it has been clicked.
Is there any solution to add a custom class, like .active when click on a item of list.
This is my code to setup JWplayer.
var playerInstance = jwplayer("videoCont");
playerInstance.setup({
image: "{PLAYLIST_IMAGE}",
autostart: false,
aspectratio: "16:9",
playlist : "{NV_BASE_SITEURL}{MODULE_NAME}/player/{RAND_SS}{PLAYLIST_ID}-{PLIST_CHECKSS}-{RAND_SS}{FAKE_ID}/",
controls: true,
displaydescription: true,
displaytitle: true,
flashplayer: "{NV_BASE_SITEURL}themes/default/modules/{MODULE_NAME}/jwplayer/jwplayer.flash.swf",
primary: "html5",
repeat: false,
skin: {"name": "stormtrooper"},
stagevideo: false,
stretching: "uniform",
visualplaylist: true,
width: "100%"
});
And following code to generate custom player
var list = document.getElementById("show-list");
var html = list.innerHTML;
html +="<ul class='list-group'>"
playerInstance.on('ready',function(){
var playlist = playerInstance.getPlaylist();
for (var index=0;index<playlist.length;index++){
var playindex = index +1;
html += "<li class='list-group-item'><span>"+playlist[index].title+"</span><span class='pull-right'><label onclick='javascript:playThis("+index+")' title='Phát "+playlist[index].title+"' class='btn btn-default btn-xs'><i class='fa fa-play'></i></label><label class='btn btn-default btn-xs' href='"+playlist[index].link+"' title='Xem ở cửa sổ mới' target='_blank'><i class='fa fa-external-link-square'></i></label></span></li>"
list.innerHTML = html;
}
html +="</ul>"
});
function playThis(index) {
playerInstance.playlistItem(index);
}
SOLUTION : Based on an idea of #zer00ne
Add following code :
playerInstance.on('playlistItem', function() {
var playlist = playerInstance.getPlaylist();
var index = playerInstance.getPlaylistIndex();
var current_li = document.getElementById("play-items-"+index);
for(var i = 0; i < playlist.length; i++) {
$('li[id^=play-items-]').removeClass( "active" )
}
current_li.classList.add('active');
});
before
function playThis(index) {
playerInstance.playlistItem(index);
}
And edit html generate like this :
html += "<li id='play-items-"+index+"' class='list-group-item'><span>"+playlist[index].title+"</span><span class='pull-right'><label onclick='javascript:playThis("+index+")' title='"+lang_play+" "+playlist[index].title+"' class='btn btn-primary btn-xs mgr_10'><i class='fa fa-play'></i></label><a href='"+playlist[index].link+"' title='"+lang_new_window+"' target='_blank'><label class='btn btn-default btn-xs'><i class='fa fa-external-link-square'></i></label></a></span></li>"
With adding id='play-items-"+index+"' to identify unique class for each item of list.
Thanks for idea of #zer00ne !
Your code not total works with my site but it give a solution.
playerInstance.on('playlistItem', function() {
var playlist = playerInstance.getPlaylist();
var index = playerInstance.getPlaylistIndex();
var current_li = document.getElementById("play-items-"+index);
for(var i = 0; i < playlist.length; i++) {
$('li[id^=play-items-]').removeClass( "active" )
}
current_li.classList.add('active');
});
This code will remove all "active" from each li element and find the ID is correct with current playing Index, then add "active" class.
UPDATE
Firefox has a problem with li[i], since it's a HTMLCollection (nodeList) and not live coming from querySelectorAll(). One extra step needs to be added in order to convert li[i] to a true Array. The update involves a function called nodeList2Array(sel).
UPDATE
I misinterpreted the OP's request:
Is there any solution to add a custom class, like .active when click on a item of list.
So what is needed is manipulation of the generated <li>s of the custom playlist.
SOLUTION
Add this after the the rest of the script:
jw.on('playlistItem', function() {
var playlist = jw.getPlaylist();
var idx = jw.getPlaylistIndex();
//var li = document.querySelectorAll('.group-list-item');
var li = nodeList2Array('.group-list-item');
for(var i = 0; i < playlist.length; i++) {
if(i === idx) {
li[i].classList.add('active');
}
else {
li[i].classList.remove('active');
}
}
});
function nodeList2Array(sel) {
var li = Array.prototype.slice.call(document.querySelectorAll(sel));
return li;
}
DEMO
!!!IMPORTANT PLEASE READ THIS!!!
The following demo DEFINITELY WORKS, but you need to enter your own key in order for it to function. JW7 does not have a free version like JW6 does.
var jw = jwplayer("media1");
jw.setup({
playlist: "https://content.jwplatform.com/feeds/13ShtP5m.rss",
displaytitle: false,
width: 680,
height: 360
});
var list = document.querySelector(".group-list");
var html = list.innerHTML;
jw.on('ready', function() {
var playlist = jw.getPlaylist();
for (var idx = 0; idx < playlist.length; idx++) {
html += "<li class='group-list-item' title='" + playlist[idx].title + "'><a href='javascript:playThis(" + idx + ");'><img height='75' width='120' src='" + playlist[idx].image + "'><figcaption>" + playlist[idx].title + "</figcaption></a></li>";
list.innerHTML = html;
}
});
//SOLUTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
jw.on('playlistItem', function() {
var playlist = jw.getPlaylist();
var idx = jw.getPlaylistIndex();
var li = document.querySelectorAll('.group-list-item');
for (var i = 0; i < playlist.length; i++) {
if (i === idx) {
li[i].classList.add('active');
} else {
li[i].classList.remove('active');
}
}
});
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function playThis(idx) {
jw.playlistItem(idx);
}
html {
box-sizing: border-box;
font: 400 16px/2 small-caps"Trebuchet MS";
height: 100vh;
width: 100vw;
}
*,
*:before,
*:after {
box-sizing: inherit;
margin: 0;
padding: 0;
border: 0 solid transparent;
outline: 0;
text-indent: 0;
}
body {
height: 100%;
width: 100%;
background: #000;
color: #FFF;
position: relative;
}
#main {
margin: auto;
width: 680px;
}
#frame1 {
position: absolute;
top: 12.5%;
left: 25%;
}
.jwp {
position: relative;
}
.group-list {
position: relative;
list-style-type: none;
list-style-position: inside;
}
.group-list li {
list-style: none;
display: inline-block;
float: left;
padding: 15px 0 0 11px;
line-height: 2;
}
.group-list a {
text-decoration: none;
display: inline-block;
background: #000;
border: 1px solid #666;
border-radius: 8px;
height: 75px;
width: 120px;
text-align: center;
}
.group-list a:hover,
.group-list a:active {
border: 1px solid #ff0046;
border-radius: 8px;
color: #FFF;
background: hsla(180, 60%, 50%, .4);
}
img {
display: block;
}
.active {
background: hsla(180, 60%, 50%, .4);
outline: 3px solid #0FF;
}
.active figcaption {
color: #000;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JWplayer 7 - Add active class to current playing video</title>
<meta name="SO33252950" content="http://stackoverflow.com/questions/33252950/jwplayer-7-add-active-class-to-current-playing-video">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://d1jtvmpy1cspce.cloudfront.net/lib/jw/7/jwplayer.js"></script>
<script>
jwplayer.key = "/*........::::::45_Alphanumerics::::::........*/"
</script>
</head>
<body>
<main id="main">
<section id="frame1" class="frame">
<div id="media1" class="jwp">Loading...</div>
<ul id="list1" class="group-list"></ul>
</section>
</main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
OLD
Sure it's possible to add a class such as .active then apply styles that way, but JW7 has extensive CSS Skin documentation. I styled the skin using the technique detailed here:
http://support.jwplayer.com/customer/en/portal/articles/2092249-sample-css-file
DEMO
https://glpro.s3.amazonaws.com/_util/smpte/jwp.html
/* Allows you to adjust the color of the playlist item when hovering and has a different active style.*/
.jw-skin-stormtrooper .jw-playlist-container .jw-option:hover,
.jw-skin-stormtrooper .jw-playlist-container .jw-option.jw-active-option {
background-color: hsla(210,100%,20%,1);
}
/* Changes the color of the label when hovering.*/
.jw-skin-stormtrooper .jw-playlist-container .jw-option:hover .jw-label {
color: #0080ff;
}
/* Sets the color of the play icon of the currently playing playlist item.*/
.jw-skin-stormtrooper .jw-playlist-container .jw-label .jw-icon-play {
color: #0080ff;
}
/* Sets the color of the playlist title */
.jw-skin-stormtrooper .jw-tooltip-title {
background-color: #000;
color: #fff
}
/* Style for playlist item, current time, qualities, and caption text.*/
.jw-skin-stormtrooper .jw-text {
color: #aed4ff;
}
/* Color for all buttons when they are inactive. This is over-ridden with the
inactive configuration in the skin block.*/
.jw-skin-stormtrooper .jw-button-color {
color: #cee2ec;
}
/* Color for all buttons for when they are hovered on. This is over-ridden with the
active configuration in the skin block.*/
.jw-skin-stormtrooper .jw-button-color:hover {
color: #00e;
}
/* Color for when HD/CD icons are toggled on. */
.jw-skin-stormtrooper .jw-toggle {
color: #0080ff;
}
/* Color for when HD/CD icons are toggled off. */
.jw-skin-stormtrooper .jw-toggle.jw-off {
color: #ffffff;
}
I want to add two arrows to the sides of the "boxes" divs (below) to cycle through the 3 divs.
Working JSFiddle: https://jsfiddle.net/HBHcC/11/
Can someone help me with this?
HTML:
<div class="container">
<div class="boxes">
<div class="one box">
</div>
<div class="two box">
</div>
<div class="three box">
</div>
</div>
</div>
CSS:
.container{
width:100px;
height:100px;
overflow:hidden;
position:relative;
}
.box {
display:inline-block;
float: left;
width: 100px;
height: 100px;
}
.one{
background-color:green;
}
.two{
background-color:red;
}
.three{
background-color:blue;
}
.boxes{
width:400px;
}
JS:
$(document).ready(function(){
$('.box').on("click", function() {
// Is this the last div, or is there a next one?
if ($(this).next().length) {
var animSpeed = 200; // Make this 0 for an instant change
$('.boxes').animate({marginLeft : "-=100"}, animSpeed);
}
});
});
After adding arrows to the div, here is a new fiddle that should get you started:
$('.rightarrow').on("click", function() {
// Is this the last div, or is there a next one?
var animSpeed = 200; // Make this 0 for an instant change
$('.boxes').animate({marginLeft : "-=100"}, animSpeed);
});
$('.leftarrow').on("click", function() {
// Is this the last div, or is there a next one?
var animSpeed = 200; // Make this 0 for an instant change
$('.boxes').animate({marginLeft : "+=100"}, animSpeed);
});
https://jsfiddle.net/tx2yg06w/1/
Updated w/arrows moved out of divs:
$(document).ready(function(){
var animSpeed = 200;
$('.rightarrow').on("click", function() {
if(parseInt($("#boxes").css("marginLeft")) == -200){ return;}
$('.boxes').animate({marginLeft : "-=100"}, animSpeed);
});
$('.leftarrow').on("click", function() {
if(parseInt($("#boxes").css("marginLeft")) == 0){ return;}
$('.boxes').animate({marginLeft : "+=100"}, animSpeed);
});
});
https://jsfiddle.net/b56r0d72/
Errata has given you a good solution. Just wire up his code to the arrows in the snippet below.
Run snippet to view:
<html>
<body>
<style type="text/css">
.leftarrow, .rightarrow {
font-size: 48px;
color: blue;
text-decoration: none;
}
.rightarrow {
color: red;
float: right;
}
.content {
width: 200px;
padding: 4px;
border: 1px gray solid;
}
.box {
height: 200px;
border: 1px green solid;
}
</style>
<div class="content">
<div>
◀
▶
</div>
<div class="box">slide</div>
</div>
</body>
</html>
I'm trying to simulate an animate effect via jQuery that consists drag and drop as events to be fired. The code I use seems to be fine until the point when I have to swap divs by setting their display to none/block. Whenever I swap to the first div it perfectly executes the animation but when it gets on the 2nd div (after swapped) it doesn't fire the droppable event. I chose to have id selectors for the respective divs to instance the container of the droppable event hence to animate. I'm stuck and are out of any solution after searching numerous results so far. Thank you in advance. Here is my JS fiddle I prepared to easily understand my problem.
<html>
<head>
<style>
#wrapper {
border: 1px solid gray;
height:300px;
margin: 0 auto;
padding: 20px 20px 20px 20px;
position:relative;
text-align:center;
width:600px;
}
p {
display:inline;
font-family:Calibri;
font-size:20px;
color: #0b1207;
text-shadow: #63c9b8 0px 10px 10px;
}
#div1, #div2 {
border: 1px dotted green;
bottom:0;
margin-left:100px;
position: absolute;
}
#div1 {
background-color: orange;
height:200px;
width:300px;
}
#div2 {
background-color: green;
display:none;
height:100px;
width:300px;
}
#btnchange {
background-color:black;
border-radius:10px;
color: #fff;
height:35px;
margin-top:10px;
margin-left:100px;
position:absolute;
width:80px;
}
.example {
border: 1px solid red;
background-color: blue;
height:75px;
margin: 5px auto 0 ;
width:75px;
}
</style>
</head>
<body>
<div id='wrapper'>
<p></p>
<div id='div1'></div>
<div id='div2'></div>
</div>
<button id ='btnchange' type='button'>Change</button>
<div class='example'></div>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script src="http://biostall.com/wp-content/uploads/2010/07/jquery-swapsies.js"></script>
<script type="text/javascript">
var id = 1;
var parent = document.getElementById('wrapper');
var makina = parent.children[id].id;
$(function(){
$( "#draggable" ).draggable({
connectToSortable: "#sortable",
helper: "clone",
revert: "invalid"
});
$('.example').draggable({
containtment: "#" + makina,
cursor: "pointer",
revert: true
});
$('#btnchange').click(function(){
if (id == 1)
{
document.getElementById(makina).style.display = 'none';
id = 2;
makina = parent.children[id].id;
document.getElementById(makina).style.display = 'block';
document.getElementById('wrapper').children[0].innerText = makina;
}
else
{
document.getElementById(makina).style.display = 'none';
id = 1;
makina = parent.children[id].id;
document.getElementById(makina).style.display = 'block';
document.getElementById('wrapper').children[0].innerText = makina;
}
console.log(makina);
});
$("#" + makina).droppable({
drop: function(){
doAnimate(makina);}
});
});
function doAnimate(container)
{
$('#'+ container).animate({height: '+=10px'}, 500, function(){
var message = container.clientHeight;
$(this).html(message);
});
}
</script>
</body>
</html>
http://jsfiddle.net/xoxxbr4t/6/
Your problem is you were only calling droppable once, on only one of the items. Once the .droppable() function is also put inside the change button click, it should work.
put this inside change function:
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
example:
http://jsfiddle.net/xoxxbr4t/7/
You aren't binding droppable to your second element. You call this function once:
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
Since your "makina" at this point is div1, that's the only thing that gets bound. I made that it's own function:
function setDroppable(makina) {
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
}
And then called it for both divs in your setup:
setDroppable('div1');
setDroppable('div2');
And now it works fine. Here's the updated fiddle
Thanks Michal indeed that was the answer but I think a good programmer would reduce the redundant snippet of code as far as I can tell those are duplicate lines from the $(document).ready() function. However it's a solution. And right after I read your post I decided to post the answer myself as it follows:
//Previous
$("#" + makina).droppable({
drop: function () {
doAnimate(makina);
}
});
//Current
$("#wrapper").droppable({
drop: function () {
doAnimate(makina);
}
});
Since I'm using nested divs I then realised that I could make the parent div droppable and just animate the child which is active(shown).
I want to add a custom right-click menu to my web application. Can this be done without using any pre-built libraries? If so, how to display a simple custom right-click menu which does not use a 3rd party JavaScript library?
I'm aiming for something like what Google Docs does. It lets users right-click and show the users their own menu.
NOTE:
I want to learn how to make my own versus using something somebody made already since most of the time, those 3rd party libraries are bloated with features whereas I only want features that I need so I want it to be completely hand-made by me.
Answering your question - use contextmenu event, like below:
if (document.addEventListener) {
document.addEventListener('contextmenu', function(e) {
alert("You've tried to open context menu"); //here you draw your own menu
e.preventDefault();
}, false);
} else {
document.attachEvent('oncontextmenu', function() {
alert("You've tried to open context menu");
window.event.returnValue = false;
});
}
<body>
Lorem ipsum...
</body>
But you should ask yourself, do you really want to overwrite default right-click behavior - it depends on application that you're developing.
JSFIDDLE
Was very useful for me. For the sake of people like me, expecting the drawing of menu, I put here the code I used to make the right-click menu:
$(document).ready(function() {
if ($("#test").addEventListener) {
$("#test").addEventListener('contextmenu', function(e) {
alert("You've tried to open context menu"); //here you draw your own menu
e.preventDefault();
}, false);
} else {
//document.getElementById("test").attachEvent('oncontextmenu', function() {
//$(".test").bind('contextmenu', function() {
$('body').on('contextmenu', 'a.test', function() {
//alert("contextmenu"+event);
document.getElementById("rmenu").className = "show";
document.getElementById("rmenu").style.top = mouseY(event) + 'px';
document.getElementById("rmenu").style.left = mouseX(event) + 'px';
window.event.returnValue = false;
});
}
});
// this is from another SO post...
$(document).bind("click", function(event) {
document.getElementById("rmenu").className = "hide";
});
function mouseX(evt) {
if (evt.pageX) {
return evt.pageX;
} else if (evt.clientX) {
return evt.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
} else {
return null;
}
}
function mouseY(evt) {
if (evt.pageY) {
return evt.pageY;
} else if (evt.clientY) {
return evt.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
} else {
return null;
}
}
.show {
z-index: 1000;
position: absolute;
background-color: #C0C0C0;
border: 1px solid blue;
padding: 2px;
display: block;
margin: 0;
list-style-type: none;
list-style: none;
}
.hide {
display: none;
}
.show li {
list-style: none;
}
.show a {
border: 0 !important;
text-decoration: none;
}
.show a:hover {
text-decoration: underline !important;
}
<!-- jQuery should be at least version 1.7 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="contextmenu.js"></script>
<link rel="stylesheet" href="contextmenu.css" />
<div id="test1">
Google
Link 2
Link 3
Link 4
</div>
<!-- initially hidden right-click menu -->
<div class="hide" id="rmenu">
<ul>
<li>
Google
</li>
<li>
Localhost
</li>
<li>
C
</li>
</ul>
</div>
A combination of some nice CSS and some non-standard html tags with no external libraries can give a nice result (JSFiddle)
HTML
<menu id="ctxMenu">
<menu title="File">
<menu title="Save"></menu>
<menu title="Save As"></menu>
<menu title="Open"></menu>
</menu>
<menu title="Edit">
<menu title="Cut"></menu>
<menu title="Copy"></menu>
<menu title="Paste"></menu>
</menu>
</menu>
Note: the menu tag does not exist, I'm making it up (you can use anything)
CSS
#ctxMenu{
display:none;
z-index:100;
}
menu {
position:absolute;
display:block;
left:0px;
top:0px;
height:20px;
width:20px;
padding:0;
margin:0;
border:1px solid;
background-color:white;
font-weight:normal;
white-space:nowrap;
}
menu:hover{
background-color:#eef;
font-weight:bold;
}
menu:hover > menu{
display:block;
}
menu > menu{
display:none;
position:relative;
top:-20px;
left:100%;
width:55px;
}
menu[title]:before{
content:attr(title);
}
menu:not([title]):before{
content:"\2630";
}
The JavaScript is just for this example, I personally remove it for persistent menus on windows
var notepad = document.getElementById("notepad");
notepad.addEventListener("contextmenu",function(event){
event.preventDefault();
var ctxMenu = document.getElementById("ctxMenu");
ctxMenu.style.display = "block";
ctxMenu.style.left = (event.pageX - 10)+"px";
ctxMenu.style.top = (event.pageY - 10)+"px";
},false);
notepad.addEventListener("click",function(event){
var ctxMenu = document.getElementById("ctxMenu");
ctxMenu.style.display = "";
ctxMenu.style.left = "";
ctxMenu.style.top = "";
},false);
Also note, you can potentially modify menu > menu{left:100%;} to menu > menu{right:100%;} for a menu that expands from right to left. You would need to add a margin or something somewhere though
According to the answers here and on other 'flows, I've made a version that looks like the one of Google Chrome, with css3 transition.
JS Fiddle
Lets start easy, since we have the js above on this page, we can worry about the css and layout. The layout that we will be using is an <a> element with a <img> element or a font awesome icon (<i class="fa fa-flag"></i>) and a <span> to show the keyboard shortcuts. So this is the structure:
<a href="#" onclick="doSomething()">
<img src="path/to/image.gif" />
This is a menu option
<span>Ctrl + K</span>
</a>
We will put these in a div and show that div on the right-click. Let's style them like in Google Chrome, shall we?
#menu a {
display: block;
color: #555;
text-decoration: no[...]
Now we will add the code from the accepted answer, and get the X and Y value of the cursor. To do this, we will use e.clientX and e.clientY. We are using client, so the menu div has to be fixed.
var i = document.getElementById("menu").style;
if (document.addEventListener) {
document.addEventListener('contextmenu', function(e) {
var posX = e.clientX;
var posY = e.client[...]
And that is it! Just add the css transisions to fade in and out, and done!
var i = document.getElementById("menu").style;
if (document.addEventListener) {
document.addEventListener('contextmenu', function(e) {
var posX = e.clientX;
var posY = e.clientY;
menu(posX, posY);
e.preventDefault();
}, false);
document.addEventListener('click', function(e) {
i.opacity = "0";
setTimeout(function() {
i.visibility = "hidden";
}, 501);
}, false);
} else {
document.attachEvent('oncontextmenu', function(e) {
var posX = e.clientX;
var posY = e.clientY;
menu(posX, posY);
e.preventDefault();
});
document.attachEvent('onclick', function(e) {
i.opacity = "0";
setTimeout(function() {
i.visibility = "hidden";
}, 501);
});
}
function menu(x, y) {
i.top = y + "px";
i.left = x + "px";
i.visibility = "visible";
i.opacity = "1";
}
body {
background: white;
font-family: sans-serif;
color: #5e5e5e;
}
#menu {
visibility: hidden;
opacity: 0;
position: fixed;
background: #fff;
color: #555;
font-family: sans-serif;
font-size: 11px;
-webkit-transition: opacity .5s ease-in-out;
-moz-transition: opacity .5s ease-in-out;
-ms-transition: opacity .5s ease-in-out;
-o-transition: opacity .5s ease-in-out;
transition: opacity .5s ease-in-out;
-webkit-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
-moz-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
padding: 0px;
border: 1px solid #C6C6C6;
}
#menu a {
display: block;
color: #555;
text-decoration: none;
padding: 6px 8px 6px 30px;
width: 250px;
position: relative;
}
#menu a img,
#menu a i.fa {
height: 20px;
font-size: 17px;
width: 20px;
position: absolute;
left: 5px;
top: 2px;
}
#menu a span {
color: #BCB1B3;
float: right;
}
#menu a:hover {
color: #fff;
background: #3879D9;
}
#menu hr {
border: 1px solid #EBEBEB;
border-bottom: 0;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<h2>CSS3 and JAVASCRIPT custom menu.</h2>
<em>Stephan Stanisic | Lisence free</em>
<p>Right-click anywhere on this page to open the custom menu. Styled like the Google Chrome contextmenu. And yes, you can use <i class="fa fa-flag"></i>font-awesome</p>
<p style="font-size: small">
<b>Lisence</b>
<br /> "THE PIZZA-WARE LICENSE" (Revision 42):
<br /> You can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a Pizza in return.
<br />
<a style="font-size:xx-small" href="https://github.com/KLVN/UrbanDictionary_API#license">https://github.com/KLVN/UrbanDictionary_API#license</a>
</p>
<br />
<br />
<small>(The white body background is just because I hate the light blue editor background on the result on jsfiddle)</small>
<div id="menu">
<a href="#">
<img src="http://puu.sh/nr60s/42df867bf3.png" /> AdBlock Plus <span>Ctrl + ?!</span>
</a>
<a href="#">
<img src="http://puu.sh/nr5Z6/4360098fc1.png" /> SNTX <span>Ctrl + ?!</span>
</a>
<hr />
<a href="#">
<i class="fa fa-fort-awesome"></i> Fort Awesome <span>Ctrl + ?!</span>
</a>
<a href="#">
<i class="fa fa-flag"></i> Font Awesome <span>Ctrl + ?!</span>
</a>
</div>
Simplest jump start function, create a context menu at the cursor position, that destroys itself on mouse leave.
oncontextmenu = (e) => {
e.preventDefault()
let menu = document.createElement("div")
menu.id = "ctxmenu"
menu.style = `top:${e.pageY-10}px;left:${e.pageX-40}px`
menu.onmouseleave = () => ctxmenu.outerHTML = ''
menu.innerHTML = "<p>Option1</p><p>Option2</p><p>Option3</p><p>Option4</p><p onclick='alert(`Thank you!`)'>Upvote</p>"
document.body.appendChild(menu)
}
#ctxmenu {
position: fixed;
background: ghostwhite;
color: black;
cursor: pointer;
border: 1px black solid
}
#ctxmenu > p {
padding: 0 1rem;
margin: 0
}
#ctxmenu > p:hover {
background: black;
color: ghostwhite
}
You could try simply blocking the context menu by adding the following to your body tag:
<body oncontextmenu="return false;">
This will block all access to the context menu (not just from the right mouse button but from the keyboard as well).
P.S. you can add this to any tag you want to disable the context menu on
for example:
<div class="mydiv" oncontextmenu="return false;">
Will disable the context menu in that particular div only
Pure JS and css solution for a truly dynamic right click context menu, albeit based on predefined naming conventions for the elements id, links etc.
jsfiddle
and the code you could copy paste into a single static html page :
var rgtClickContextMenu = document.getElementById('div-context-menu');
/** close the right click context menu on click anywhere else in the page*/
document.onclick = function(e) {
rgtClickContextMenu.style.display = 'none';
}
/**
present the right click context menu ONLY for the elements having the right class
by replacing the 0 or any digit after the "to-" string with the element id , which
triggered the event
*/
document.oncontextmenu = function(e) {
//alert(e.target.id)
var elmnt = e.target
if (elmnt.className.startsWith("cls-context-menu")) {
e.preventDefault();
var eid = elmnt.id.replace(/link-/, "")
rgtClickContextMenu.style.left = e.pageX + 'px'
rgtClickContextMenu.style.top = e.pageY + 'px'
rgtClickContextMenu.style.display = 'block'
var toRepl = "to=" + eid.toString()
rgtClickContextMenu.innerHTML = rgtClickContextMenu.innerHTML.replace(/to=\d+/g, toRepl)
//alert(rgtClickContextMenu.innerHTML.toString())
}
}
.cls-context-menu-link {
display: block;
padding: 20px;
background: #ECECEC;
}
.cls-context-menu {
position: absolute;
display: none;
}
.cls-context-menu ul,
#context-menu li {
list-style: none;
margin: 0;
padding: 0;
background: white;
}
.cls-context-menu {
border: solid 1px #CCC;
}
.cls-context-menu li {
border-bottom: solid 1px #CCC;
}
.cls-context-menu li:last-child {
border: none;
}
.cls-context-menu li a {
display: block;
padding: 5px 10px;
text-decoration: none;
color: blue;
}
.cls-context-menu li a:hover {
background: blue;
color: #FFF;
}
<!-- those are the links which should present the dynamic context menu -->
<a id="link-1" href="#" class="cls-context-menu-link">right click link-01</a>
<a id="link-2" href="#" class="cls-context-menu-link">right click link-02</a>
<!-- this is the context menu -->
<!-- note the string to=0 where the 0 is the digit to be replaced -->
<div id="div-context-menu" class="cls-context-menu">
<ul>
<li>link-to=0 -item-1 </li>
<li>link-to=0 -item-2 </li>
<li>link-to=0 -item-3 </li>
</ul>
</div>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<title>Context menu - LabLogic.net</title>
</head>
<body>
<script language="javascript" type="text/javascript">
document.oncontextmenu=RightMouseDown;
document.onmousedown = mouseDown;
function mouseDown(e) {
if (e.which===3) {//righClick
alert("Right-click menu goes here");
}
}
function RightMouseDown() { return false; }
</script>
</body>
</html>
Tested and works in Opera 11.6, firefox 9.01, Internet Explorer 9 and chrome 17
Try this:
var cls = true;
var ops;
window.onload = function() {
document.querySelector(".container").addEventListener("mouseenter", function() {
cls = false;
});
document.querySelector(".container").addEventListener("mouseleave", function() {
cls = true;
});
ops = document.querySelectorAll(".container td");
for (let i = 0; i < ops.length; i++) {
ops[i].addEventListener("click", function() {
document.querySelector(".position").style.display = "none";
});
}
ops[0].addEventListener("click", function() {
setTimeout(function() {
/* YOUR FUNCTION */
alert("Alert 1!");
}, 50);
});
ops[1].addEventListener("click", function() {
setTimeout(function() {
/* YOUR FUNCTION */
alert("Alert 2!");
}, 50);
});
ops[2].addEventListener("click", function() {
setTimeout(function() {
/* YOUR FUNCTION */
alert("Alert 3!");
}, 50);
});
ops[3].addEventListener("click", function() {
setTimeout(function() {
/* YOUR FUNCTION */
alert("Alert 4!");
}, 50);
});
ops[4].addEventListener("click", function() {
setTimeout(function() {
/* YOUR FUNCTION */
alert("Alert 5!");
}, 50);
});
}
document.addEventListener("contextmenu", function() {
var e = window.event;
e.preventDefault();
document.querySelector(".container").style.padding = "0px";
var x = e.clientX;
var y = e.clientY;
var docX = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || document.body.offsetWidth;
var docY = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || document.body.offsetHeight;
var border = parseInt(getComputedStyle(document.querySelector(".container"), null).getPropertyValue('border-width'));
var objX = parseInt(getComputedStyle(document.querySelector(".container"), null).getPropertyValue('width')) + 2;
var objY = parseInt(getComputedStyle(document.querySelector(".container"), null).getPropertyValue('height')) + 2;
if (x + objX > docX) {
let diff = (x + objX) - docX;
x -= diff + border;
}
if (y + objY > docY) {
let diff = (y + objY) - docY;
y -= diff + border;
}
document.querySelector(".position").style.display = "block";
document.querySelector(".position").style.top = y + "px";
document.querySelector(".position").style.left = x + "px";
});
window.addEventListener("resize", function() {
document.querySelector(".position").style.display = "none";
});
document.addEventListener("click", function() {
if (cls) {
document.querySelector(".position").style.display = "none";
}
});
document.addEventListener("wheel", function() {
if (cls) {
document.querySelector(".position").style.display = "none";
static = false;
}
});
.position {
position: absolute;
width: 1px;
height: 1px;
z-index: 2;
display: none;
}
.container {
width: 220px;
height: auto;
border: 1px solid black;
background: rgb(245, 243, 243);
}
.container p {
height: 30px;
font-size: 18px;
font-family: arial;
width: 99%;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background: rgb(245, 243, 243);
color: black;
transition: 0.2s;
}
.container p:hover {
background: lightblue;
}
td {
font-family: arial;
font-size: 20px;
}
td:hover {
background: lightblue;
transition: 0.2s;
cursor: pointer;
}
<div class="position">
<div class="container" align="center">
<table style="text-align: left; width: 99%; margin-left: auto; margin-right: auto;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="vertical-align: middle; text-align: center;">Option 1<br>
</td>
</tr>
<tr>
<td style="vertical-align: middle; text-align: center;">Option 2<br>
</td>
</tr>
<tr>
<td style="vertical-align: middle; text-align: center;">Option 3<br>
</td>
</tr>
<tr>
<td style="vertical-align: middle; text-align: center;">Option 4<br>
</td>
</tr>
<tr>
<td style="vertical-align: middle; text-align: center;">Option 5<br>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Here is a very good tutorial on how to build a custom context menu with a full working code example (without JQuery and other libraries).
You can also find their demo code on GitHub.
They give a detailed step-by-step explanation that you can follow along to build your own right-click context menu (including html, css and javascript code) and summarize it at the end by giving the complete example code.
You can follow along easily and adapt it to your own needs. And there is no need for JQuery or other libraries.
This is how their example menu code looks like:
<nav id="context-menu" class="context-menu">
<ul class="context-menu__items">
<li class="context-menu__item">
<i class="fa fa-eye"></i> View Task
</li>
<li class="context-menu__item">
<i class="fa fa-edit"></i> Edit Task
</li>
<li class="context-menu__item">
<i class="fa fa-times"></i> Delete Task
</li>
</ul>
</nav>
A working example (task list) can be found on codepen.
I know this has already been answered, but I spent some time wrestling with the second answer to get the native context menu to disappear and have it show up where the user clicked.
HTML
<body>
<div id="test1">
Google
Link 2
Link 3
Link 4
</div>
<!-- initially hidden right-click menu -->
<div class="hide" id="rmenu">
<ul>
<li class="White">White</li>
<li>Green</li>
<li>Yellow</li>
<li>Orange</li>
<li>Red</li>
<li>Blue</li>
</ul>
</div>
</body>
CSS
.hide {
display: none;
}
#rmenu {
border: 1px solid black;
background-color: white;
}
#rmenu ul {
padding: 0;
list-style: none;
}
#rmenu li
{
list-style: none;
padding-left: 5px;
padding-right: 5px;
}
JavaScript
if (document.getElementById('test1').addEventListener) {
document.getElementById('test1').addEventListener('contextmenu', function(e) {
$("#rmenu").toggleClass("hide");
$("#rmenu").css(
{
position: "absolute",
top: e.pageY,
left: e.pageX
}
);
e.preventDefault();
}, false);
}
// this is from another SO post...
$(document).bind("click", function(event) {
document.getElementById("rmenu").className = "hide";
});
CodePen Example
Try This
$(function() {
var doubleClicked = false;
$(document).on("contextmenu", function (e) {
if(doubleClicked == false) {
e.preventDefault(); // To prevent the default context menu.
var windowHeight = $(window).height()/2;
var windowWidth = $(window).width()/2;
if(e.clientY > windowHeight && e.clientX <= windowWidth) {
$("#contextMenuContainer").css("left", e.clientX);
$("#contextMenuContainer").css("bottom", $(window).height()-e.clientY);
$("#contextMenuContainer").css("right", "auto");
$("#contextMenuContainer").css("top", "auto");
} else if(e.clientY > windowHeight && e.clientX > windowWidth) {
$("#contextMenuContainer").css("right", $(window).width()-e.clientX);
$("#contextMenuContainer").css("bottom", $(window).height()-e.clientY);
$("#contextMenuContainer").css("left", "auto");
$("#contextMenuContainer").css("top", "auto");
} else if(e.clientY <= windowHeight && e.clientX <= windowWidth) {
$("#contextMenuContainer").css("left", e.clientX);
$("#contextMenuContainer").css("top", e.clientY);
$("#contextMenuContainer").css("right", "auto");
$("#contextMenuContainer").css("bottom", "auto");
} else {
$("#contextMenuContainer").css("right", $(window).width()-e.clientX);
$("#contextMenuContainer").css("top", e.clientY);
$("#contextMenuContainer").css("left", "auto");
$("#contextMenuContainer").css("bottom", "auto");
}
$("#contextMenuContainer").fadeIn(500, FocusContextOut());
doubleClicked = true;
} else {
e.preventDefault();
doubleClicked = false;
$("#contextMenuContainer").fadeOut(500);
}
});
function FocusContextOut() {
$(document).on("click", function () {
doubleClicked = false;
$("#contextMenuContainer").fadeOut(500);
$(document).off("click");
});
}
});
http://jsfiddle.net/AkshayBandivadekar/zakn7Lwb/14/
You can do it with this code.
visit here for full tutorial with automatic edge detection http://www.voidtricks.com/custom-right-click-context-menu/
$(document).ready(function () {
$("html").on("contextmenu",function(e){
//prevent default context menu for right click
e.preventDefault();
var menu = $(".menu");
//hide menu if already shown
menu.hide();
//get x and y values of the click event
var pageX = e.pageX;
var pageY = e.pageY;
//position menu div near mouse cliked area
menu.css({top: pageY , left: pageX});
var mwidth = menu.width();
var mheight = menu.height();
var screenWidth = $(window).width();
var screenHeight = $(window).height();
//if window is scrolled
var scrTop = $(window).scrollTop();
//if the menu is close to right edge of the window
if(pageX+mwidth > screenWidth){
menu.css({left:pageX-mwidth});
}
//if the menu is close to bottom edge of the window
if(pageY+mheight > screenHeight+scrTop){
menu.css({top:pageY-mheight});
}
//finally show the menu
menu.show();
});
$("html").on("click", function(){
$(".menu").hide();
});
});
`
<script language="javascript" type="text/javascript">
document.oncontextmenu = RightMouseDown;
document.onmousedown = mouseDown;
function mouseDown(e) {
if (e.which==3) {//righClick
alert("Right-click menu goes here");
}
}
function RightMouseDown() {
return false;
}
</script>
</body>
</html>
A simple way you could do it is use onContextMenu to return a JavaScript function:
<input type="button" value="Example" onContextMenu="return RightClickFunction();">
<script>
function RightClickFunction() {
// Enter your code here;
return false;
}
</script>
And by entering return false; you will cancel out the context menu.
if you still want to display the context menu you can just remove the return false; line.
Tested and works in Opera 12.17, firefox 30, Internet Explorer 9 and chrome 26.0.1410.64
document.oncontextmenu =function( evt ){
alert("OK?");
return false;
}
For those looking for a very simple self-contained implementation of a custom context menu using bootstrap 5 and jQuery 3, here it is...
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<title>Custom Context Menu</title>
</head>
<style>
#context-menu {
position: absolute;
display: none;
}
</style>
<body>
<div class="container-fluid p-5">
<div class="row p-5">
<div class="col-4">
<span id="some-element" class="border border-2 border-primary p-5">Some element</span>
</div>
</div>
<div id="context-menu" class="dropdown clearfix">
<ul class="dropdown-menu" style="display:block;position:static;margin-bottom:5px;">
<li><a class="dropdown-item" href="#" data-value="copy">Copy</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" data-value="select-all">Select All</a></li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
<script>
$('body').on('contextmenu', '#some-element', function(e) {
$('#context-menu').css({
display: "block",
left: e.pageX,
top: e.pageY
});
return false;
});
$('html').click(function() {
$('#context-menu').hide();
});
$("#context-menu li a").click(function(e){
console.log('in context-menu item, value = ' + $(this).data('value'));
});
</script>
</body>
</html>
Adapted from https://codepen.io/anirugu/pen/xjjxvG
<script>
function fun(){
document.getElementById('menu').style.display="block";
}
</script>
<div id="menu" style="display: none"> menu items</div>
<body oncontextmenu="fun();return false;">
What I'm doing up here
Create your own custom div menu and set the position: absolute and display:none in case.
Add to the page or element to be clicked the oncontextmenu event.
Cancel the default browser action with return false.
User js to invoke your own actions.
You should remember if you want to use the Firefox only solution, if you want to add it to the whole document you should add contextmenu="mymenu" to the <html> tag not to the body tag.
You should pay attention to this.
<html>
<head>
<style>
.rightclick {
/* YOUR CONTEXTMENU'S CSS */
visibility: hidden;
background-color: white;
border: 1px solid grey;
width: 200px;
height: 300px;
}
</style>
</head>
<body>
<div class="rightclick" id="ya">
<p onclick="alert('choc-a-late')">I like chocolate</p><br><p onclick="awe-so-me">I AM AWESOME</p>
</div>
<p>Right click to get sweet results!</p>
</body>
<script>
document.onclick = noClick;
document.oncontextmenu = rightClick;
function rightClick(e) {
e = e || window.event;
e.preventDefault();
document.getElementById("ya").style.visibility = "visible";
console.log("Context Menu v1.3.0 by IamGuest opened.");
}
function noClick() {
document.getElementById("ya").style.visibility = "hidden";
console.log("Context Menu v1.3.0 by IamGuest closed.");
}
</script>
<!-- Coded by IamGuest. Thank you for using this code! -->
</html>
You can tweak and modify this code to make a better looking, more efficient contextmenu. As for modifying an existing contextmenu, I'm not sure how to do that... Check out this fiddle for an organized point of view. Also, try clicking the items in my contextmenu. They should alert you a few awesome messages. If they don't work, try something more... complex.
I use something similar to the following jsfiddle
function onright(el, cb) {
//disable right click
document.body.oncontextmenu = 'return false';
el.addEventListener('contextmenu', function (e) { e.preventDefault(); return false });
el.addEventListener('mousedown', function (e) {
e = e || window.event;
if (~~(e.button) === 2) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
return false;
}
});
// then bind Your cb
el.addEventListener('mousedown', function (e) {
e = e || window.event;
~~(e.button) === 2 && cb.call(el, e);
});
}
if You target older IE browsers you should anyway complete it with the ' attachEvent; case