I got some DIV's I'm editing with 'jeditable' which works perfectly!
Now I want to give my users an alert to ask them if they really want to edit this post.
<script type="text/javascript" src="jquery-1.9.1.js"></script>
<script type="text/javascript" src="jquery.jeditable.js"></script>
<script type="text/javascript">
$(document).ready(function jeditable() {
$("div[title='Article']").click (function() {
var Edit;
Edit = confirm("Editing article?");
if (Edit == true) {
$('.edit').editable('x2.php', {
cancel : 'Cancel',
submit : 'OK',
onblur: 'ignore',
});
} else {
alert("Canceling edit..");
}
});
});
</script>
1)When the alert pops and I cancel it, nothing happens (intended).
2)When I click "OK" in the alert nothing happens as well.
3)When I clicked "OK" once, the function in my 'if' works no matter if I check "OK" or "Cancel" in a second click in the alert.
I would like to only make my text editable after the user clicks "OK" once.
(Later on I want to make an image clickable instead of the text itself, but because that throws same error I try to solve this way first)
Please help me.
Thanks in advance
Problem still alive!
I changed to not make the article itself clickable fo the "confirm" but some img instead. That way it works perfectly, even with another element so trigger the confirm to make '.edit' editable. Workaround found, but still would be interested in a solution for the other way :)
I looked at the jeditable library , therefore here is what I would do to achieve your requirement
$(document).ready(function()
$("div[title='Article']").click (function() {
if (confirm("Editing article?")) {
$('.edit').editable('x2.php', {
cancel : 'Cancel',
submit : 'OK',
onblur: 'ignore',
});
}
});
});
It looks like you are missing a "}" after the end of the else clause. If you look at the error console in the browser I think you will have an error indicating this.
if (Edit == true) {
$(document).ready(function () {
$('.edit').editable('x2.php', {
cancel : 'Cancel',
submit : 'OK',
onblur: 'ignore',
});
});
} else {
alert("Canceling edit..");
}
} // <-- add this in
});
$(document).ready(function jeditable() {
$("div[title='Article']").click (function() {
var Edit;
Edit = confirm("Editing article?");
if (Edit == true) {
$('.edit').editable('x2.php', {
cancel : 'Cancel',
submit : 'OK',
onblur: 'ignore',
});
} else {
alert("Canceling edit..");
}
}); //<<< this was closing out the function BEFORE the else.
});
You dont need "$(document).ready(function" after if
$(document).ready(function jeditable() {
$("div[title='Article']").click (function() {
var Edit;
Edit = confirm("Editing article?");
if (Edit == true) {
$('.edit').editable('x2.php', {
cancel : 'Cancel',
submit : 'OK',
onblur: 'ignore',
});
} else {
alert("Canceling edit..");
}
});
});
Related
I want to display a Bootbox dialog that includes an "OK" button. When the user clicks the "OK" button, it should POST back, with the ID of the message to confirm that the user has viewed the message. The Bootbox dialog is the form. I don't see a way to make the dialog buttons a submit form with hidden fields, which is what I assume is the right way to accomplish my goals.
Thanks to the helpful comments from Isabel Inc and Mistalis, I have a working solution.
Notes specific to my implementation:
The messages contain images that need to be responsive, so I add the appropriate Bootstrap classes to each image
The messages may have links. Clicking a link is equivalent to clicking "OK" on the dialog
And the JavaScript that makes it happen...
jQuery(function($, window, bootbox, undefined) {
var accept = function(callback) {
$.ajax({
type: 'POST',
data: {message_id: 244826},
success: callback()
});
};
var $message = $('<p><img src="https://www.gravatar.com/avatar/80fa81938a6d1df92cd101d7fe997a71" alt></p><p>Here is a message from Sonny.</p>');
$message.find('img').addClass('img-responsive center-block');
$message.find('a').on('click', function(e) {
var href = $(this).attr('href');
if (0 === href.length) {
return;
}
e.preventDefault();
accept(function() { window.location.href = href; });
});
bootbox.dialog({
message: $message,
closeButton: false,
buttons: {
accept: {
label: 'OK',
callback: function() {
accept(function() { window.location.reload(); });
}
}
}
});
}(jQuery, window, bootbox));
My users may use IE7 and I want to avoid using the prompt function. I have working code using prompt but am unsure of a good way to replace it.
My usage requirement is this. User clicks an image button and then has to OK/Cancel a prompt. If OK is pressed, a Reference is requested which is assigned to RemovePalletReference for use in code behind.
<asp:imagebutton id="ibRemoveFromPallet" runat="server" ImageUrl="../Images/Icons/removefrompallet.gif" OnClientClick="return ConfirmReroute();"></asp:imagebutton>
<asp:HiddenField ID="RemovePalletReference" runat="server" value="" ></asp:HiddenField>
You can see above that I first call ConfirmReroute() which is the following js function.
function ConfirmReroute()
{
if (confirm("Confirm Remove Unit From Pallet") == true)
{
var pmt;
do {
pmt = prompt("Please Enter a Reference:", "");
}
while ( pmt == null || pmt.length < 1);
document.getElementById('<%= RemovePalletReference.ClientID %>').value = pmt;
return true;
}
else
return false;
}
I wish to replace the code where the user has pressed OK to the confirm. I tried with jquery UI modal dialog but could not work it out. I think it may be workable using callbacks but this is a new subject to me and I'm struggling.
Please in answers show some code to help me out. Grateful for any assistance.
Ex
function confirmDialog(title, message, confirm, reject) {
var dialog = $('<div />').html(message).dialog({
appendTo: 'body',
title: title,
modal: true,
buttons: {
"OK": function () {
$(this).dialog("close");
confirm();
},
"cancel": function () {
$(this).dialog("close");
if ($.isFunction(reject)) {
reject();
}
}
},
close: function (event, ui) {
$(this).dialog('destroy');
$(this).remove()
}
})
}
function test(notes) {
confirmDialog('Confirm', 'Confirm Something', function () {
console.log('ok');
//what ever you want to do on confirmation has to go here
}, function () {
console.log('cancelled')
});
//any code added here will get executed before the confirm box is displayed
}
Demo: Fiddle
I want to try to override window.confirm function with modal dialog.
<a href="http://example.com" onClick="return confirm('you want to go?')">
<script>
window.confirm = function(message){
$("#confirm-dialog").modal('show');
$("#confirm-dialog .modal-body p").html(message);
$("#confirmYes").on("click", function () {
return true;
});
}
</script>
When I click in modal window on the #confirmYes element it returns true, but the redirect by href link will not work...Why?
Can somebody tell me how I can do this thing without changing my link?
Thanks
UPD
Yii framework generates that code for CGridView widget and i want to override it. I can't change this code, because its in framework. Instead this confirm standard i want to use my modal window
$(document).on('click','#product-grid a.delete',function() {
if(!confirm('Are you sure you want to delete this item?')) return false;
var th=this;
var afterDelete=function(){};
$.fn.yiiGridView.update('product-grid', {
type:'POST',
url:$(this).attr('href'),
success:function(data) {
$.fn.yiiGridView.update('product-grid');
afterDelete(th,true,data);
},
error:function(XHR) {
return afterDelete(th,false,XHR);
}
});
return false;
});
Here is a practice that we used in my company in a UI conversion project.
It is ugly though, but it works just fine.
var clickState={};
var justClicked=null;
window.confirm = function(message) {
var e = window.event || window.confirm.caller.arguments[0];
var el = e.target || e.srcElement; // the element's click that triggers confirm dialog
if(justClicked && clickState[justClicked]===true){
clickState[justClicked]=false;
return true;
}else{
// your async style confirmation dialog (e.g. jQuery's dialog)
showConfirmBox(message, function() {
justClicked=el;
clickState[el]=true;
$(justClicked).click(); // in the call back function , click the target again.
});
}
return false;
};
Js default confirm dialog work synchronously, it means that code will wait for the user to make his choice to continue. When you override confirm dialog this way what happens is that your new stylish confirm dialog is shown but method end immediately and returns undefined.
You can work with callbacks;
<a href="http://example.com" onClick="confirm('you want to go?', function(result){
if(result)
//code to redirect, like window.location(this.href);
}); return false;">
then:
<script>
window.confirm = function(message, cb){
$("#confirm-dialog").modal('show');
$("#confirm-dialog .modal-body p").html(message);
$("#confirmYes").on("click", function (userChoice) {
cb(userChoice); //true or false - your jquery plugin will supply this value
});
}
</script>
EDIT: Its important to keep the link url on href (instead of just leaving "/#") for SEO reasons - for the link not be triggered you should also return false after calling your new confirm dialog.
If you need Overriding the window.alert() dialog box you can find it here
after that I have create my own Overriding the window.confirm() dialog box you can find it here
Overriding the window.confirm() dialog box.
It is pretty simple just like:
window.confirm = function(message, title, doYes) {
$(document.createElement('div'))
.attr({title: title, class: 'confirm'})
.html(message)
.dialog({
buttons: {
"Confirm": function() {
$(this).dialog("close");
if (doYes && (typeof doYes === "function")) {
doYes();
}
},
"Cancel": function() {
$(this).dialog("close");
}
}
,
close: function() {
$(this).remove();
},
draggable: true,
modal: true,
resizable: false,
width: 'auto'
});
};
// New confirm
//confirm('This is a <strong>new</strong> alert!','Confirm', function(){alert('Yes')},function(){alert('No')});
I know it is an old post but I want to share my solution, I know this changes the yii default behaviour but I replaced their function for one custom working the same way, I am gonna ask yii gurus about a better way or if in the future this can be done easily.
In framework/yii/zii/widgets/grid/CButtonColumn.php modify the initDefaultButtons:
/**
* Initializes the default buttons (view, update and delete).
*/
protected function initDefaultButtons()
{
if($this->viewButtonLabel===null)
$this->viewButtonLabel=Yii::t('zii','View');
if($this->updateButtonLabel===null)
$this->updateButtonLabel=Yii::t('zii','Update');
if($this->deleteButtonLabel===null)
$this->deleteButtonLabel=Yii::t('zii','Delete');
if($this->viewButtonImageUrl===null)
$this->viewButtonImageUrl=$this->grid->baseScriptUrl.'/view.png';
if($this->updateButtonImageUrl===null)
$this->updateButtonImageUrl=$this->grid->baseScriptUrl.'/update.png';
if($this->deleteButtonImageUrl===null)
$this->deleteButtonImageUrl=$this->grid->baseScriptUrl.'/delete.png';
if($this->deleteConfirmation===null)
$this->deleteConfirmation=Yii::t('zii','Are you sure you want to delete this item?');
foreach(array('view','update','delete') as $id)
{
$button=array(
'label'=>$this->{$id.'ButtonLabel'},
'url'=>$this->{$id.'ButtonUrl'},
'imageUrl'=>$this->{$id.'ButtonImageUrl'},
'options'=>$this->{$id.'ButtonOptions'},
);
if(isset($this->buttons[$id]))
$this->buttons[$id]=array_merge($button,$this->buttons[$id]);
else
$this->buttons[$id]=$button;
}
if(!isset($this->buttons['delete']['click']))
{
if(is_string($this->deleteConfirmation))
$confirmation="if(!confirm(".CJavaScript::encode($this->deleteConfirmation).")) return false;";
else
$confirmation='';
if(Yii::app()->request->enableCsrfValidation)
{
$csrfTokenName = Yii::app()->request->csrfTokenName;
$csrfToken = Yii::app()->request->csrfToken;
$csrf = "\n\t\tdata:{ '$csrfTokenName':'$csrfToken' },";
}
else
$csrf = '';
if($this->afterDelete===null)
$this->afterDelete='function(){}';
$withConfirmation = strlen($confirmation) == 0 ? 0 : 1;
$confirmationMessage = CJavaScript::encode($this->deleteConfirmation);
$this->buttons['delete']['click']=<<<EOD
`function(event) {
event.preventDefault();
if ($withConfirmation){
var th=this;
var afterDelete=$this->afterDelete;
var deleteUrl=$(this).attr('href');
console.log(deleteUrl);
$(document.createElement('div')).attr({
title:'AtenciĆ³n',
'class': 'dialog'
}).html($confirmationMessage).dialog({
buttons: {
"OK": function () {
$(this).dialog('close');
$.fn.yiiGridView.update('{$this->grid->id}', {
type:'POST',
url:deleteUrl,$csrf
success:function(data) {
$.fn.yiiGridView.update('{$this->grid->id}');
afterDelete(th,true,data);
},
error:function(XHR) {
return afterDelete(th,false,XHR);
}
});
return true;
},
"Cancel": function () {
$(this).dialog('close');
return false;
}
},
close: function () {
$(this).remove();
},
draggable: false,
modal: true,
resizable: false,
width: 'auto'
}).position({
my: "center",
at: "center",
of: window
});
}
}
EOD;
}
}
`
EDIT:
I also learned how to do it without modify core yii:
In you widget grid you a file for the buttons like this:
array
(
'class'=>'CButtonColumn',
'deleteConfirmation'=>'Atencion',
'buttons'=>array
(
'update'=>array
(
'imageUrl'=>FALSE,
'label'=>'update',
'options'=>array('title'=>'update'),
'visible'=>'$row > 0'
),
'delete'=>array
(
'imageUrl'=>FALSE,
'label'=>'delete',
'options'=>array('title'=>'delete'),
'click'=>'function(){$("#mydialog").dialog("open"); return false;}',
),
),
'template'=>'{update} | {delete}'
),
Try adding a return to the onclick:
a href="http://example.com" onclick="return confirm("you want to go?")">
SOLUTION
Thanks to Arman's P. proof of concept, finally got it to work with my site.
CODE
//Edit Note
$(function(){
function makeEditable() {
$(".edit").editable('ajax/save.php?editnotetext', {
type : 'mce',
submit : '<button class="save_button">Save</button>',
event: 'dblclick',
indicator : 'Saving...',
tooltip : 'Doubleclick to edit...',
onblur: 'ignore',
width : '700px',
height : '100px',
callback : function(value, settings){
console.log('unlocked');
$.post('ajax/save.php?unlocknotetext', {"id" : $(this).attr('id')});
$(this).effect("highlight", {}, 3000);
$(this).parents('.panel').effect("highlight", {}, 3000);
},
'onreset' : function(){
console.log('unlocked');
$.post('ajax/save.php?unlocknotetext', {"id" : $(this).attr('id')});
}
});
};
makeEditable();
$('.edit').live('click', function() {
console.log('locked');
$.post('ajax/save.php?locknotetext', {"id" : $(this).attr('id')});
});
$(".edit").click(function() {
$.post('ajax/save.php?checklock', {"id" : $(this).attr('id')},
function(data) {
// USE SAME OPTION IN BOTH PLACES
// IF YOU USE 1ST OPTION, YOU CAN TAKE JEDITABLE OUT OF makeEditable() and do everything without that function
if (data[0].is_locked == 1) {
// Option 1
//$(this).editable('disable');
//alert(data[0].username.toUpperCase() + " is editing this note!");
// Option 2
$(".edit").unbind('dblclick');
} else {
// Option 1
//$(this).editable('enable')
// Option 2
makeEditable();
}
},
"json"
);
});
});
UPDATE
So now, as per what I think Arman suggested, I made JEdtiable only work if a custom event is triggered. I'm trying to trigger the event only if I find no lock. But now JEditable doesn't get called. There's something wrong with how I'm trying ot trigger it. [Note that JEditable does get called if if I test it with a button like <button onclick="$('.edit').trigger('custom_event');">Click to Edit</button>]
CODE
So here's my new code
$(function(){
$(".edit").bind("dblclick",function() {
$.ajax({ // first check to see if locked
type: "POST",
url: "ajax/save.php?locknotetext",
data: {"id" : $(this).attr('id')},
dataType: "json",
success: function(data){
if (data[0].is_locked == 1){ // if locked then alert someone is editing ntoe
alert(data[0].username.toUpperCase() + " is editing this note!");
}
else{
$(this).trigger('custom_event');
$(this).unbind('custom_event.editable');
}
}
}); //close $.ajax(
});
});
Here's the JEditable pieces
$(function(){
$(".edit").editable('ajax/save.php?editnotetext', {
type : 'mce',
submit : '<button class="save_button">Save</button>',
event: 'custom_event',
indicator : 'Saving...',
tooltip : 'Doubleclick to edit...',
onblur: 'ignore',
width : '700px',
height : '100px',
callback : function(value, settings){
console.log(this, value, settings);
$(this).effect("highlight", {}, 3000);
$(this).parents('.panel').effect("highlight", {}, 3000);
$.ajax({
type: "POST",
url: "ajax/save.php?unlocknotetext",
data: {"id" : $(this).attr('id')}
}); //close $.ajax(
//$(this).addClass("edit");
}
// },
// function(value, settings) {
// $(this).unbind('settings.event');
});
});
BACKGROUND
I'm creating a website where people can share and edit notes. What I would like to do is if someone is editing a note, the note gets locked so that another user can't edit the note.
I'm using JEditable. Users can double click so edit a note.
If a user doubleclicks, I do an AJAX call to see if there's a lock in the note. If there isn't then I lock the note and the user can edit. If there is a lock, I alert the user the "userX is currently editing the note".
PROBLEM
My problem is that I only want to call JEditable when there is no lock. Otherwise, I just want to alert the user that someone else is editing it. The problem I'm getting with my code below is that JEditable is called no matter what. I've also tried using another class name for the editable and adding the class only when there is no lock in that callback of the first AJAX call, but that doesn't work either.
Any suggestions would be much appreciated!
JEditable supports this natively at this point:
$.fn.editable = function(target, options) {
if ('disable' == target) {
$(this).data('disabled.editable', true);
return;
}
if ('enable' == target) {
$(this).data('disabled.editable', false);
return;
}
This seems to work:
$(...).editable("disable")
$(...).editable("enable")
Try to unbind previous event (probably dblclick) that jeditable added to the element, add your own with alert and then when the element is unlocked call jeditable again.
Another solution would be to add transparent div or something with absolute positioning on your elements when they're locked and bind dblclik event with your own message to that transpatrent elements. .remove() them when your original elements've been unlocked.
The problem I see in your code is: when first user dblclicks element you apply jeditable and lock it and when second user dbclicks it you want to alert, but the problem is that jeditable has already applied dblclick event to element. Instead of this change your check for lock to mouseenter event and if your condition for lock succeeds unbind dblclick event (see unbind), if nobody is editing simply apply jeditable, the function body of editText(). There is no need to have seperate function for it. And why are using .live(). Do you have dinamically added elements?
You can find also some answers to your question here JQuery JEditable - How to Disable on click editing
The solution I came up for you looks like this.
HTML file:
<html>
<head>
<title>Lock wirh jEditable</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="http://www.appelsiini.net/download/jquery.jeditable.mini.js"></script>
<script type="text/javascript">
$(function() {
function makeEditable() {
$('#editable').editable("save.php", {
tooltip : 'Doubleclick to edit...',
event : 'dblclick',
onblur : 'ignore',
callback : function(value, settings) {
console.log('unlocked');
},
'onreset' : function() {
console.log('unlocked');
$.post('unlock.php');
}
});
};
makeEditable();
$('#editable input').live('focus', function() {
console.log('locked');
$.post('lock.php');
});
$('#editable').hover(function() {
$.post('checklock.php', function(response) {
// USE SAME OPTION IN BOTH PLACES
// IF YOU USE 1ST OPTION, YOU CAN TAKE JEDITABLE OUT OF makeEditable() and do everything without that function
if (response) {
// Option 1
$('#editable').editable('disable');
// Option 2
//$('#editable').unbind('dblclick');
} else {
// Option 1
$('#editable').editable('enable')
// Option 2
//makeEditable();
}
});
});
});
</script>
</head>
<body>
<div id="editable">Here is the text that can be edited.</div>
</body>
</html>
LOCK.PHP
<?php
$fileName = 'lock.txt';
file_put_contents($fileName, '1');
?>
UNLOCK.PHP
<?php
$fileName = 'lock.txt';
file_put_contents($fileName, '0');
?>
CHECKLOCK.PHP
<?php
$fileName = 'lock.txt';
$locked = file_get_contents($fileName);
if ($locked == '0') {
echo false;
} else {
echo true;
}
?>
SAVE.PHP
<?php
$fileName = 'lock.txt';
file_put_contents($fileName, '0');
echo $_POST['value'];
?>
LOCK.TXT (Initial)
0
You can grab the idea from the example. Of course you can do it more elegantly. This is rough example. You can try on your own simply by creating those files in same directory on your web server and copy-pasting contents. Sorry for not putting demo online, jsFiddle doesn't support ajax with change state (at least I think so). If you need any further assistance, let me know. Good Luck.
This does require a bit of messing with classes, and placement, but it works well.
Here is the jquery UI based code to create a button that controls its own state and the state of the editable text
function makeEditable(params){ //params excluded for now
$("div#body").append("<button id='editTable'>Edit Table</button>"); //inserts a button into a div
$("div#body button#editTable").button({icons: {primary:'ui-icon-pencil'}}); //creates button
$("div#body button#editTable").unbind(); //removes all listeners
$("div#body button#editTable").hover( //sets hover behaviour
function(event){ //over
$(this).addClass("ui-state-hover");
},
function(event){ //over
$(this).removeClass("ui-state-hover");
}
);
//uses a class called editText which is assigned to the td elements of the blocks you want to make editable
$("div#body table .editText").editable("http://www.blah.com/Controller/CEditTable.php", {
indicator : 'Saving...',
tooltip : 'Click to edit...'
}); //basic editable initialization
$("div#body table .editText").editable("disable"); //disables by default
//adds a toggle to the button which enables/disables the editable functionality
$("div#body button#editTable").toggle(
function(event){
$("button#editTable").removeClass("ui-state-default");
$("button#editTable").addClass("ui-state-active");
$("div#body table .editText").editable("enable");
},
function(event){
$("button#editTable").removeClass("ui-state-active");
$("button#editTable").addClass("ui-state-default");
$("div#body table .editText").editable("disable");
}
);
$("div#body button#editTable").appendTo("div#body div#tableControls"); //move button to wherever to want it.
}
I use edit-in-place plugin: http://arashkarimzadeh.com/jquery/7-editable-jquery-plugin.html
I't works Great!
I just need something to check if the new text is empty. If it is we have to go back and show some error alert.
The code:
$('.name').editable({
submit:'Gem',
cancel:'Fortryd',
onSubmit: function(content){
$.post('/admin/ajax/products/edit_category/',{ category_name:$(this).text(),category_id: this.parent().attr('id') })
}
});
Can someone please help me! :-/
check the content.current property in the onSubmit function before posting.
(there's also a content.previous property that can be used to check for changes)
Example:
$(document).ready(function() {
$("#div1").editable({
type : 'textarea',
submit : 'OK',
cancel : 'Cancel',
onSubmit : function(content) {
alert(content.current+':'+content.previous);
}
});
});
Change your onSubmit:
onSubmit: function(content){
if ($(this).val()=='') {
alert("can't be blank");
} else {
$.post('/admin/ajax/products/edit_category/',{ category_name:$(this).text(),category_id: this.parent().attr('id') });
}
}
I found a Solution:
function end(content){
if (content.current == '') {
$(this).text(content.previous);
}else{
$.post('/admin/ajax/products/edit_category/',{ category_name:$(this).text(),category_id: this.parent().attr('id')});
}
}
Its works, and goes to show the previous data