Well, this is exactly what I need to do :
When the user right-clicks on a WebView, the typical menu (without "reload",etc) should not show up.
How can this be done? Any ideas?
P.S. Also : is it possible that a custom menu is shown?
It is simple to prevent the context menu with html:
<body oncontextmenu="return false;">
or with javascript (jquery):
$(document).bind(“contextmenu”, function (e) {
e.preventDefault();
});
Or, if you want to show a custom html context menu using javascript...
HTML:
<div id="context-menu">
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
</div>
<div id="op">Right click anywhere!</div>
CSS:
#context-menu {
display: none;
position: fixed;
border: 1px solid #ddd;
background: white;
box-shadow: 2px 2px 1px grey;
}
#context-menu ul {
list-style: none;
padding: 0;
margin: 0;
}
#context-menu li {
width:150px;
padding: 5px 8px;
}
#context-menu li:hover {
background:#eaeaea;
cursor:pointer;
}
JS:
function startFocusOut() {
$(document).on("click", function () {
$("#context-menu").fadeOut(20); // To hide the context menu
$(document).off("click");
});
}
$(function(){
$(document).bind("contextmenu", function (e) {
e.preventDefault(); // To prevent the default context menu.
$("#context-menu").css("left", e.pageX); // position with cursor
$("#context-menu").css("top", e.pageY);
$("#context-menu").fadeIn(20, startFocusOut()); // show the menu
});
$("#context-menu li").click(function () {
$("#op").text("You have selected " + $(this).text()); // Performing the selected function.
});
});
Jsfiddle: http://jsfiddle.net/VRy93/
Related
I have a List Detail View using Nuxt dynamic routes in SSR mode
The list with overflow-y appears on left and on clicking an item, the contents appear on right
When I click each item, the URL params change and a new item is shown on right
When I press back button the previous item is shown but the scrollbar does not change
How do I make the scrollbar go to the previous item?
Here is the GIF showing the problem, on clicking back, the list should scroll to the previous item
<template>
<div class="root">
<div class="left">
<ul>
<li v-for="i in sortedArticles" :key="i.feedItemId">
<nuxt-link :to="'/articles/' + i.feedItemId" :id="i.feedItemId" no-prefetch>{{ i.title }}</nuxt-link>
</li>
</ul>
</div>
<div class="right">Article {{ $route.params.id }}</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
key(route) {
return 'articles'
},
computed: {
...mapGetters({
sortedArticles: 'news/SORTED_ARTICLES'
})
},
}
</script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
line-height: 1.8;
}
.root {
display: flex;
flex-direction: row;
height: 100vh;
}
.left {
flex: 1;
overflow-y: auto;
}
.left ul {
list-style-type: none;
}
.left li a {
display: block;
text-decoration: none;
padding: 0.5rem 1rem;
border-bottom: 1px solid #eee;
color: black;
}
.left li a:hover {
color: darkorange;
}
.right {
flex: 1;
}
</style>
The above code is the pages/articles/_id.vue file
How do I achieve this in NUXT
You must be use watch:
<li :ref="'el' + i.feedItemId" v-for="i in sortedArticles" :key="i.feedItemId">
watch: {
'$route.params.id': function(id) {
this.$refs['el' + id].scrollIntoView()
}
}
I am using the Blazor server-side.
When the Blazor App disconnect to the remote server, it will shows this:
I want to change the text ('Could not reconnect to the server...' and so on) of the image above.
I want to change it to the language of our country.
I found the file of the project but found nothing about this.
How can I change it? Thank you.
The Blazor App will check whether there's a html element with id={dialogId} in the page:
If such an element doesn't exists, it will use the default handler to display message.
If this element exists, this element's class will be :
set as components-reconnect-show when attempting to reconnect to the server.
set as components-reconnect-failed when reconnection failed, probably due to a network failure. To attempt reconnection, call window.Blazor.reconnect().
set as components-reconnect-rejected when reconnection rejected. The server was reached but refused the connection, and the user's state on the server is lost. To reload the app, call location.reload().
By default, the dialogId is components-reconnect-modal. So you can create an element in the page and use CSS to control the content and styles as you like.
Check out the Microsoft Docs for the latest info.
Demo:
For example, I create three parts of content to display within the Pages/_Host.cshtml:
<div id="components-reconnect-modal" class="my-reconnect-modal components-reconnect-hide">
<div class="show">
<p>
This is the message when attempting to connect to server
</p>
</div>
<div class="failed">
<p>
This is the custom message when failing
</p>
</div>
<div class="rejected">
<p>
This is the custom message when refused
</p>
</div>
</div>
<app>
#(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
And then let's add some CSS to control the style:
<style>
.my-reconnect-modal > div{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
overflow: hidden;
background-color: #fff;
opacity: 0.8;
text-align: center;
font-weight: bold;
}
.components-reconnect-hide > div
{
display: none;
}
.components-reconnect-show > div
{
display: none;
}
.components-reconnect-show > .show
{
display: block;
}
.components-reconnect-failed > div
{
display: none;
}
.components-reconnect-failed > .failed
{
display: block;
}
.components-reconnect-rejected >div
{
display: none;
}
.components-reconnect-rejected > .rejected
{
display: block;
}
</style>
Finally, we'll get the following message when attempting to connect or failing to connect:
For the javascript side of things Blazor exposes a tiny API via the window.Blazor object.
One part of this API is the defaultReconnectionHandler which allows you to customize the reconnection experience including setting different options for the number of retrys etc.
However, it is also possible to just swap out the logic for displaying the ReconnectionDisplay
A simple implemenation looks like this and enables you to to get controll over the process:
function createOwnDisplay() {
return {
show: () => { alert("put code that shows a toast , ui, or whaterver here"); },
hide: () => { console.log('foo'); },
failed: () => { console.log('foo'); },
rejected: () => { console.log('foo'); }
};
}
Blazor.defaultReconnectionHandler._reconnectionDisplay = createOwnDisplay();
In your css:
#components-reconnect-modal {
display: none;
position: fixed;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
z-index: 1000;
overflow: hidden;
background-color: rgb(255, 255, 255);
opacity: 0.8;
text-align: center;
font-weight: bold;
}
#components-reconnect-modal.components-reconnect-show{
display: block;
}
#components-reconnect-modal.components-reconnect-show div.reconnecting {
display: block;
}
div.reconnecting {
display: none;
}
#components-reconnect-modal.components-reconnect-failed {
display: block;
}
#components-reconnect-modal.components-reconnect-failed div.failedToConnect {
display: block;
}
div.failedToConnect {
display: none;
}
#components-reconnect-modal.components-reconnect-rejected {
display: block;
}
#components-reconnect-modal.components-reconnect-rejected div.connectionRejected {
display: block;
}
div.connectionRejected {
display: none;
}
#components-reconnect-modal.components-reconnect-hide {
display: none;
}
In _Host body:
<div id="components-reconnect-modal">
<div class="reconnecting">
Подключение к серверу...
</div>
<div class="failedToConnect">
Не удалось подключиться к серверу <input type="button" value="переподключиться" onclick="ReconnectToServer()" />
<script>
function ReconnectToServer() {
window.Blazor.reconnect();
}
</script>
</div>
<div class="connectionRejected">
Подключение к серверу прервано <input type="button" value="обновить страницу" onclick="ReloadPage()" />
<script>
function ReloadPage() {
location.reload();
}
</script>
</div>
</div>
Please open https://jsfiddle.net/gfmyt9u8/31/
When user clicks outside <section> tag area, then the opened div overlay panel should be closed.
Steps to produce scenario :
Click "Please Select Options"
Now, click first item from opened overlay panel (by doing this, the panel got closed automatically)
Next, Click inside the blue color border div (This shows "Please Select Options" as label) again
Now, try to click outside the "blue color border div" and "opened div overlay panel beneath" both
overlay panel will not close
Actual Result : overlay panel is not closing
Expected Result : overlay panel should close when clicked outside the "blue color border div" and "open overlay panel
beneath"
Use the mounted lifecycle hook to add a click event listener to check if the click event is outside the element or not, and based on that hide the element.
A working example:
new Vue({
el: '#app',
data: {
displayList: false,
cat: ['A', 'B']
},
methods: {
itemSelect(o) {
this.displayList = false;
}
},
mounted: function () {
// Listen to all clicks on the document
document.addEventListener("click", function(event) {
// If the click inside the element, do nothing
if (event.target.closest(".section-main")) return;
// If the clicks outside the element, hide it!
this.displayList = false;
}.bind(this));
}
});
.display-no-selected {
cursor: text;
width: 300px;
height: 25px;
border: solid 2px blue;
}
.display-list {
border: solid 1px wheat;
width: 300px;
max-height: 150px;
overflow-y: auto;
}
.toggle-list {
display: none;
}
ul, .selected-ul {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.inner-ul li {
cursor: pointer;
font-weight: normal;
}
ul.inner-ul li:hover {
background-color: wheat;
}
.default-highlight {
background-color: wheat;
}
ul.inner-ul li span {
margin-left: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<section class="section-main">
<div class="display-no-selected" #click="displayList=true"> Please Select Options
</div>
<div class="display-list"
v-bind:class="{'toggle-list': !displayList}">
<ul class="inner-first-ul inner-ul">
<li v-for="o in cat" #click="itemSelect(o)">
<span>{{o}}</span>
</li>
</ul>
</div>
</section>
</div>
I'm creating a modal in Vue, which I want to to be able to close whenever the user clicks outside of the inner modal container. The problem is when I add an event listener on click to the parent element all children elements also trigger that event listener when clicked.
I created a simple demo below to demonstrate my problem. If the user clicks on the black portion of the parent element the modal should close but the containing white space of the child element shouldn't be able to trigger the close function.
new Vue({
el: '#modal',
data: {
active: true,
},
methods: {
closeModal() {
this.active = false
}
}
})
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
justify-content: center;
align-items: center;
background-color: black;
}
.modal.active {
display: flex;
}
.modal-content {
width: 200px;
height: 200px;
padding: 1rem;
background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="modal" class="modal" :class="{active: active}" v-on:click="closeModal">
<div class="modal-content">This child element shouldn't be able to close the modal on click.</div>
</div>
You can try
v-on:click.self=...
Should only trigger if the target element is itself.
Hope that helps
I endorse kimy82's answer. Use click.self. Snippet updated.
new Vue({
el: '#modal',
data: {
active: true,
},
methods: {
closeModal(event) {
this.active = false
}
}
})
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
justify-content: center;
align-items: center;
background-color: black;
}
.modal.active {
display: flex;
}
.modal-content {
width: 200px;
height: 200px;
padding: 1rem;
background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="modal" class="modal" :class="{active: active}" v-on:click.self="closeModal">
<div class="modal-content">This child element shouldn't be able to close the modal on click.</div>
</div>
There are event modifiers for the click event handler
https://v2.vuejs.org/v2/guide/events.html#Event-Modifiers
<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>
I'm adding elements to a list dynamically using v-for.
<ol>
<li v-for="light in lights">
<input type="range" min="0" max="255" v-model="light.currentBrightness" v-on:change="setBrightness(light)" />
</li>
</ol>
I want to decorate the slider using rangeslider.
Problem is, when a new element is added after the DOM is initialized, it's not taking the style specified in rangeslider.js. Way to fix this is to call the reinitialize method in rangeslider.js which will redecorate all the slider elements.
I'm not sure how to call the javascript method when the element is added dynamically during the runtime. Does anyone how to do it? To me, it seems like a very common problem but I could not find a solution by Googling.
My issue is same as discussed in github.
If you're new to JavaScript and Vue, you're diving in pretty close to the deep end. The rangeslider isn't just styling (like CSS), it's a widget that replaces the built-in range input.
One basic idea behind Vue is that it controls the DOM and you only modify your model, but there are some carefully controlled exceptions. Components have lifecycle hooks where you are allowed to insert and modify DOM elements owned by the component.
Some instructions for v-model support:
So for a component to work with v-model, it should (these can be
configured in 2.2.0+):
accept a value prop
emit an input event with the new value
So we make a component whose template is a range input element. We give it a value prop. In the mounted hook, we initialize the rangeslider on the input element (made available as el), then set it up to emit input events on change.
new Vue({
el: '#app',
data: {
lights: [{
currentBrightness: 10
},
{
currentBrightness: 30
}
]
},
methods: {
addRange: function() {
this.lights.push({
currentBrightness: 50
});
}
},
components: {
rangeSlider: {
props: ['value', 'min', 'max'],
template: '<input min="{{min}}" max="{{max}}" type=range />',
mounted: function() {
var vm = this
$(this.$el)
.val(this.value)
// init rangeslider
.rangeslider({
polyfill: false
})
// emit event on change.
.on('change', function() {
vm.$emit('input', this.value)
})
}
}
}
});
<link href="//cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.0/rangeslider.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.2/vue.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.0/rangeslider.min.js"></script>
<div id="app">
<ol>
<li v-for="light in lights">
<range-slider v-model="light.currentBrightness" min="0" max="255"></range-slider>
<div>{{light.currentBrightness}}</div>
</li>
</ol>
<button #click="addRange">Add Range</button>
</div>
You can use the below CSS codes to apply some stylings in the html5 range input:
body {
padding: 30px;
}
input[type=range] {
/*removes default webkit styles*/
-webkit-appearance: none;
/*fix for FF unable to apply focus style bug */
border: 1px solid white;
/*required for proper track sizing in FF*/
width: 300px;
}
input[type=range]::-webkit-slider-runnable-track {
width: 300px;
height: 5px;
background: #ddd;
border: none;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: goldenrod;
margin-top: -4px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #ccc;
}
input[type=range]::-moz-range-track {
width: 300px;
height: 5px;
background: #ddd;
border: none;
border-radius: 3px;
}
input[type=range]::-moz-range-thumb {
border: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: goldenrod;
}
/*hide the outline behind the border*/
input[type=range]:-moz-focusring{
outline: 1px solid white;
outline-offset: -1px;
}
input[type=range]::-ms-track {
width: 300px;
height: 5px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent;
border-width: 6px 0;
/*remove default tick marks*/
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: #777;
border-radius: 10px;
}
input[type=range]::-ms-fill-upper {
background: #ddd;
border-radius: 10px;
}
input[type=range]::-ms-thumb {
border: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: goldenrod;
}
input[type=range]:focus::-ms-fill-lower {
background: #888;
}
input[type=range]:focus::-ms-fill-upper {
background: #ccc;
}