Detect user selection within html element - javascript

How can I detect if a user selection (highlighting with mouse) is within/a child of a certain element?
Example:
<div id="parent">
sdfsdf
<div id="container">
some
<span>content</span>
</div>
sdfsd
</div>
pseudo code:
if window.getSelection().getRangeAt(0) is a child of #container
return true;
else
return false;

Using jQuery on() event handler
$(function() {
$("#container > * ").on("click",
function(event){
return true;
});
});​
Edit: http://jsfiddle.net/9DMaG/1/
<div id="parent">outside
<div id="container">
outside
<span>first_span_clickMe</span>
<span>second_span_clickMe</span>
</div>
outside</div>
$(function() {
$("#container > span").on("click", function(){
$('body').append("<br/>child clicked");
});
});​
​

Ok I managed to solve this in a "dirty" way. The code could use improvement but it did the job for me and I am lazy to change it now. Basically I loop through the object of the selection checking if at some point it reaches an element with the specified class.
var inArticle = false;
// The class you want to check:
var parentClass = "g-body";
function checkParent(e){
if(e.parentElement && e.parentElement != $('body')){
if ($(e).hasClass(parentClass)) {
inArticle = true;
return true;
}else{
checkParent(e.parentElement);
}
}else{
return false;
}
}
$(document).on('mouseup', function(){
// Check if there is a selection
if(window.getSelection().type != "None"){
// Check if the selection is collapsed
if (!window.getSelection().getRangeAt(0).collapsed) {
inArticle = false;
// Check if selection has parent
if (window.getSelection().getRangeAt(0).commonAncestorContainer.parentElement) {
// Pass the parent for checking
checkParent(window.getSelection().getRangeAt(0).commonAncestorContainer.parentElement);
};
if (inArticle === true) {
// If in element do something
alert("You have selected something in the target element");
}
};
}
});
JSFiddle

Related

How to link div visibility with input text by simple if condition statement

I want to link the visibility of two html div with whether input has value or not by very simple if condition statement but I may have problem in it.
html:
<input id="tags" />
<div id="div1" >
this is first div means input don't have value values
</div>
<div id="div2" >
this is second div means input does have value.
</div>
script:
$('#tags').on('keyup',function(e){
var div1 = $('#div1');
var div2 = $('#div2');
var txt=$(this).val ;
if (txt.length == 0){
div1.hide();
div2.show();
} else {
div1.show();
div2.hide();
}
});
It works only by the first time I type to input.
Can anyone help me please?
use this :
var txt=$(this).val() ;
instead of
var txt=$(this).val ;
Refer jQuery docs for correct usage of val() function.
Error:Invalid jquery Object change to val() instead of val .And validate the length.use with trim() for remove the unwanted space otherwise it will be count the empty spaces also
$('#tags').on('keyup', function(e) {
var div1 = $('#div1');
var div2 = $('#div2');
var txt = $(this).val().trim().length;
if (txt.length == 0) {
div1.hide();
div2.show();
} else {
div1.show();
div2.hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="tags" />
<div id="div1">
this is first div means input don't have value values
</div>
<div id="div2">
this is second div means input does have value.
</div>
Use $(this).val().length
<input id="tags" />
<div id="div1" >
this is first div means input don't have value values
</div>
<div id="div2" >
this is second div means input does have value.
</div>
$('#tags').keyup(function() {
// If value is not empty
if ($(this).val().length == 0) {
div1.hide();
div2.show();
} else {
div1.show();
div2.hide();
}
}).keyup(); // Trigger the keyup event on page load
$(function(){
$('#tags').on('keyup',function(e){
var div1 = $('#div1');
var div2 = $('#div2');
var txt=$(this).val() ;
if (!txt.length){
div1.show();
div2.hide();
} else {
div1.hide();
div2.show();
}
});
});
// Declaring outside of the functions speeds up the page because it prevents
// jQuery from parsing the hole html document again.
var div1 = $('#div1');
var div2 = $('#div2');
// Declare the function outside of jQuery so that we can init the fields
function handleKeyup(event) {
var content = event.target.value;
if (content.length !== 0) {
div1.hide();
div2.show();
return;
}
div1.show();
div2.hide();
}
// Call the function with no data to init the div fields
handleKeyup({ target: { value: '' } });
// Register the keyup listener
$('#tags').on('keyup', handleKeyup);
Hope it helps. Here's a pen of the working code: https://codepen.io/flasd/pen/mMXYMa

addEventListener for the same event

So I have a few div tags that I have currently hidden, and I want to display them one after the other by hitting the enter key.
What I want to happen: I hit enter and the first div tag is revealed, and then I hit enter a second time to see the second div tag.
What is happening instead: I hit enter once and both div tags show up.
In this case, the first div tag I want to reveal is "intro", and the second is "body". I am running this website on jsbin, and I am using chrome, if that helps.
This is my JavaScript:
//***********************************************************
// BODY MODULE
var bodyController = (function(){
var enterBool;
var reveal = function(){
if(enterBool){
document.getElementById("evidence").style.display = "block";
enterBool = false;
}
};
var enterListen = function(){
document.addEventListener("keydown", function(event){
if(event.keyCode === 13){
document.addEventListener("keyup", function(event){
if(event.keyCode === 13){
enterBool = true;
reveal();
}
});
}
});
};
return{
enterBoolBody: enterBool,
enterListenBody: function(){
enterListen();
}
}
})();
//***********************************************************
// INTRO MODULE
var introController = (function(){
var enterBool;
var reveal = function(){
if(enterBool){
document.getElementById("body").style.display = "block";
enterBool = false;
}
};
var enterListen = function(){
document.addEventListener("keydown", function(event){
if(event.keyCode === 13){
document.addEventListener("keyup", function(event){
if(event.keyCode === 13){
enterBool = true;
reveal();
}
});
}
});
};
return{
enterBoolIntro: enterBool,
enterListenIntro: function(){
enterListen();
}
}
})();
//***********************************************************
// CONTROL MODULE
var controller = (function(introCtrl, bodyCtrl, evidenceCtrl, infoCtrl,
conclusionCtrl){
var eventListeners = function(){
introCtrl.enterListenIntro();
bodyCtrl.enterListenBody();
};
return{
init: function(){
eventListeners();
}
}
})(introController, bodyController, evidenceController,
infoController, conclusionController);
//***********************************************************
controller.init();
I think you might be over engineering this a bit. All you need is an event listener to check for enter. Then you check if the first div is shown, if not show it. If the first div is shown check if the second div is shown and show it.
Quick note, no IE9 support for classList if that's important to you.
https://caniuse.com/#feat=classlist
(function(window, document, undefined)
{
document.addEventListener('keyup', showDivs, false);
})(window, window.document);
function showDivs(event)
{
event = event || window.event;
var divsToShow = document.getElementsByClassName("Display-Div");
for (var i = 0; i < divsToShow.length; i++) {
if (!divsToShow[i].classList.contains("Block")) {
divsToShow[i].classList.add("Block");
break;
}
}
}
.Hidden {
display: none;
}
.Block {
display: block;
}
<div class="Hidden Display-Div">This</div>
<div class="Hidden Display-Div">Now</div>
<div class="Hidden Display-Div">Works</div>
<div class="Hidden Display-Div">With</div>
<div class="Hidden Display-Div">Any</div>
<div class="Hidden Display-Div">Div</div>
<div class="Hidden Display-Div">With</div>
<div class="Hidden Display-Div">Class</div>
<div class="Hidden Display-Div">Display-Div</div>
You can put the ids of your divs in an array, or you could assign a common class to all divs that you want to appear one by one. Assuming the first, this code simply grabs the id of the next div to display from the array and increments the counter. You could add more divs to the array and it would work.
var divs = ["evidence", "body"];
var counter = 0;
document.addEventListener("keyup", function(event){
if(counter < divs.length && event.keyCode == 13){
document.getElementById(divs[counter]).style.display = 'block';
counter++;
}
});

button continually only fire once

If keep clicking the same buttons then only fire once. sample: https://jsfiddle.net/h4wgxofh/, For example, if click1 clicked then 2nd time or more times clicks should stop firing, the same as click2 however, if I click the same button, it always fires. Also I want links only trigger once but becomes available if other buttons being clicked. (considering if more buttons) Thanks
HTML
<div class="wrap">
Click1
Click2
</div>
Script
var clicked = false;
$('.wrap').on('click', 'a', function(){
var $this = $(this);
clicked = true;
if(clicked = true){
console.log($this.text());
clicked = false;
}
});
I'm probably missing something here, but why not just bind the event to every link in .wrap and unbind it on click like this :
$('.wrap a').on('click', function(){
console.log($(this).text());
$(this).unbind('click');
});
See this fiddle
Edit : after your comment on wanting one link to be rebound after cliking on another, even though it might not be the cleanest solution, this does the job :
var onclick = function(){
var $el = $(this);
console.log($el.text());
$('.wrap a').off('click', onclick);
$('.wrap a').each(function(id, link){
if($el.text() != $(link).text())
$(link).on('click', onclick);
});
}
$('.wrap a').on('click', onclick);
Fiddle again
See the following code
var clicked1 = false;
var clicked2 = false;
$('.wrap').on('click', 'a', function(){
var $this = $(this);
var clickOrigin = $(this).text();
if(clickOrigin == 'Click1' && clicked1==false){
console.log("Click 1 clicked");
clicked1 = true;
}
if(clickOrigin == 'Click2' && clicked2==false){
console.log("Click 2 clicked");
clicked2 = true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
Click1
Click2
</div>
Also you can find the jsFiddle.
You need to Distinguish between two links(i used text here you may put whatever scenario ) see this example it may help:-
var clicked1 = 0;
var clicked2 = 0;
$('.wrap').on('click', 'a', function() {
var $this = $(this);
var $text = $(this).text();
//Click2
if ($text == 'Click1') {
clicked1 += 1;
if (clicked1 == 1) {
console.log($text);
} else {
return;
}
}
//Click2
if ($text == 'Click2') {
clicked2 += 1;
if (clicked2 == 1) {
console.log($text);
} else {
return;
}
}
});
Full Demo
To disable both buttons after first click, try:
var clicked = false;
$('.wrap').on('click', 'a', function(){
let $this = $(this);
if( !clicked ){
console.log($this.text());
clicked = true;
};
});
To disable each button after first click, try:
$('.wrap a').each(function() {
let $this = $(this);
$this.disabled = false;
$this.on('click', function() {
if ( !$this.disabled ) {
console.log($this.text());
$this.disabled = true;
};
});
});
Every time someone clicks one of the buttons, your script is setting clicked from false to true, checking if the value is true, then setting it to false again. You need to format it like this if you only want the buttons to fire once (obviously you'd have to duplicate this specifically for each button with different IDs):
var clicked = false;
$('.wrap').on('click', 'a', function(){
var $this = $(this);
if(clicked == false){
console.log($this.text());
clicked = true;
}
});
try this ,much simpler and this will be more useful if you have multiple click buttons
if you had implemented some other way ,this will worth a try
<div class="wrap">
Click1
Click2
</div>
$('.wrap').on('click', 'a', function(){
var $this = $(this);
if($this.attr("data-value") == ""){
console.log($this.text());
$this.attr("data-value","clicked")
}
else{
console.log("Already clicked")
}
});
Fiddle
Instead of putting code on click just on first click disable anchor tag this serve the same thing you wants just find below snippet for more information using this we can reduces round trips to the click functions as well
$('.wrap').on('click', 'a', function(){
$(this).addClass("disableClick");
});
.disableClick{
pointer-events: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
Click1
Click2
</div>
I think you can disable anchor link after one click like this
<div class="wrap">
Click1
Click2
</div>
I think you can disable anchor link after one click like this
<div class="wrap">
Click1
Click2
</div>
$(function () {
$('#click1').on("click", function (e) {
$('#click1').on("click", function (e){
e.preventDefault();
e.preventDefault();
});
});
I think its help you.
Just use $(".wrap").one('click', ....
Read the jquery API documentation.

Drag&Drop keep behavior of editable content

i'm experimenting with Drag&Drop in Javascript. So far it is working but my editable Content within the dragable objects aren't useable anymore (hence not the way they normally are)
this is an example of an dropable object:
<div id="ziel_2" draggable="true" trvdroptarget="true">
<div> some text<br>some text</div>
<div contenteditable="true">some text</div>
</div>
the whole object shouldn't be dragged if i try to use the contenteditable div, i want to click in the text and edit it or just select some text in it ang drag it just like normal
so the question: how can i cancel the drag-event if e.target.hasAttribute("contenteditable") in ondragstart?
EDIT: this is the Code behind the Scenes so far:
function lieferungen_draggable_add_dragstart(obj)
{
obj.addEventListener('dragstart', function (e) {
if(e.target.hasAttribute("contenteditable")) { /* make something stop this thing */ }
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('Text', this.getAttribute('id'));
return false;
});
return obj;
}
EDIT2:
contenteditableDiv.addEventListener('mousedown', function() { this.parentNode.setAttribute("draggable", false); });
contenteditableDiv.addEventListener('mouseup', function() { this.parentNode.setAttribute("draggable", true); });
this worked for me based on an idea from https://stackoverflow.com/a/9339176/4232410
thanks for your help!
Check for the contentEditable status of the element and any parent elements (see the docs for info about the attribute)
for (var el = e.target; el && el !== el.parentNode; el = el.parentNode) {
if (el.contentEditable === "true") {
return false;
}
}
// Continue processing here
Try this:
if(e.target.hasAttribute("contenteditable")) { return false; }
Basically, that's saying get out and don't do anything else if the target has attribute: contenteditable

javascript sort with data handlers issue

sorry if this is a stupid question but I'm a bit of a javascript novice and I'm trying to learn better programming instead of "cheating" and writing out each event type individually.
I can't seem to get this to run. The user clicks on a link at the top of the page with a data attribute with an event types ID number in it (data-event-type="1", etc). It should hide any events without that id number. JS and HTML is below.
JS fiddle with it all
http://jsfiddle.net/96r9jqp6/
HTML
<div class="sort">
All
Trainer
Conference
</div>
<div class="events-container">
<div class="eventsys-event-wrapper" data-event-type="1">
event 1 info here
</div>
<div class="eventsys-event-wrapper" data-event-type="2">
event 2 info here
</div>
<div class="eventsys-event-wrapper" data-event-type="1">
event 3 info here
</div>
<div class="eventsys-event-wrapper" data-event-type="2">
event 4 info here
</div>
</div>
Javascript
<script src="text/javascript">
$(document).ready(function(){
$('.eventSort').click(function(){
if (event.preventDefault) event.preventDefault();
else event.returnValue = false;
var thisEventSort = $(this).attr("data-event-sort");
if (thisEventSort = "0"){
$('.eventsys-event-wrapper').show('fast');
return;
} else {
$('.eventsys-event-wrapper').each(function(){
var thisEventType = $(this).attr("data-event-type");
if (thisEventType = thisEventSort) {
$(this).show('fast');
} else {
$(this).hide('fast');
}
});
}
});
});
</script>
if (thisEventSort = "0")
needs to be
if (thisEventSort === "0")
and same for
if (thisEventType = thisEventSort)
needs to be
if (thisEventType === thisEventSort)
Something like this
$('.eventSort').click(function(e){
e.preventDefault();
var thisEventSort = $(this).data("event-sort");
$('.eventsys-event-wrapper').hide().filter(function() {
return thisEventSort === 0 ? true : ($(this).data('event-type') == thisEventSort);
}).show('fast');
});
FIDDLE
You didnt pass event also... so your if there is not needed...
and use .data("event-sort") for this...
$(document).ready(function(){
$('.eventSort').click(function(event){
event.preventDefault();
var thisEventSort = $(this).data("event-sort");
if (thisEventSort == "0"){
$('.eventsys-event-wrapper').show('fast');
return;
} else {
$('.eventsys-event-wrapper').each(function(){
var thisEventType = $(this).attr("data-event-type");
if (thisEventType == thisEventSort) {
$(this).show('fast');
} else {
$(this).hide('fast');
}
});
}
});
});
I've updated your jsfiddle here
http://jsfiddle.net/96r9jqp6/5/
the most import piece is your use of the "=" operator
you need to use triple equal to test for equality instead of just one.
also when using data-* attributes, you should use the jquery .data() function to retrieve its values
$(document).ready(function(){
$('.eventSort').click(function(){
if (event.preventDefault) event.preventDefault();
else event.returnValue = false;
var thisEventSort = $(this).data("event-sort");
console.log(thisEventSort);
if (thisEventSort === 0){
$('.eventsys-event-wrapper').show('fast');
return;
} else {
$('.eventsys-event-wrapper').each(function(){
var thisEventType = $(this).data("event-type");
if (thisEventType === thisEventSort) {
$(this).show('fast');
} else {
$(this).hide('fast');
}
});
}
});
});

Categories

Resources