X-Editable Bootstrap field loads only on the first link - javascript

I'm using Bootstrap X-Editable along with bootstrap-wysihtml5.
I have a comment list on every post page with an edit link under each comment.
But I can only edit the first comment on the last (the newest submitted comment) and the rest simply don't load the X-Editable field.
$('#note').editable({
validate: function(value) {
if($.trim(value) == '')
return 'Value is required.';
},
type: 'wysihtml5',
title: 'Edit Comment',
placement: 'top',
send:'always',
ajaxOptions: {
dataType: 'json',
type: 'post'
}
});
$('#pencil').click(function(e) {
e.stopPropagation();
e.preventDefault();
$('#note').editable('toggle');
});
And the HTML
<div id="note"
class="note"
data-type="wysihtml5"
data-toggle="manual"
data-pk="{{ $each_comment->id }}"
data-placement="top"
data-url="{{ url($each_comment->post_id . '/comment/update') }}">
{!! $each_comment->comment !!}
</div>
<a href="#"
id="pencil"
class="pencil"
data-type="wysihtml5"
data-toggle="manual"
data-pk="{{ $each_comment->id }}"
data-placement="top"
data-url="{{ url($each_comment->post_id . '/comment/update') }}">
<i class="icon-pencil" style="padding-right: 5px"></i>[edit]
</a>
UPDATE
I made some changes, I added a pen class to the edit link
[edit]
And I call it with a.pen
('a.pen').click(function(e) {
e.stopPropagation();
e.preventDefault();
console.log($('#note').attr("data-pk"));
$('#note').editable('toggle');
});
Now all edit links are loading the X-Editable field but they're all showing the same comment with id 142 which is the latest submitted comment.
console.log prints the same id whenever I click on the edit link.

From $('#note').editable( it looks like you're dynamically generating content with duplicate id.
id selector always returns the first match because the rule is, id should be unique in a document .
You should be using class, name or similar attributes that is allowed to be repeated instead of id.
So using class the code should be something like following:
$('.pencil').click(function(e) {
e.stopPropagation();
e.preventDefault();
$(this).prev('.note').editable('toggle');
});

Related

How can I change icon on AJax response?

I have an anchor tag with an icon inside that I want to change it on click.
So, using Ajax I tried as below:
HTML
<a id="#pl-esong234" class="social-button-song" title="Add in playlist" onclick="addInPlaylistSongs(234, 1)">
<i class="ion-plus all-btn-icon"></i>
</a>
JS
function addInPlaylistSongs(track, id) {
$.ajax({
type: "POST",
url: baseUrl+"/requests/manage_playlists.php",
data: "id="+track+"&playlist="+id+"&type=4&token_id="+token_id,
cache: false,
success: function(html) {
$('#pl-esong'+track).append('<i class="ion-checkmark all-btn-icon"></i>');
}
});
}
I tried also:
//2nd try
$('#pl-esong'+track+' i').after('<i class="ion-checkmark all-btn-icon"></i>').remove();
//3rd try
$('#pl-esong'+track+' i').after(html).remove();
//4th try
$('#pl-esong'+track+' i').replaceWith(html);
I tried to console log on success and everything is correct, the html response is <i class="ion-checkmark all-btn-icon"></i> and the select item is #pl-esong234.
Why I'm not able to change the icon inside my anchor element?
Remove the hash from the id. It is using by the selectors to find the matched tag.
# - used to find by id.
. - user to find by class
<a id="pl-esong234" class="social-button-song" title="Add in playlist" onclick="addInPlaylistSongs(234, 1)">
<i class="ion-plus all-btn-icon"></i>
</a>
and call html().
$('#pl-esong'+track+' i').html('<i class="ion-checkmark all-btn-icon"></i>');

Ajax and Mongodb, use _id

I have a test project using express.js that displays all items in a mongo database on a webpage. Each database entry is displayed on the page with a button to delete it.
-each i in docs
p ----------------------
p <strong>Name: #{i.name}
p <strong>Type: #{i.type}
p <strong>Amount: #{i.quantity}
p <strong>ID: #{i._id}
input(type = 'button', value ="delete item", id='delete')
I want the button to send a DELETE request to /api/item/_id
My script is as follows
script(type='text/javascript').
$(document).ready(function() {
$("#delete").click(function() {
$.ajax({
type: 'DELETE',
url: '/api/item/' + this._id
}).done(function(result) {
});
});
});
This is not sending the desired request. How would I go about passing the _id from the item to the button?
If I set the URL to a know _id, like below, it works and the item is deleted
url: '/api/item/56f3e800d6f24d0819e43fcc'
Thanks in advace
Use data- attribute
Html
<input type="button" id="delete" data-id="mongo id here" />
JS
$.ajax({
type: 'DELETE',
url: '/api/item/' + this.attr('data-id')
})
Also you'd better use class instead of id="delete"
If I understand your looping code you appear to be assigning the same HTML ID attribute to each button:
input(type = 'button', value ="delete item", id='delete')
That makes for invalid HTML (only one item can have a given ID). You can make the delete attribute a class where its legal to have more than one item with the same class.
If you console.log(this) when any of these buttons are clicked what is this referring to? What _id do you get? Do you get the same _id regardless of what button is clicked?

How can I make dynamic Ajax requests with Laravel

I'm creating a social network site using Laravel. I have a page that load all the posts created by users the currentUser follows. I have a comment section on each post. I want a user to be able to comment on any post without the page reloading so the user doesn't have to re-scroll through the page.
I have everything working fine without ajax (minus the reloading page). I'm able to post comments, the page reloads and the new comment is displayed. However, when I try to use Ajax I've been running into problems.
Here is my code.
Here is the view of the comment-box. It contains a section where I loop through each comment and display them. At the end is the type field so a user can post a new comment:
<div class="comment-box-container ajax-refresh">
<div class="comment-box">
#if ($type->comments)
#foreach ($type->comments as $comment)
<div class="user-comment-box">
<div class="user-comment">
<p class="comment">
<!-- starts off with users name in blue followed by their comment-->
<span class="tag-user">{{ $comment->owner->first_name }} {{ $comment->owner->last_name }} </span>{{ $comment->body }}
</p>
<!-- Show when the user posted comments-->
<div class="com-details">
<div class="com-time-container">
{{ $comment->created_at->diffForHumans() }} ·
</div>
</div>
</div><!--user-comment end-->
</div><!--user-comment-box end-->
#endforeach
#endif
<!--type box-->
<div class="type-comment">
<div class="type-box">
{{ Form::open(['data-remote', 'route' => ['commentPost', $id], 'class' => 'comments_create-form']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden($idType, $id) }}
{{--{{ Form::hidden('user_id', $currentUser->id) }}--}}
{{ Form::textarea('body', null, ['class' =>'type-box d-light-solid-bg', 'placeholder' => 'Write a comment...', 'rows' => '1']) }}
{{ Form::close() }}
</div><!--type-box end-->
</div><!--type-comment-->
</div><!--comment-box end-->
The user submit the form for the comment type box by pressing the "enter/return" key. Here is the JS for that
<script>
$('.comments_create-form').on('keydown', function(e) {
if (e.keyCode == 13) {
e.preventDefault();
$(this).submit();
}
});
</script>
Here is my Ajax
(function(){
$('form[data-remote]').on('submit', function(e){
var form = $(this);
var method = form.find('input[name="_method"]').val() || 'POST';
var url = form.prop('action');
$.ajax({
type: method,
url: url,
data: form.serialize(),
success: function(data) {
var tmp = $('<div>');
tmp.html(data);
$('.ajax-refresh').html(tmp.find('.ajax-refresh').html());
$('.type-box').html(tmp.find('.type-box').html());
tmp.destroy();
}
});
e.preventDefault();
});
})();
I'm running into a few problems with this code. The comment gets displayed on ever single post until I manually refresh the page then it only shows on the correct post. I feel like every post's comment-box will need it's own unique ID to solve this, but I do not know how to do this with Laravel and make the JavaScript work.
also,
After I submit one comment I can no longer submit a second one because my "submit on enter/return key" functionally is no longer working. My cursor just moves to a new line, and I'm not able to post another comment.
Does anyone know a way to fix these problems?
EDIT
Here is my ajax so far
(function(){
$(document).on('submit', 'form[data-remote]', function(e){
e.preventDefault();
var form = $(this)
var target = form.closest('div.ajax-refresh');
var method = form.find('input[name="_method"]').val() || 'POST';
var url = form.prop('action');
$.ajax({
type: method,
url: url,
data: form.serialize(),
success: function(data) {
var tmp = $('<div>');
tmp.html(data);
target.html( tmp.find('.ajax-refresh').html() );
target.find('.type-box').html( tmp.find('.type-box').html() );
tmp.destroy();
}
});
});
})();
Please use the following to fix the issue:
$(document).on('submit', 'form[data-remote]', function(e){
e.preventDefault();
var form = $(this),
var target = form.closest('div.ajax-refresh');
var method = form.find('in......
......
.....
tmp.html(data);
target.html( tmp.find('.ajax-refresh').html() );
target.find('.type-box').html( tmp.find('.type-box').html() );
tmp.destroy();
}
});
});
The variable target will help you target just the right div to add the ajax response to.
Further, you would have to just reset the relevant form rather than replace the form markup. Otherwise each form will work only once.
UPDATE
The above code has been updated to use a delegated submit event -- $(document).on('submit', '.selector', ...) instead of $('.selector').on('submit', .....) since the form content is being replaced after each comment.
UPDATE 2
The following delegated keydown event should enable you to submit by pressing the enter key:
$(document).on('keydown', '.comments_create-form', function(e) {
if (e.keyCode == 13) {
e.preventDefault();
$(this).submit();
}
});

bootstrap popover update content

how do you update the content of bootstrap popover after ajax success, I specifically need to change the value of the input field that I have but once I close the popover and click on it, the original value of the input field shows up? can someone help me out?
<button class="btn btn-primary edit" data-content='<input type="text" id="name" value="some value">
<button class="btn btn-primary save">Save</button>'>Edit</button>
JavaScript:
$('.edit').popover({
placement: 'left',
html: true,
});
$('body').on("click", ".save", function() {
var name = $('#name').val();
$.ajax({
type: "POST",
url: "test.php",
data: {
name: name
},
cache: false,
success: function(response) {
if (response.indexOf("success") != -1) {
$('#name').val(name);
$('.edit').popover('hide').next('.popover').remove();
}
}
});
});
after the data is saved the popover is closed and when I click edit again the old value shows in the input box.
Please find enclosed a working demo of a popover that will be updated with the response from an ajax request.
I've removed your request parameters just for the demo to be able to do the request with mocky.io.
The trick was to use .attr('value', text) instead of .val(text). I'm not exactly sure what's going on here. Maybe someone can explain why that's different.
But with attr it changes the popover and it works.
Another thing that is required is to recreate the popover. I also wanted to destroy the first popover but that doesn't work. So I created the same popover again.
You can also find the same code here at jsFiddle.
There is a bug in the code here at SO. If you get the data from the server and then close the popover, the data will be reset to initial value.
Don't know what's wrong, because it works at jsFiddle with-out that bug.
Update 04.12.2014:
I've improved the code a bit. Now there is a close button in the popover and the data is stored so the data from server is still available when the popover is re-opened.
The bug mentioned above was probably not a SO issue, it was because the data from server was not properly stored. That is also fixed now.
I've also removed some not needed script tags in the demo because tooltip and popover are already included in bootstrap 3.
Update 05.12.2014:
I have another improvement to the code.
The line $(this).parent().find('.close').click(...) is not working like I wanted it. I wanted to add the handler only to the close button of the current popover. But it adds it to all elements with class .close.
Because $(this).parent() is the body element. I think it is better to do it like this:
var current_popover = '#' + $(e.target).attr('aria-describedby');
var $cur_pop = $(current_popover);
$cur_pop.find('.close').click({});
With aria-describedby you'll get the id of the current popover and then you can find the close button of that popover.
$(function () {
var editData = 'new value';
var doPopover = function (item, text) {
$('#name').attr('value',text); // use set attr and not val()
//$('#name').val(text); //<<<< not working here doesn't set DOM properly
var $pop = $(item);
$pop.popover({
placement: 'right',
title: 'edit <a class="close" href="#">×</a>',
trigger: 'click',
html: true,
content: function () {
return $('#popup-content').html();
}
}).on('shown.bs.popover', function(e) {
// console.log('triggered');
// 'aria-describedby' is the id of the current popover
var current_popover = '#' + $(e.target).attr('aria-describedby');
var $cur_pop = $(current_popover);
$cur_pop.find('.close').click(function(){
//console.log('close triggered');
$pop.popover('hide');
});
});
return $pop;
};
// enable popover
doPopover('.edit', editData);
// edit button click handler to show popover
$('.edit').click(function() {
doPopover('.edit', editData);
});
$('body').on("click", ".save", function (e) {
e.preventDefault();
var name = $('#name').val();
//console.log($popover);
$.ajax({
type: "GET", //"POST",
url: "http://www.mocky.io/v2/547f86501713955b0a8ed4da", //"test.php",
data: {
//name: name
},
cache: false,
success: function (response) {
editData = response.data;
doPopover('.edit', editData);
console.log('response: ', editData);
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<button class="btn btn-primary edit" data-html="true" data-toggle="popover" class="edit" data-title="Edit">Edit</button>
<div id="popup-content" class="hide">
<input type="text" id="name" value="some value" />
<button class="btn btn-primary save">Save</button>
</div>

Getting Meteor 0.9.1.1 click event to update object

I'm just playing around with different patterns and am very new to programming, however I've got everything to work in my test app so far except this. I've tried a bunch of variations with no luck, but I suspect I'm missing something really simple.
Basically what I want to happen is for a user to click a button and for it to then update the value of two specific attributes of the current object.
In this example I'm wanting the update to occur when the user clicks the "Return" button (the other buttons shown below are working fine).
Here's the HTML template for the button in question:
<template name="bookDetails">
<div class="post">
<div class="post-content">
<h3>{{title}}</h3><span> {{author}}</span>
{{#if onLoan}}
<i class="fa fa-star"></i>
On loan to: {{lender}}{{/if}}
</div>
{{#if ownBook}}
Edit
Lend
<div class="control-group">
<div class="controls">
<a class="discuss btn return" href="">Return </a>
</div>
</div>
{{/if}}
</div>
</template>
Here's the .js file which contains my Template event. Basically I want to set the values for the "lendstatus" and "lender" attributes.
Template.bookDetails.helpers({
ownBook: function() {
return this.userId == Meteor.userId();
},
onLoan: function() {
return this.lendstatus == 'true';
}
});
Template.bookLoan.events({
'click .return': function(e) {
e.preventDefault();
var currentBookId = this._id;
var bookProperties = {
lendstatus: "false",
lender: "",
}
Books.update(currentBookId, {$set: bookProperties}, function(error) {
if (error) {
// display the error to the user
throwError(error.reason);
} else {
Router.go('bookPage', {_id: currentBookId});
}
});
},
});
If I type the following into the Browser console while on the page for the object with id ZLDvXZ9esfp8yEmJu I get the correct behaviour on screen and the database updates so I know I'm close:
Books.update({ _id: "ZLDvXZ9esfp8yEmJu"}, {$set: {lendstatus: "false", lender: ""}});
What am I missing?
OK - so my problem was that I'd defined the event handler in the wrong template. I'd defined it in the bookLoan template instead of the bookDetails template. Thanks #saimeunt for pointing this out!

Categories