How to Enable/Disable JEditable

2019-04-12 14:42发布

问题:

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!

回答1:

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")


回答2:

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.



回答3:

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.
}