Related
For a chat app, I need to change the color of words starting with a special character, #word inside an input tag, i.e:
Hello #John how are you?
the part #John should change color inside the input, i.e:
Hello #John how are you?
It works after it's posted, but that's obviously another code. I want it to highlight words (#mention) by changing its color right in the input or textarea Element.
Color specific text inside a textarea-alike element
One 5y old idea (Highlight syntax in contenteditable) would be to:
let the user type into a contenteditable DIV with transparent color but visible caret, then get and modify the content on the fly as-you-ype to an underlying DIV, used as a markup highlighter.
Basically:
On "input" event get the editable innerHTML, do some String.prototype.replace() with a regular expression that matches #mentions on the contenteditable value and replace i.e: #John with <span class="mention">#John</span>
Write the result as HTML to the underlying (highlighter) DIV element.
This way you're not replacing and creating any child SPAN elements in the area where the user is typing, but actually on the underlying one.
const colorMention = (elText, elPre) => {
elPre.innerHTML = elText.innerHTML.replace(/(?<=^| )#\p{L}+/gu, "<span class='mention'>$&</span>");
};
const scrollMirror = (elText, elPre) => {
elPre.scrollTo(elText.scrollLeft, elText.scrollTop);
};
const handleKey = (ev, elText, elPre) => {
if (ev.key === "Enter" && !ev.shiftKey) {
// prevent Enter key behavior (new-line)
ev.preventDefault();
// Check message to send...
const message = elText.innerHTML;
if (!message.trim()) {
return; // Nothing to submit. Message is empty
}
// YOUR SUBMIT LOGIC GOES HERE:
console.log(message);
// Clear fields:
elText.innerHTML = "";
elPre.innerHTML = "";
} else {
// Any other key: (scroll areas is necessary)
scrollMirror(elText, elPre);
}
};
document.querySelectorAll(".message").forEach(el => {
const elText = el.querySelector(".text");
const elPre = el.querySelector(".pre");
elText.addEventListener("scroll", () => scrollMirror(elText, elPre));
elText.addEventListener("keyup", () => scrollMirror(elText, elPre));
elText.addEventListener("input", () => colorMention(elText, elPre));
elText.addEventListener("keydown", (ev) => handleKey(ev, elText, elPre));
// Init:
colorMention(elText, elPre);
scrollMirror(elText, elPre);
});
* {
margin: 0;
box-sizing: border-box;
}
body {
font: 16px/1.3 sans-serif;
}
.message {
display: block;
border: 1px solid #888;
position: relative;
width: 100%;
border: 1px solid #ccc;
}
.message .pre,
.message .text {
border: 0;
overflow: scroll;
overflow-x: hidden;
font: inherit;
padding: 10px;
height: 5rem;
resize: none;
width: 100%;
white-space: break-spaces;
word-wrap: break-word;
}
/* The overlay contenteditable with transparent text but visible caret */
.message .text {
position: relative;
background: transparent;
outline: none;
/* transparent color */
color: transparent;
/* but visible caret */
caret-color: black;
}
/* The underlaying element with colors */
.message .pre {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* Prevent text selections */
user-select: none;
}
.mention {
color: fuchsia;
}
<div class="message">
<div class="pre"></div>
<div class="text" contenteditable spellcheck="false">Hi #Roko, how are you today?</div>
</div>
<br>
Chat tips:<br> Use <code>#username</code> to mention a user.<br> Use <kbd>Enter</kbd> to send.<br> Use <kbd>Shift</kbd>+<kbd>Enter</kbd> to go to a new line.<br>
Regarding the regular expression for matching mentions:
/(?<=^| )#\p{L}+/gu
here's a Regex101.com example with description, and a related answer.
I have an HTML page which has some draggable elements. Our specs say that hovering mouse on such element the cursor must be grab , and during drag cursor must be grabbing .
I know it is possible to set dropEffect which changes cursor appearance above drop zone, but there are very little options: copy, move, link, and none -- no custom or alike.
I have tried to change cursor with Javascript and CSS, like setting cursor: grabbing; when ondragstart is fired. But browser default move cursor appears instead when dragging on drop zone.
So the question is: What am I missing to show grabbing cursor () during drag?
Unfortunately I cannot use JQuery or other helping libraries in the solution. Thanks in advance!
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 200px;
background-color: silver;
}
.block {
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
}
.draggable {
cursor: -webkit-grab;
cursor: grab;
}
.being-dragged {
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
}
<div class = "dropzone"
ondragover = "onDragOver(event);"
>
Grab and drag block around
<div class = "draggable block"
draggable = "true"
ondragstart = "onDragStart(event);"
ondragend = "onDragEnd(event);"
>
I'm draggable
</div>
</div>
It seems that browsers don't allow changing the cursor at the beginning of a drag & drop operation. I don't know why but it's a known issue, I believe they will in the future.
If jQuery is not an option, a possible way around is to implement a drag & drop from scratch, using mouse events and cloning the source element:
var onDragStart = function (event) {
event.preventDefault();
var clone = event.target.cloneNode(true);
clone.classList.add("dragging");
event.target.parentNode.appendChild(clone);
var style = getComputedStyle(clone);
clone.drag = {
x: (event.pageX||(event.clientX+document.body.scrollLeft)) - clone.offsetLeft + parseInt(style.marginLeft),
y: (event.pageY||(event.clientY+document.body.scrollTop)) - clone.offsetTop + parseInt(style.marginTop),
source: event.target
};
};
var onDragMove = function (event) {
if (!event.target.drag) {return;}
event.target.style.left = ((event.pageX||(event.clientX+document.body.scrollLeft)) - event.target.drag.x) + "px";
event.target.style.top = ((event.pageY||(event.clientY+document.body.scrollTop)) - event.target.drag.y) + "px";
};
var onDragEnd = function (event) {
if (!event.target.drag) {return;}
// Define persist true to let the source persist and drop the target, otherwise persist the target.
var persist = true;
if (persist || event.out) {
event.target.parentNode.removeChild(event.target);
} else {
event.target.parentNode.removeChild(event.target.drag.source);
}
event.target.classList.remove("dragging");
event.target.drag = null;
};
var onDragOver = function (event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 200px;
background-color: silver;
}
.block {
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
}
.draggable {
position: absolute;
cursor: pointer; /* IE */
cursor: -webkit-grab;
cursor: grab;
}
.dragging {
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
}
<div class="dropzone" onmouseover="onDragOver(event);">
Grab and drag block around
<div class = "draggable block"
onmousedown = "onDragStart(event);"
onmousemove = "onDragMove(event);"
onmouseup = "onDragEnd(event);"
onmouseout = "event.out = true; onDragEnd(event);"
>
I'm draggable
</div>
</div>
It is a known issue reported here
While dragging, the cursor will automatically changed to normal.
My tries gave me the following. Gave an active on the element with grabbing cursor. While it is active, the cursor will change but once you start the drag, it will change automatically.
I tried to set body cursor to grabbing on dragstart but no result. Even it is not working.
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 200px;
background-color: silver;
}
.block {
position: absolute;
background-color: pink;
margin: 10px;
border: 20px solid pink;
}
.draggable {
cursor: -webkit-grab;
cursor: grab;
}
.draggable:active{
cursor : -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
.being-dragged{
background-color: red;
cursor : -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
<div class = "dropzone"
ondragover = "onDragOver(event);"
>
Grab and drag block around
<div class = "draggable block"
draggable = "true"
ondragstart = "onDragStart(event);"
ondragend = "onDragEnd(event);"
>
I'm draggable
</div>
</div>
I went through a lot of pain trying to figure this out. The accepted answer was the best answer on the web, but best practices now would be to use the element's .setPointerCapture event, which allows you to listen to and act upon drag like behaviors on an element without being boxed into the narrow behavior of the Drag API. One way to do it would be like so:
el.onpointerdown = ev => {
el.onpointermove = pointerMove
el.setPointerCapture(ev.pointerId)
}
pointerMove = ev => {
console.log('Dragged!')
}
el.onpointerup = ev => {
el.onpointermove = null
el.releasePointerCapture(ev.pointerId)
}
The obvious gift being the fact that there is no cursor hijacking to be found sneaking in the backdoor here.
I know just a little bit about draggable elements with pure JavaScript and I'm sorry that I can't explain the following.
The problem was that the onDragEnd never get fired so I've searched something and find this example with draggable elements.
Now, if you change the function of the onDragStart event it will work but I think you have to change the cursor in another way like to change the class of the body onDragStart
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
All in one
var onDragStart = function(event) {
event.dataTransfer.setData("Text", event.target.id);
event.currentTarget.classList.add("being-dragged");
};
var onDragEnd = function(event) {
event.currentTarget.classList.remove("being-dragged");
};
var onDragOver = function(event) {
event.preventDefault();
};
.dropzone {
width: 500px;
height: 500px;
background-color: silver;
}
.block {
width: 200px;
height: 50px;
background-color: pink;
}
.draggable1 {
cursor: -webkit-grab;
cursor: grab;
}
.being-dragged {
cursor: -webkit-grabbing;
cursor: grabbing;
background-color: red;
}
<div class="dropzone" ondragover="onDragOver(event);">
<div class="draggable1 block" draggable="true" ondragstart="onDragStart(event);" ondragend="onDragEnd(event);">
I'm draggable
</div>
</div>
Try this ! It works for me !
.draggable {
cursor: -webkit-grab;
cursor: grab;
}
.draggable:active {
cursor: -webkit-grabbing;
cursor: grabbing;
}
I spent sometime to find solution for this, ended with this trick. I feel this is best way less code and apt work.
.drag{
cursor: url('../images/grab.png'), auto;
}
.drag:active {
cursor: url('../images/grabbing.png'), auto;
}
I am using popup.js to display content inside a popup. However, if I am executing the basic example, this is what I am getting:
What you see here is the popup with some uninteresting content, but you can also see that <div class="popup_cont" ..> has been added several times to the DOM tree. The result is that I have to click (here) 7 times to get rid of the popup. Each click removes one of those overlays..
I have no idea why this is happening. This is how I embed the popup:
<div id="btn-help" class="toy-button">
<span lang="en">
HELP
</span>
</div>
And this is how it gets invoked:
/**
* Callback to display help window.
* #private
* #memberOf module:cpu-controlls_controller
*/
_onHelpButtonClicked = function() {
debug('cpu-controlls.controller _onHelpButtonClicked()');
var options = { content : "hallo.html" };
$('.default_popup').popup(options);
};
Where the hallo.html is just a .html file with a lot of "Hello World!" messages.
Any idea how I can solve this?
It seems like you initialize the popup plugin every time the user clicks on the button, so the first time it will work okay, but with every next click you will have more and more popups to close.
Put the initialization in the document.ready() function, and out of the click handler.
There are two different ways to popup the window (in any case I use always full url path):
/*-------------------------------
POPUP.JS
Simple Popup plugin for jQuery
#author Todd Francis
#version 2.2.3
-------------------------------*/
;(function(b,t){b.fn.popup=function(h){var q=this.selector,m=new b.Popup(h);b(document).on("click.popup",q,function(n){var k=h&&h.content?h.content:b(this).attr("href");n.preventDefault();m.open(k,void 0,this)});return this.each(function(){b(this).data("popup",m)})};b.Popup=function(h){function q(a){var d;b.each(a,function(a,c){if(c)return d=c,!1});return d}function m(a){return"function"===typeof a?"function":a instanceof b?"jQuery":"#"===a.substr(0,1)||"."===a.substr(0,1)?"inline":-1!==b.inArray(a.substr(a.length-
3),u)?"image":"http"===a.substr(0,4)?"external":"ajax"}function n(c){r&&r.fadeOut("fast",function(){b(this).remove()});var d=!0;void 0===f&&(d=!1,f=b('<div class="'+a.o.containerClass+'">'),p=b(a.o.markup).appendTo(f),b(a.o.closeContent).one("click",function(){a.close()}).appendTo(f),b(t).resize(a.center),f.appendTo(b("body")).css("opacity",0));var e=b("."+a.o.contentClass,f);a.width?e.css("width",a.width,10):e.css("width","");a.height?e.css("height",a.height,10):e.css("height","");p.hasClass(a.o.contentClass)?
p.html(c):p.find("."+a.o.contentClass).html(c);d?a.o.replaced.call(a,f,g):a.o.show.call(a,f,g)}function k(a,d){var b=(new RegExp("[?&]"+a+"=([^&]*)")).exec(d);return b&&decodeURIComponent(b[1].replace(/\+/g," "))}var a=this,u=["png","jpg","gif"],l,s,g,f,r,p;a.ele=void 0;a.o=b.extend(!0,{},{backClass:"popup_back",backOpacity:.7,containerClass:"popup_cont",closeContent:'<div class="popup_close">×</div>',markup:'<div class="popup"><div class="popup_content"/></div>',contentClass:"popup_content",
preloaderContent:'<p class="preloader">Loading</p>',activeClass:"popup_active",hideFlash:!1,speed:200,popupPlaceholderClass:"popup_placeholder",keepInlineChanges:!0,modal:!1,content:null,type:"auto",width:null,height:null,typeParam:"pt",widthParam:"pw",heightParam:"ph",beforeOpen:function(a){},afterOpen:function(){},beforeClose:function(){},afterClose:function(){},error:function(){},show:function(a,b){var e=this;e.center();a.animate({opacity:1},e.o.speed,function(){e.o.afterOpen.call(e)})},replaced:function(a,
b){this.center().o.afterOpen.call(this)},hide:function(a,b){void 0!==a&&a.animate({opacity:0},this.o.speed)},types:{inline:function(c,d){var e=b(c);e.addClass(a.o.popupPlaceholderClass);a.o.keepInlineChanges||(s=e.html());d.call(this,e.children())},image:function(c,d){var e=this;b("<img />").one("load",function(){var a=this;setTimeout(function(){d.call(e,a)},0)}).one("error",function(){a.o.error.call(a,c,"image")}).attr("src",c).each(function(){this.complete&&b(this).trigger("load")})},external:function(c,
d){var e=b("<iframe />").attr({src:c,frameborder:0,width:a.width,height:a.height});d.call(this,e)},html:function(a,b){b.call(this,a)},jQuery:function(a,b){b.call(this,a.html())},"function":function(b,d){d.call(this,b.call(a))},ajax:function(c,d){b.ajax({url:c,success:function(a){d.call(this,a)},error:function(b){a.o.error.call(a,c,"ajax")}})}}},h);a.open=function(c,d,e){c=void 0===c||"#"===c?a.o.content:c;if(null===c)return a.o.error.call(a,c,l),!1;void 0!==e&&(a.ele&&a.o.activeClass&&b(a.ele).removeClass(a.o.activeClass),
a.ele=e,a.ele&&a.o.activeClass&&b(a.ele).addClass(a.o.activeClass));if(void 0===g){g=b('<div class="'+a.o.backClass+'"/>').appendTo(b("body")).css("opacity",0).animate({opacity:a.o.backOpacity},a.o.speed);if(!a.o.modal)g.one("click.popup",function(){a.close()});a.o.hideFlash&&b("object, embed").css("visibility","hidden");a.o.preloaderContent&&(r=b(a.o.preloaderContent).appendTo(b("body")))}d=q([d,a.o.type]);l=d="auto"===d?m(c):d;a.width=a.o.width?a.o.width:null;a.height=a.o.height?a.o.height:null;
if(-1===b.inArray(d,["inline","jQuery","function"])){e=k(a.o.typeParam,c);var f=k(a.o.widthParam,c),h=k(a.o.heightParam,c);d=null!==e?e:d;a.width=null!==f?f:a.width;a.height=null!==h?h:a.height}a.o.beforeOpen.call(a,d);a.o.types[d]?a.o.types[d].call(a,c,n):a.o.types.ajax.call(a,c,n)};a.close=function(){a.o.beforeClose.call(a);"inline"===l&&a.o.keepInlineChanges&&(s=b("."+a.o.contentClass).html());void 0!==g&&g.animate({opacity:0},a.o.speed,function(){a.cleanUp()});a.o.hide.call(a,f,g);return a};a.cleanUp=
function(){g.add(f).remove();f=g=void 0;b(t).unbind("resize",a.center);a.o.hideFlash&&b("object, embed").css("visibility","visible");a.ele&&a.o.activeClass&&b(a.ele).removeClass(a.o.activeClass);var c=b("."+a.o.popupPlaceholderClass);"inline"==l&&c.length&&c.html(s).removeClass(a.o.popupPlaceholderClass);l=null;a.o.afterClose.call(a);return a};a.center=function(){f.css(a.getCenter());g.css({height:document.documentElement.clientHeight});return a};a.getCenter=function(){var a=f.children().outerWidth(!0),
b=f.children().outerHeight(!0);return{top:.5*document.documentElement.clientHeight-.5*b,left:.5*document.documentElement.clientWidth-.5*a}}}})(jQuery,window);
$(function () {
// first method
$('.default_popup').popup();
// second method
$('.default_popup1').click(function(e) {
e.preventDefault();
var popup = new $.Popup();
popup.open('http://stackoverflow.com/');
});
});
/*-------------------------------
POPUP.CSS
-------------------------------*/
.popup_back {
height: 100%;
left: 0;
position: fixed;
top: 0;
width: 100%;
z-index: 100;
}
.popup_cont {
position: fixed;
z-index: 102;
}
.preloader {
z-index: 101;
}
/*---------------------
EDIT BELOW
*/
.popup_close {
color: #888;
cursor: pointer;
position: absolute;
padding: 5px;
right: 5px;
top: 0;
}
.popup_close:hover {
color: #111;
}
.popup_back {
cursor: pointer;
background-color: #222;
}
div.popup {
background: #fff;
padding: 25px;
box-shadow: 0 3px 10px #222;
}
.preloader {
left: 50%;
margin: -10px 0 0 -25px;
position: fixed;
top: 50%;
}
<script src="//code.jquery.com/jquery-1.11.3.js"></script>
<div id="btn-help" class="toy-button">
<span lang="en">
HELP1
</span>
</div>
<div id="btn-help1" class="toy-button">
<span lang="en">
HELP2
</span>
</div>
I am trying to build a slider based upon http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/. My goal is to make a horizontal, mobile-only slider that allows you to slide back and forth between the steps in a registration process.
The code works for the most part, but the slider only moves every other touch, and I'm not sure why.
http://codepen.io/anon/pen/zKhao
HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="visible-xs mobile-tabs">
<div class="slider-wrap">
<div class="slider" id="slider">
<div class="holder">
<div class="slide-wrapper">
<h4 class="complete">Before you begin</h4>
</div>
<div class="slide-wrapper">
<h4 class="complete">1. Terms & Conditions</h4>
</div>
<div class="slide-wrapper">
<h4 class="current">2. Teams</h4>
</div>
<div class="slide-wrapper">
<h4>3. Add-Ons</h4>
</div>
<div class="slide-wrapper">
<h4>4. Review & Submit</h4>
</div>
</div>
</div>
</div>
</div>
CSS:
a
{
color: #5fa4db;
text-decoration: none;
}
.mobile-tabs
{
height: 45px;
overflow: hidden;
border-bottom: 1px solid #f1f2f4;
white-space: nowrap;
margin-bottom: 10px;
}
.mobile-tabs h4
{
color: #9fa9b2;
display: inline-block;
padding-right: 10px;
padding-bottom: 10px;
font-weight: bold;
font-size: 18px;
}
.mobile-tabs h4.current
{
border-bottom: 5px solid #5fa4db;
color: #0f2034;
}
.mobile-tabs h4.complete
{
color: #5fa4db;
}
/* CSS for mobile tab slider.
Source: http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/
*/
.mobile-tabs .animate {
transition: transform 0.3s ease-out;
}
.mobile-tabs .slider-wrap {
width: 100%;
position: absolute;
}
.mobile-tabs .slider {
width: 100%;
height: 100%;
overflow: hidden;
}
.mobile-tabs .ms-touch.slider {
overflow-x: scroll;
overflow-y: hidden;
-ms-overflow-style: none;
/* Hides the scrollbar. */
-ms-scroll-chaining: none;
/* Prevents Metro from swiping to the next tab or app. */
-ms-scroll-snap-type: mandatory;
/* Forces a snap scroll behavior on your images. */
-ms-scroll-snap-points-x: snapInterval(0%, 1%);
/* Defines the y and x intervals to snap to when scrolling. */
}
.mobile-tabs .holder {
width: 300%;
overflow-y: hidden;
}
.mobile-tabs .slide-wrapper {
float: left;
position: relative;
overflow: hidden;
}
.mobile-tabs .slide div {
width: 300px;
height: 500px;
z-index: 0;
}
JavaScript:
if (navigator.msMaxTouchPoints) {
$('#slider').addClass('ms-touch');
$('#slider').on('scroll', function () {
$('.slide-image').css('transform', 'translate3d(-' + (100 - $(this).scrollLeft() / 6) + 'px,0,0)');
});
} else {
var slider = {
el: {
slider: $("#slider"),
holder: $(".holder")
},
slideWidth: $('#slider').width(),
touchstartx: undefined,
touchmovex: undefined,
movex: 0,
index: 0,
longTouch: undefined,
init: function () {
this.bindUIEvents();
},
bindUIEvents: function () {
this.el.holder.on("touchstart", function (event) {
slider.start(event);
});
this.el.holder.on("touchmove", function (event) {
slider.move(event);
});
this.el.holder.on("touchend", function (event) {
slider.end(event);
});
},
start: function (event) {
// Test for flick.
this.longTouch = false;
setTimeout(function () {
window.slider.longTouch = true;
}, 250);
// Get the original touch position.
this.oldx = this.movex;
// The movement gets all janky if there's a transition on the elements.
$('.animate').removeClass('animate');
},
move: function (event) {
// Continuously return touch position.
this.touchmovex = event.originalEvent.touches[0].pageX;
// Calculate distance to translate holder.
this.movex = -this.oldx - this.touchmovex;
// Defines the speed the images should move at.
var panx = 100 - this.movex / 6;
if (this.movex < 600) { // Makes the holder stop moving when there is no more content.
this.el.holder.css('transform', 'translate3d(-' + this.movex + 'px,0,0)');
}
},
end: function (event) {
}
};
slider.init();
}
In order to emulate the issue, you'll have to view the code on a mobile device (or use Chrome's mobile emulation) and try to slide the slider back and forth. It will move, but only every other time you attempt to slide it.
I am completely lost, and any help will be appreciated.
This isn't really an answer, per se, but I've decided to throw the entire thing out and use jquery UI's Draggable feature to do what I need to do.
http://jqueryui.com/draggable/#constrain-movement
I am going to make a button to take an action and save the data into a database.
Once the user clicks on the button, I want a JavaScript alert to offer “yes” and “cancel” options. If the user selects “yes”, the data will be inserted into the database, otherwise no action will be taken.
How do I display such a dialog?
You’re probably looking for confirm(), which displays a prompt and returns true or false based on what the user decided:
if (confirm('Are you sure you want to save this thing into the database?')) {
// Save it!
console.log('Thing was saved to the database.');
} else {
// Do nothing!
console.log('Thing was not saved to the database.');
}
var answer = window.confirm("Save data?");
if (answer) {
//some code
}
else {
//some code
}
Use window.confirm instead of alert. This is the easiest way to achieve that functionality.
How to do this using 'inline' JavaScript:
<form action="http://www.google.com/search">
<input type="text" name="q" />
<input type="submit" value="Go"
onclick="return confirm('Are you sure you want to search Google?')"
/>
</form>
Avoid inline JavaScript - changing the behaviour would mean editing every instance of the code, and it isn’t pretty!
A much cleaner way is to use a data attribute on the element, such as data-confirm="Your message here". My code below supports the following actions, including dynamically-generated elements:
a and button clicks
form submits
option selects
jQuery:
$(document).on('click', ':not(form)[data-confirm]', function(e){
if(!confirm($(this).data('confirm'))){
e.stopImmediatePropagation();
e.preventDefault();
}
});
$(document).on('submit', 'form[data-confirm]', function(e){
if(!confirm($(this).data('confirm'))){
e.stopImmediatePropagation();
e.preventDefault();
}
});
$(document).on('input', 'select', function(e){
var msg = $(this).children('option:selected').data('confirm');
if(msg != undefined && !confirm(msg)){
$(this)[0].selectedIndex = 0;
}
});
HTML:
<!-- hyperlink example -->
Anchor
<!-- button example -->
<button type="button" data-confirm="Are you sure you want to click the button?">Button</button>
<!-- form example -->
<form action="http://www.example.com" data-confirm="Are you sure you want to submit the form?">
<button type="submit">Submit</button>
</form>
<!-- select option example -->
<select>
<option>Select an option:</option>
<option data-confirm="Are you want to select this option?">Here</option>
</select>
JSFiddle demo
You have to create a custom confirmBox. It is not possible to change the buttons in the dialog displayed by the confirm function.
jQuery confirmBox
See this example: https://jsfiddle.net/kevalbhatt18/6uauqLn6/
<div id="confirmBox">
<div class="message"></div>
<span class="yes">Yes</span>
<span class="no">No</span>
</div>
function doConfirm(msg, yesFn, noFn)
{
var confirmBox = $("#confirmBox");
confirmBox.find(".message").text(msg);
confirmBox.find(".yes,.no").unbind().click(function()
{
confirmBox.hide();
});
confirmBox.find(".yes").click(yesFn);
confirmBox.find(".no").click(noFn);
confirmBox.show();
}
Call it by your code:
doConfirm("Are you sure?", function yes()
{
form.submit();
}, function no()
{
// Do nothing
});
Pure JavaScript confirmBox
Example: http://jsfiddle.net/kevalbhatt18/qwkzw3rg/127/
<div id="id_confrmdiv">confirmation
<button id="id_truebtn">Yes</button>
<button id="id_falsebtn">No</button>
</div>
<button onclick="doSomething()">submit</button>
Script
<script>
function doSomething(){
document.getElementById('id_confrmdiv').style.display="block"; //this is the replace of this line
document.getElementById('id_truebtn').onclick = function(){
// Do your delete operation
alert('true');
};
document.getElementById('id_falsebtn').onclick = function(){
alert('false');
return false;
};
}
</script>
CSS
body { font-family: sans-serif; }
#id_confrmdiv
{
display: none;
background-color: #eee;
border-radius: 5px;
border: 1px solid #aaa;
position: fixed;
width: 300px;
left: 50%;
margin-left: -150px;
padding: 6px 8px 8px;
box-sizing: border-box;
text-align: center;
}
#id_confrmdiv button {
background-color: #ccc;
display: inline-block;
border-radius: 3px;
border: 1px solid #aaa;
padding: 2px;
text-align: center;
width: 80px;
cursor: pointer;
}
#id_confrmdiv .button:hover
{
background-color: #ddd;
}
#confirmBox .message
{
text-align: left;
margin-bottom: 8px;
}
Or simply:
click me!
This plugin can help you jquery-confirm easy to use
$.confirm({
title: 'Confirm!',
content: 'Simple confirm!',
confirm: function(){
alert('Confirmed!');
},
cancel: function(){
alert('Canceled!')
}
});
This a full responsive solution using vanilla javascript :
// Call function when show dialog btn is clicked
document.getElementById("btn-show-dialog").onclick = function(){show_dialog()};
var overlayme = document.getElementById("dialog-container");
function show_dialog() {
/* A function to show the dialog window */
overlayme.style.display = "block";
}
// If confirm btn is clicked , the function confim() is executed
document.getElementById("confirm").onclick = function(){confirm()};
function confirm() {
/* code executed if confirm is clicked */
overlayme.style.display = "none";
}
// If cancel btn is clicked , the function cancel() is executed
document.getElementById("cancel").onclick = function(){cancel()};
function cancel() {
/* code executed if cancel is clicked */
overlayme.style.display = "none";
}
.popup {
width: 80%;
padding: 15px;
left: 0;
margin-left: 5%;
border: 1px solid rgb(1,82,73);
border-radius: 10px;
color: rgb(1,82,73);
background: white;
position: absolute;
top: 15%;
box-shadow: 5px 5px 5px #000;
z-index: 10001;
font-weight: 700;
text-align: center;
}
.overlay {
position: fixed;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,.85);
z-index: 10000;
display :none;
}
#media (min-width: 768px) {
.popup {
width: 66.66666666%;
margin-left: 16.666666%;
}
}
#media (min-width: 992px) {
.popup {
width: 80%;
margin-left: 25%;
}
}
#media (min-width: 1200px) {
.popup {
width: 33.33333%;
margin-left: 33.33333%;
}
}
.dialog-btn {
background-color:#44B78B;
color: white;
font-weight: 700;
border: 1px solid #44B78B;
border-radius: 10px;
height: 30px;
width: 30%;
}
.dialog-btn:hover {
background-color:#015249;
cursor: pointer;
}
<div id="content_1" class="content_dialog">
<p>Lorem ipsum dolor sit amet. Aliquam erat volutpat. Maecenas non tortor nulla, non malesuada velit.</p>
<p>Aliquam erat volutpat. Maecenas non tortor nulla, non malesuada velit. Nullam felis tellus, tristique nec egestas in, luctus sed diam. Suspendisse potenti.</p>
</div>
<button id="btn-show-dialog">Ok</button>
<div class="overlay" id="dialog-container">
<div class="popup">
<p>This will be saved. Continue ?</p>
<div class="text-right">
<button class="dialog-btn btn-cancel" id="cancel">Cancel</button>
<button class="dialog-btn btn-primary" id="confirm">Ok</button>
</div>
</div>
</div>
You can intercept the onSubmit event using JavaScript.
Then call a confirmation alert and then grab the result.
Another way to do this:
$("input[name='savedata']").click(function(e){
var r = confirm("Are you sure you want to save now?");
//cancel clicked : stop button default action
if (r === false) {
return false;
}
//action continues, saves in database, no need for more code
});
xdialog provides a simple API xdialog.confirm(). Code snippet is following. More demos can be found here
document.getElementById('test').addEventListener('click', test);
function test() {
xdialog.confirm('Are you sure?', function() {
// do work here if ok/yes selected...
console.info('Done!');
}, {
style: 'width:420px;font-size:0.8rem;',
buttons: {
ok: 'yes text',
cancel: 'no text'
},
oncancel: function() {
console.warn('Cancelled!');
}
});
}
<link href="https://cdn.jsdelivr.net/gh/xxjapp/xdialog#3/xdialog.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/gh/xxjapp/xdialog#3/xdialog.min.js"></script>
<button id="test">test</button>
Made super simple, tiny vanilla js confirm dialog with Yes and No buttons.
It's a pity we can't customize the native one.
https://www.npmjs.com/package/yesno-dialog.
Another solution apart from the others is to use the new dialog element. You need to make use of show or showModal methods based on interactivity with other elements. close method can be used for closing the open dialog box.
<dialog>
<button class="yes">Yes</button>
<button class="no">No</button>
</dialog>
const dialogEl = document.querySelector("dialog");
const openDialog = document.querySelector("button.open-dialog");
const yesBtn = document.querySelector(".yes");
const noBtn = document.querySelector(".no");
const result = document.querySelector(".result");
openDialog.addEventListener("click", () => {
dialogEl.showModal();
});
yesBtn.addEventListener("click", () => {
// Below line can be replaced by your DB query
result.textContent = "This could have been your DB query";
dialogEl.close();
});
noBtn.addEventListener("click", () => {
result.textContent = "";
dialogEl.close();
});
#import url('https://fonts.googleapis.com/css2?family=Roboto:wght#300&display=swap');
body {
font-family: "Roboto";
}
button {
background: hsl(206deg 64% 51%);
color: white;
padding: 0.5em 1em;
border: 0 none;
cursor: pointer;
}
dialog {
border: 0 none;
}
.result {
margin-top: 1em;
}
<dialog>
<button class="yes">Yes</button>
<button class="no">No</button>
</dialog>
<button class="open-dialog">Click me</button>
<div class="result"></div>
Can I use?
Right now the compatibility is great with all the modern browsers.
I'm currently working on a web workflow which already has it's own notifications/dialog boxes, and I recently (like, today) created a tiny, custom (and tailored to the project needs) YES/NO dialog box.
All dialog boxes appeard over a modal layer. Full user attention is required.
I define the options configurations in this way. This options are used to define the buttons text, and the values associated to each button when there clicked:
optionsConfig = [
{ text: 'Yes', value: true },
{ text: 'No', value: false }
]
The use of the function goes something like this:
const answer = await notifier.showDialog('choose an option', options.config);
if (answer) {
// 'Yes' was clicked
} else {
// 'No' was clicked!
}
What I do, it's simply creating a async event handler for each option, it means, there is a simple handler assigned to each button. Each handler returns the value of the option. The handlers are pushed inside an array.
The array is then passed to Promise.race, and that is the return value of the showDialog method, which will correspond to the value's actual value (the one returned by the handler).
Can't provide too much code. As I said it's a very specific case, but the idea may be usefull for other implementations. Twenty lines of code or so.
A vanilla JavaScript option with a class for creating the custom modal dialog which includes a text box:
jsfiddle:
https://jsfiddle.net/craigdude/uh82mjtb/2/
html:
<!DOCTYPE html>
<html>
<style>
.modal_dialog
{
box-sizing: border-box;
background-color: #ededed;
border-radius: 5px;
border: 0.5px solid #ccc;
font-family: sans-serif;
left: 30%;
margin-left: -50px;
padding: 15px 10px 10px 5px;
position: fixed;
text-align: center;
width: 320px;
}
</style>
<script src="./CustomModalDialog.js"></script>
<script>
var gCustomModalDialog = null;
/** this could be static html from the page in an "invisible" state */
function generateDynamicCustomDialogHtml(){
var html = "";
html += '<div id="custom_modal_dialog" class="modal_dialog">';
html += 'Name: <input id="name" placeholder="Name"></input><br><br>';
html += '<button id="okay_button">OK</button>';
html += '<button id="cancel_button">Cancel</button>';
html += '</div>';
return html;
}
function onModalDialogOkayPressed(event) {
var name = document.getElementById("name");
alert("Name entered: "+name.value);
}
function onModalDialogCancelPressed(event) {
gCustomModalDialog.hide();
}
function setupCustomModalDialog() {
var html = generateDynamicCustomDialogHtml();
gCustomModalDialog = new CustomModalDialog(html, "okay_button", "cancel_button",
"modal_position", onModalDialogOkayPressed, onModalDialogCancelPressed);
}
function showCustomModalDialog() {
if (! gCustomModalDialog) {
setupCustomModalDialog();
}
gCustomModalDialog.show();
gCustomModalDialog.setFocus("name");
}
</script>
<body>
<button onclick="showCustomModalDialog(this)">Show Dialog</button><br>
Some content
<div id="modal_position">
</div>
Some additional content
</body>
</html>
CustomModalDialog.js:
/** Encapsulates a custom modal dialog in pure JS
*/
class CustomModalDialog {
/**
* Constructs the modal content
* #param htmlContent - content of the HTML dialog to show
* #param okayControlElementId - elementId of the okay button, image or control
* #param cancelControlElementId - elementId of the cancel button, image or control
* #param insertionElementId - elementId of the <div> or whatever tag to
* insert the html at within the document
* #param callbackOnOkay - method to invoke when the okay button or control is clicked.
* #param callbackOnCancel - method to invoke when the cancel button or control is clicked.
* #param callbackTag (optional) - to allow object to be passed to the callbackOnOkay
* or callbackOnCancel methods when they're invoked.
*/
constructor(htmlContent, okayControlElementId, cancelControlElementId, insertionElementId,
callbackOnOkay, callbackOnCancel, callbackTag) {
this.htmlContent = htmlContent;
this.okayControlElementId = okayControlElementId;
this.cancelControlElementId = cancelControlElementId;
this.insertionElementId = insertionElementId;
this.callbackOnOkay = callbackOnOkay;
this.callbackOnCancel = callbackOnCancel;
this.callbackTag = callbackTag;
}
/** shows the custom modal dialog */
show() {
// must insert the HTML into the page before searching for ok/cancel buttons
var insertPoint = document.getElementById(this.insertionElementId);
insertPoint.innerHTML = this.htmlContent;
var okayControl = document.getElementById(this.okayControlElementId);
var cancelControl = document.getElementById(this.cancelControlElementId);
okayControl.addEventListener('click', event => {
this.callbackOnOkay(event, insertPoint, this.callbackTag);
});
cancelControl.addEventListener('click', event => {
this.callbackOnCancel(event, insertPoint, this.callbackTag);
});
} // end: method
/** hide the custom modal dialog */
hide() {
var insertPoint = document.getElementById(this.insertionElementId);
var okayControl = document.getElementById(this.okayControlElementId);
var cancelControl = document.getElementById(this.cancelControlElementId);
insertPoint.innerHTML = "";
okayControl.removeEventListener('click',
this.callbackOnOkay,
false
);
cancelControl.removeEventListener('click',
this.callbackOnCancel,
false
);
} // end: method
/** sets the focus to given element id
*/
setFocus(elementId) {
var focusElement = document.getElementById(elementId);
focusElement.focus();
if (typeof focusElementstr === "HTMLInputElement")
focusElement.select();
}
} // end: class
The easiest way to ask before action on click is following
<a onclick="return askyesno('Delete this record?');" href="example.php?act=del&del_cs_id=<?php echo $oid; ?>">
<button class="btn btn-md btn-danger">Delete </button>
</a>
document.getElementById("button").addEventListener("click", function(e) {
var cevap = window.confirm("Satın almak istediğinizden emin misiniz?");
if (cevap) {
location.href='Http://www.evdenevenakliyat.net.tr';
}
});