contenteditable injected in the DOM is not working - javascript

I created an editable field based on "contenteditable="true" and it is working well. Content is saved to the database when the user clicks out of the div (blur).
However, when I inject an additional field with Jquery after the first one, the new field does not send content to the database when the user clicks out of the div.
I reproduced the problem in this snippet (see the console).
Any clue ?
$(document).ready(function () {
codetoinject = '<div contenteditable="true">Editable text 2</div>'
$(document).on("click", "#abutton", function (event) {
console.log("Ok");
$('#receptionarea').append(codetoinject);
})
})
$('.editablediv').blur(function () {
console.log("save content with Ajax");
// Ajax code
});
#abutton {
cursor: pointer;
border: solid;
width: 120px;
border-radius: 5px;
text-align: center;
margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="abutton">
Click here
</div>
<div id="receptionarea">
<div class="editablediv" contenteditable="true">Editable text 1</div>
</div>

The .blur function is only being applied to elements with the editablediv class, which you are not giving to the dynamically added div. Also, you'll need to modify the way you are setting up the blur event handler to use event delegation for dynamically added elements.
Also, you can set up a click event handler directly on your button. There's no need to use event delegation there.
$(document).ready(function () {
$('#abutton').on("click", function (event) {
$("#receptionarea").append('<div contenteditable="true" class="editablediv">Editable text 2</div>');
});
// You must set up event delegation for dynamically
// added elements to get hooked up to events.
$("div").on("blur",'.editablediv', function () {
console.log("save content with Ajax");
// Ajax code
});
});
#abutton {
cursor: pointer;
border: solid;
width: 120px;
border-radius: 5px;
text-align: center;
margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="abutton">Click here</div>
<div id="receptionarea">
<div class="editablediv" contenteditable="true">Editable text 1</div>
</div>

Related

Jquery click on popup div to show another div

The requirement is user can Click on black box to show orange box, and click on orange box to show red box, but the orange box and red box should be hidden
when user click anywhere of the document except the orange box or the
red box itself.
But currently the issue is that we cannot click on orange box to show red box
Would much appreciate if you could help me out, thanks a lot
Demo link: http://plnkr.co/edit/OqlfbmFPKdXx0wDhnLxZ?p=preview
$(function() {
$('#mypop').click(function(e) {
event.stopPropagation();
});
$(document).on('click', '#myclick', function() {
$('#mypop').toggle();
$(document).one('click', function() {
$('#mypop').hide();
});
});
$(document).on('click', '#myclick1', function() {
$('#mypop2').show();
});
$(document).on('click', '#myclick2', function() {
$('#mypop2').show();
});
})()
#mypop {
background-color: orange;
position: absolute;
top: 130px;
left: 50px;
width: 150px;
padding: 15px;
}
.mydiv {
background-color: black;
padding: 30px;
width: 50px;
cursor: pointer;
color: white;
}
#mypop2 {
margin-top: 150px;
background-color: red;
width: 100px;
height: 50px;
padding: 18px;
display: none;
}
#myclick1,
#myclick2 {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myclick" class='mydiv black-box'>
click me!
</div>
<div id="mypop" style="display:none;" class='orange-box'>
<p>hello world</p>
<div id='myclick1'>BUTTON1</div>
<div id='myclick2'>BUTTON2</div>
</div>
<div id="mypop2" class='red-box'>
Hello World!!!
</div>
try this. I think this is what you are excepting but I'm not sure since you keep editing your question.
Demo Link: http://plnkr.co/edit/n7rdgqTwiFrXtpgoX4TQ?p=preview
$('#myclick1').click(function(){
$('#mypop2').show();
});
$('#myclick2').click(function(){
$('#mypop2').show();
});
You have couple of things mixed up.
The main stop-point was the very first event listener
$('#mypop').click(function(e) {
which is incompatible with the rest of listeners
$(document).on('click','#myclick1',function(e){
after I have changed it to
$(document).on('click','#mypop', function(e){
the other listeners have started working.
Second thing is that for embedded elements (parent-child) you need to stop event propagation, otherwise the parent event is triggered as well (which is not desired)
$(document).on('click','#myclick1',function(e){
e.stopPropagation();
:
});
I have also changed the CSS a bit and added class hide to use instead of styles. Toggling this class is what hides and shows an element.

Don't allow child elements to be clicked

I have elements like this
<div class="parent-component">
<div class="form-group">
<label for="my-input">Label</label>
<input type="text" name="my-input" id="my-input" class="form-control">
</div>
</div>
I have attached a click listener with jQuery on method to the parent as follows
$(document).on("click", ".parent-component", function() {
// ...
})
Where ever I click inside the .parent-component the event listener fires. However, clicking on the input - or any interactive element (links, buttons, inputs) for that matter - it get's active.
How do I prevent any element inside .parent-component from being clicked so that I can have inputs and links inside it which are not able to be clicked?
This is normally desirable behaviour; a click to a child element is also a click to its parent and ancestor elements, in the same way that you can't be in your bathroom without also being in your house.
If you want to guard against child/descendant clicks, however, you can do this:
$(document).on("click", ".parent-component", function(evt) {
if (!$(evt.target).is('.parent-component')) return false;
//beyond here, we can be sure the element was to the parent directly,
//not any children/descendants
})
Another alternative, so that you can use in different places,..
Is for the controls you don't want to propagate events, you could create a class and target this, and tell them not to propagate the events..
The advantage been if you do have some controls that you do want to propagate the events you can leave the class off.
eg..
$(document).on("click", ".parent-component", function(e) {
console.log('click');
});
$(document).on('click', '.no-propagate', function (e) { e.stopPropagation(); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent-component">
<div class="form-group">
<label class="no-propagate" for="my-input">Label</label>
<input class="no-propagate" type="text" name="my-input" id="my-input" class="form-control">
<span>This still sends clicks to parent</span>
</div>
</div>
pointer-events, credit goes to #Tibos
$(document).on("click", ".parent-component", function(e) {
console.log('click on: ' + e.target.className);
});
.no-click {
pointer-events: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent-component">
<div class="form-group no-click">
<label for="my-input" style="pointer-events: none" >Label</label>
<input type="text" name="my-input" id="my-input" class="form-control" />
<span>This still sends clicks to parent</span>
</div>
</div>
You can check if the target item, which was clicked, has some class, and only then, continue.
$(document).on("click", '.someClass', function(e){
if( e.target.classList.contains('someClass') ) return false;
})
You can do this in several ways
This is just an example on you can exclude child element(s) from parent.
$(document).ready(function(){
$(document).on('click', '.main', function(e){
alert('Parent was clicked');
}).find('.child').on('click', function(){
return false;
});
});
.main{
background: orangered;
color: white;
font-weight: bold;
padding: 10px;
height: 400px;
width: 400px;
padding: 10px;
}
.child{
background: green;
color: white;
margin: auto;
height: 40%;
width: 40%;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='main'>
Click me and I will fire up something
<div class='child'>
If you click on me I will not fire.....
I am the child you cannot click me
</div>
</div>
Another way
$(document).ready(function(){
$(".main").click(function(){
alert('Parent was clicked');
}).children().click(function(){
return false;
});
});
.main{
background: orangered;
color: white;
font-weight: bold;
padding: 10px;
height: 400px;
width: 400px;
}
.child{
background: green;
color: white;
margin: auto;
height: 40%;
width: 40%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='main'>
Click me and I will fire up something
<div class='child'>
If you click on me I will not fire.....
This is the child you cannot click me
</div>
</div>

Blog / Message - How do I fix that empty message divs will piling on / next to each other and make the close button work?

So I'm making a sort of blog posting system or TODO list, however you want to call it.
I want that the following can happen / is possible:
[Working] The user types something in the textarea
[Working] The user clicks on the button.
[Working] A new div will be created with the text of the textarea.
[Working] The textarea will be empty.
[Not Working] The user has got the choice to delete the post by clicking the 'X' on the right side of each '.post' div.
BUT: If I click on the button when there's nothing in the textarea, there appears an empty div, with only an 'X' close button, no background color either. They appear on the same line as the previous message, so you can get a lot of 'X's next to each other.
AND: Clicking the 'X' close button doesn't do anything. No errors in Firefox console.
If it's not clear enough, run this JSFiddle, click the button and I think you'll understand what I mean:
JSFiddle
HTML:
<!DOCTYPE html>
<html>
<head>
<link href="main.css" rel="stylesheet">
<script src="jquery.min.js"></script>
<meta charset="UTF-8">
</head>
<body>
<div id="blog">
<h1>Blog post application</h1>
<div id="post-system">
<textarea id="poster" rows="5" cols="50" placeholder="Update status."></textarea>
<div id="button">Post</div>
<div id="posts">
</div>
</div>
</div>
</body>
</html>
jQuery Script:
<script>
$(document).ready(function () {
$('#button').click(function () {
var text = $('#poster').val();
$('#posts').prepend("<div class='post'>" + text + "<span class='close-post'>×</span></div>");
$('#poster').val('');
});
$('.close-post').click(function () {
('.close-post').parent().hide();
});
});
</script>
CSS:
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
#blog {
background-color: blue;
margin: 50px;
padding: 50px;
text-align: center;
border-radius: 10px;
color: white;
display: block;
}
#poster {
color: default;
resize: none;
border: 1px solid black;
text-decoration: blink;
font-size: 20px;
display: inline-block;
position: relative;
border-radius: 5px;
border: 2px solid black;
padding-left: 10px;
padding-top: 5px;
}
#button {
background-color: #00FFFF;
color: white;
border: 2px solid white;
border-radius: 5px;
cursor: pointer;
width: 50px;
float: left;
}
.post {
background-color: white;
color: blue;
margin-top: 20px;
width: auto;
display: block;
}
.close-post {
margin-right: 10px;
float: right;
color: red;
cursor: pointer;
}
You appear to have two issues:
1) You don't want a post to be created if the textarea is empty
Simple fix . . . check to see if it is empty, before calling the logic to add the new post (and use jQuery's $.trim() to account for only blank spaces):
$('#button').click(function() {
var text = $.trim($('#poster').val());
if (text !== "") {
$('#posts').prepend("<div class='post'>" + text + "<span class='close-post'>×</span></div>");
$('#poster').val('');
}
});
2) The 'X' buttons are not closing the posts
This also should be a pretty easy fix . . . the reason that they are not working is because the 'X' buttons don't exist when the page is loaded so $('.close-post').click(function() { is not binding to them on page load. You will need to delegate that event binding, so that it will apply to the 'X' buttons that are dynamically added after the page is loaded.
Now, not knowing what version of jQuery that you are using (I can't access jsFiddle from work), I'll point you to the right place to figure out the correct way to do it: https://api.jquery.com/on/
If it is jQuery 1.7 or higher, you would do it like this:
$("#posts").on("click", ".close-post", function() {
$(this).parent().hide();
});
If your version is earlier than that, then investigate the jQuery .delegate() and .live() methods to determine which is the right one to use for your code..
Try this:
$(document).ready(function() {
$('#button').click(function(event) {
event.preventDefault();
var text= $('#poster').val();
if (text === '') {
alert('Nothing to post!');
return;
}
$('#posts').prepend("<div class='post'>" + text + "<span class='close-post'>×</span></div>");
$('#poster').val('');
});
$('#posts').on('click', '.close-post', function() {
$(this).closest('.post').fadeOut();
});
});
JSFiddle
The way you are doing this, the user will only ever see what they are posting - if you're trying for a chat type where users talk to each other then you will need to store what is being typed on the server side and refresh the screen using something like ajax
but in response to your question, you need to bind the close click like this:
$( "#posts" ).on( "click", ".close-post", function() {
$(this).parent().hide(); // $(this) is the clicked icon, the way you did it above wouldn't as if it had the dollar, it would close all .close-post parents
});
See the part about delegated events: http://api.jquery.com/on/

Javascript - Make the whole div clicable

I have a parent div element, and within it a child div element. Now there is a click handler for the child div, it brings a drop down(like a menu).
Requirement - Is to bring the dropdown on click of the parent div also.
Note - on click of parent div, and firing childdiv.click() won't work, infinite loop.
Cannot do a stoppropagation, functionality for bringing the dropdown won't work.
$(document).ready(function(){
$("#child").click(function(){
$("ul").slideUp();
})
$("#parent").click(function(){
$("#child").trigger("click");
})
})
#parent {
padding: 50px;
background: red;
}
#child {
height: 50px;
background: green;
color: white;
}
li {
background: rgba(0,0,255,0.3);
border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="parent">Parent
<div id="child">
Child
<ul id="menu" class="hide">
<li>menu1</li>
<li>menu2</li>
</ul>
</div>
</div>
Try this adding the parent onclick event handler and then use event.stopPropagation to stop event bubbling.
$("#child").click(function(e){
e.stopPropagation();
$("ul").slideToggle();
});
$("#parent").click(function(e){
$("#child").trigger("click");
});
CHECK FIDDLE is this what you want? Not sure what you want to do next. Adding your code would have been much easier to help.

Change CSS of Dynamic List Item

===UPDATE===
If I remove the style="display: none; from the template and apply the below method as recommended below, the empty container fires when you click on any other list item. What else can be done?
I have an ul list that is dynamically created at run time using jQuery and JSON (Using inline HTML is a template). I need the background CSS style to change when a user clicks on a list item (#navItem). I've tried everything under the moon that I can think of from inline class to .appentTo(), etc. What I have below works fine for hard-coded elements but Nothing seems to work with dynamically loaded content. Whats even more confusing is that the classes in the elements within the li tag initiate...???
Any help would be appreciated. Below are my code snippets. Thnx.
HTML:
<div id="navScrollContainer" class="navContentPosition">
<ul id="navContent">
// Display as 'None' to prevent a empty containter from showing -->
<li id="navItem" class="ulFx" style="display: none;">//<-THIS NEEDS TO CHANGE ONCLICK!!
<a class="navA">
<h1 class="navH1">.</h1>
<h2 class="navH2">.</h2>
<p class="navP">.</p>
<hr class="navHR" />
</li>
</ul>
</div>
<script type="text/javascript">
$('#navScrollContainer').on('click', '.ulFx', function() {
$(this).addClass("liFx");
});
</script>
This is the Function that injects the data into the DOM as a list:
function loadNav(url, container, appendE) {
$.getJSON(url, function(data) {
$.each(data.items, function() {
var newItem = $('#' + container).clone();
// Now fill in the fields with the data
newItem.addClass('ulFx');
newItem.find("h1").text(this.label);
newItem.find("h2").text(this.title);
newItem.find("p").text(this.description);
newItem.find("a").attr("href", this.gotoURL);
newItem.children().appendTo('#' + appendE);
});
$('#navHeaderTitle').text(data.listTitle);
iniScroll('scrollNav', 'navScrollContainer');
var target = data.targetKey;
// transition("#" + pageName, "show");
});
};
The CSS that need to happen (only on that item) when the user clicks on a Item:
#-webkit-keyframes
liBG {from {
background-color: transparent
}
50% { background-color: rgba(51,102,255,0.15); }
to {
background-color: transparent
}
}
.liFx {
-webkit-animation-name: liBG;
-webkit-animation-duration: 1s;
-webkit-animation-fill-mode: forwards;
}
The Class atributes given to the li items:
.navH1 {
font-size: 18px;
color: #FFA500;
text-decoration: underline;
font-weight: bold;
margin-top: 8px;
margin-bottom: 8px;
margin-left: 15px;
}
.navH2 {
font-size: 16px;
color: #999999;
font-weight: bold;
margin-top: 5px;
margin-bottom: 5px;
margin-left: 25px;
font-weight: bold;
}
.navP {
color: #888;
font-size: 14px;
text-align: justify;
margin-top: 5px;
margin-bottom: 16px;
margin-left: 25px;
margin-right: 10px;
}
.navA {
text-decoration: none;
}
.navHR {
border: none;
background-color: #336;
height: 1px;
}
This will watch for dynamic elements:
$(".liFx").live("click", function() {
$(this).addClass("liBG");
});
Without seeing your click handler, I can only speculate. However, generally when the problem is related to dynamic content and having them respond to stimulus, the problem lies in how you are attaching the handler.
If you use .click(), or .trigger('click'), the handler will be applied directly to the elements you are calling these functions on. That means that if the elements do not currently exist, they will not receive a handler.
The way to get around this, is to attach the event listener to a parent element that will always exist and then watch for the event propagating up from the dynamic child element. You could do this manually, by looking at the event.target, but jQuery, as usual, makes this easy for us.
The modern jQuery way of doing this is using .on() (documentation):
$('#someparent').on('click', '#childselector', function() {
// my handler code
});
jQuery then attaches a handler on #someparent, and when it sees a click that was targeted at #childselector, it fires.
If you want to apply a class to a child of #navContent, and #navContent will always exist, do this:
$('#navContent').on('click', 'li', function() {
$(this).addClass("liFx");
});
If #navContent is dynamic too, simply go higher in the DOM tree.
As a side note, I notice that the li has an id of navItem. This sounds an awful lot like a class, rather than an ID. If you are going to have more than one navItem, they cannot all have the same ID. This is what classes are for:
<li class="navItem liFx" style="display: none;">
I am not sure where is the problem, but you are trying to do something as such:
$("#navlink").on('click', function() {
$("#yourselector").css("backgroundColor", "#ddd"); //change the color
});
I added another div and an addClass() method to my function along with Jeff B's answer above. If the class is hard coded into the tag, it doesnt function.
<ul id="navContent">
<li id="navItem" style="display: none;">
<div>//ADDED THIS TAG TO EXCEPT THE CLASS
<a>
<h1>.</h1>
<h2>.</h2>
<p>.</p>
<hr/>
</a>
</div>
</li>
</ul>
In my js file:
$.each(data.items, function() {
var newItem = $('#' + container).clone();
// Now fill in the fields with the data
newItem.find("div").addClass("ulFx");//ADDED THIS METHOD
newItem.find("h1").text(this.label);
newItem.find("h2").text(this.title);
newItem.find("p").text(this.description);
newItem.find("a").attr("href", this.gotoURL);
newItem.children().appendTo('#' + appendE);
});

Categories

Resources