MarkItUp! for Jeditable

April 8th, 2008

In the heels of autogrow textarea comes next custom input for Jeditable. This time we will use markItUp! universal markup editor by Jay Salvat.

If you are not familiar with Jeditable custom inputs read the introduction. Also see autogrow and timepicker tutorials.

If you are just looking for the code download it here.

Creating custom input

Throughout the tutorial we will be using following code to trigger Jeditable. Note variable called markitupHTML. It holds configuration of used markItUp! tagset. In this example I use slightly modified HTML tagset. For more information on tagsets see markItUp! documentation.

$(".edit").editable("http://www.example.com/save.php", { 
    type      : "markitup",
    submit    : 'OK',
    cancel    : 'Cancel',
    tooltip   : "Click to edit...",
    onblur    : "ignore",
    markitup  : markitupHTML
});

Again we start by adding custom input type called markitup.

$.editable.addInputType('markitup', {
});

Right now code does not do much anything. It only creates the buttons and hidden input. Click text below to see it in action.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Add textarea element

Next we add texarea element. Unlike in previous tutorials we do not copy and paste code from default textarea element. Instead we use a shortcut:

$.editable.addInputType('markitup', {
    element : $.editable.types.textarea.element
});

Now normal textarea is added. Click text below to see how it works.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

Attach markItUp! to textarea

We wanted to see pretty textarea with toolbar. First we search textarea input inside Jeditable form. This is done with $(‘textarea’, this) selector. Then we attach markItUp! to it.

$.editable.addInputType('markitup', {
    element : $.editable.types.textarea.element,
    plugin  : function(settings, original) {
        $('textarea', this).markItUp(settings.markitup);
    }
});

Now you can edit code with tag editor. Click text below to test yourself.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.

And we are done. This illustrates how easy it is to customize Jeditable with other plugins. Only six lines of code can create pretty inline tag editor. There is also separate Textile demo. As always, all suggestions and feedback are welcome.


40 Responses to “MarkItUp! for Jeditable”

  1. Thomas Mery says:

    Hello there,

    a huge thanks for this plugin and the ability to link it with markitup :)

    I don’t know if I can post this here but …

    I am running through a problem with ie7 and making elements in an iframe editable.

    I posted an example here :

    http://www.thomas-mery.net/dev/jeditable_iframe/

    what happens is that when trying to edit an element in the iframe ie7 chokes on line 212 of jquery.jeditable.js

    /* add created form to self */ $(self).prepend(form);

    complaining that form is an ‘invalid argument’

    replacing form by form.html() makes the form appear but no events seem to be working (Enter, Escape …)

    would you point me in a direction where i can fid ways to fix this ? Or just point out what I am missing :)

    Thanks a lot for any help, as I’m kind of stuck with this issue

    Thomas

  2. Roman says:

    Hi there, first to say: Great Work! :)

    But i’m searching for the possibility to style the input-fields (input, textarea). Would be nice, if you could help me. :)

    Greets

  3. Roman says:

    there seems to be a problem with the width of the markitup-div around the textarea.

  4. Mika Tuupola says:

    Sorry I missed your comment. You can style forms directly in with css. If you want to give the form a special class, for example foobar you can use cssclass parameter:

      $(".editable").editable("http://www.example.com/save.php", { 
          type   : 'textarea',
          submit : 'OK',
          cancel : 'cancel',
          cssclass : 'foobar'
      });
    

    Resulting HTML will be like this:

    <p class="editable" id="something">
      <form class="foobar">
        <textarea name="value"></textarea>
        <button type="submit">OK</button>
        <button type="cancel">cancel</button>
      </form>
    </p>
    

    Then just style all elements with your CSS.

  5. john says:

    just a query…

    is there anyway to close the jeditable area programmatically? the situation arises where the user might click a link that will load data into the area that jeditable resides. if jeditable was active at the time, it will unbind the onclick handler for jeditable ie subsequent clicks to edit will not work. what i need is something like what onblur:cancel does. i’ve tried using onblur:cancel, but then the textarea can’t be resized…

    thanks for the great plugin!

  6. Mika Tuupola says:

    john: Atleast for custom inputs there is a reset method available. By default it looks like following:

      reset : function(settings, original) {
          original.reset();
      }
    

    So if you create a custom input which includes the load link you mentioned, you could bind calling original.reset(). Code could be something like following:

      $.editable.addInputType('load-reset-button', {
          element : $.editable.types.text.element,
          buttons : function(settings, original) {
              var default_buttons = $.editable.types['defaults'].buttons
              default_buttons.apply(this, [settings, original]);
    
              var third = $('<input type="button">');
              third.val(settings.third);
              $(this).append(third);
    
              $(third).click(function() {
                  original.reset()
                  alert("I just reseted myself and now should be loading.");
              });
          }
      });
    

    And then you would call it with:

      $(".editable").editable("http://www.example.com/save.php", { 
          type      : "load-reset-button",
          submit    : "OK",
          cancel    : "Cancel",
          third     : "Reset and load",
          onblur    : 'ignore'      
      });
    

    Check Three Button Editable tutorial to better understand code above.

  7. John says:

    What I had in mind was more along the lines of a method I could call any time I wanted, which essentially is original.reset(). You’ve pointed me in the right direction. I didn’t realise you could call .reset() from the original element. So now all I need to do is $(’#original-element’)[0].reset() whenever I need to remove inline editing. Thanks for that Mika!

  8. Mika Tuupola says:

    John: Oh cool. Thanks for heads up. I did not realize myself you can also call

     $(’#original-element’)[0].reset()
    

    directly. I was thinking it too complicated. I guess then also following would work.

     $(’#original-element’).get(0).reset()
    
  9. Cristian says:

    Hi .. great work!

    I have a question. I want to add an element .. After submit jquery post 2 elements. ID and NAME. Cool … but how can I add one more ? id, name and prod_id ?

    Thanks !

  10. Mika Tuupola says:

    Cristian: Use submitdata parameter. It can be either a hash or function returning a hash. For example:

    $(".editable").editable("http://www.example.com/save.php";, {
        submitdata : {prod_id: 27}
        }
    })
    
    $(".editable").editable("http://www.example.com/save.php";, {
        submitdata : function() {
            /* This should obviously be generated dynamically. */
            return {prod_id: 27}
        }
    })
    
  11. Ian Tresman says:

    It would be great of your Jeditable demo included an example that (a) required a simple log-in authentication (b) instead of saving to a database, saved to the actual HTML, with a copy of the orginal© Let people restore to earlier versions. This would be a brilliant practical, workable example.

  12. Anthony James Bruno says:

    Having some User Authentication would be awesome

  13. Mika Tuupola says:

    Anthony: User authentication should be implemented in backend.

  14. Ward says:

    Hello,

    I’m trying to get this working…

    I have this above my edit field

    ’, rows : 25, markitup : mySettings }); $.editable.addInputType(‘markitup’, { plugin : function(settings, original) { $(‘textarea’, this).markItUp(settings.markitup); } }); }); - The edit zone ->
    test

    Markitup default settings and css is included, jquery and jeditable also..

    Before I try’d this I was able to edit text and save it to database but now when I’m clicking on the text nothing appears not even the plain html textarea

    —> this is the error I get in the jquery.editable file.

    $.editable.types[settings.type] is undefined || function() { };

    Thanks ! Ward

  15. Mika Tuupola says:

    Ward: Are you including jquery.jeditable.markitup.js in your page?

  16. Peter says:

    How would you implement user authentication?

    Perhaps php generates an md5 token and stores it in both the session and inserts it as a jeditable submitdata token. Then the php program that handles the ajax request checks to see if the submitted token is the same as the session token.

    Something like this:

     <?php
     $security_token = md5(uniqid(rand(), TRUE));
     $_SESSION['eip_token'] = $security_token;
     ?>
     <html>
     [...]
     <script>
        $('.edit').editable('http://website/save.php', {
           submitdata : {eip_token: "<?php echo $security_token; ?>"}
        });
     </script>
     [...]
     </html>
    

    And in save.php:

     <?php
     if (isset($_POST['eip_token']) && 
         isset($_SESSION['eip_token']) && 
         $_POST['token'] == $_SESSION['eip_token']) {
            // valid user
     } else {
       // invalid user
     }
     ?>
    

    Gosh, I hope that code displays correctly.

  17. Mika Tuupola says:

    Peter: Something like that should work. Additionally you can also not output any Jeditable code to page when user has not logged in. This way user cannot event click elements to start Jeditable.

  18. Peter says:

    Well the problem with that is if save.php doesn’t have any security built in, any hacker could reference http://website.com/save.php with their own post variables and modify the page as they like.

    They could easily learn the ajax posting url and the form parameters if they’ve ever seen a page that includes a jeditable reference (a former employee, or a previous website member, for example).

    Using a session token helps prevent this kind of breach. I think that lack of authentication is a big problem with Ajax apps in general.

    Thanks for the great app, Mike!

  19. Mika Tuupola says:

    Yes of course. That is why I said additionally.

  20. Tony says:

    I am sure this is just something stupid, but I have banged my head long enough to cry “uncle” and ask for help.

    I am trying to integrate this example with a new site we are developing and it just doesn’t work. I have a “stock” MarkItUp and jEditable field working on this same page, but the “combined” field just displays as text with nothing happening when I click.

    Here are my three configurations; “miu” and “edit” work fine, but “miuEdit” does nothing:

    $(document).ready(function() {
    
        $('.miu').markItUp(mySettings);
    
        $('.edit').editable('/ContentManager/EditText', {
            type: 'textarea',
            submit: 'Save',
            cancel: 'Cancel',
            indicator: '<img src="assets/common/jEditable/img/indicator.gif">',
            loadurl: '/ContentManager/GetText',
            loadtype: 'POST',
            tooltip: 'Click to edit...',
            loaddata: { pageGuid: 'a66c63a4-7175-4078-9813-ec63efeaf65d' },
            submitdata: { pageGuid: 'a66c63a4-7175-4078-9813-ec63efeaf65d' }
        });
    
        $('.miuEdit').editable('/ContentManager/EditText', {
            type: 'markitup',
            submit: 'Save',
            cancel: 'Cancel',
            indicator: '<img src="assets/common/jEditable/img/indicator.gif">',
            loadurl: '/ContentManager/GetText',
            loadtype: 'POST',
            tooltip: 'Click to edit...',
            onblur: 'ignore',
            markitup: markitupHTML,
            loaddata: { pageGuid: 'a66c63a4-7175-4078-9813-ec63efeaf65d' },
            submitdata: { pageGuid: 'a66c63a4-7175-4078-9813-ec63efeaf65d' }
        });
    
    });
    

    And here are my CSS and script includes:

    <link type="text/css" href="assets/common/markitup/skins/markitup/style.css" rel="stylesheet" />
    <link type="text/css" href="assets/common/markitup/sets/html/style.css" rel="stylesheet" /> 
    <script type="text/javascript" src="../../assets/common/scripts/jquery-1.3.2.min.js"></script> 
    <script type="text/javascript" src="../../assets/common/markitup/jquery.markitup.pack.js"></script> 
    <script type="text/javascript" src="../../assets/common/markitup/sets/html/set.js"></script> 
    <script type="text/javascript" src="../../assets/common/jEditable/scripts/jquery.jeditable.mini.js"></script> 
    <script type="text/javascript" src="../../assets/common/jEditable/scripts/jquery.jeditable.markitup.js"></script> 
    

    My “jquery.jeditable.markitup.js” is straight off the example site here.

    And, finally, here are the elements themselves:

    <div class="miuEdit" id="fieldOne"></div> 
    <div class="edit" id="fieldTwo"></div> 
    <textarea class="miu" id="markItUp" cols="80" rows="20"> </textarea>
    

    Like I said, “miu” and “edit” work exactly as expected and I have quadruple-checked all the CSS & script paths. I am at a loss at this point as to what I am doing wrong. Does anyone have a hint/clue for me?

    TIA

    Tony

  21. Mika Tuupola says:

    Tony: Quickly looking your code looks correct. Do you have example page somewhere online which I could debug?

  22. Tony says:

    Thanks, Mika. I’ll do that. While I was publishing the website, Visual Studio spit out a warning I haven;t seen before while running the site. It said that when looking at my jquery.jeditable.markitup.js file, ”’$.editable’ is null or not an object @ 18:0”.

    I copied that file “blindly” from your site, but perhaps there is something mis-named that I need to correct in that file? Here is mine:

    $.editable.addInputType('markitup', {
        element: $.editable.types.textarea.element,
        plugin: function(settings, original) {
            $('textarea', this).markItUp(settings.markitup);
        }
    });
    

    In the meantime, I am getting a working version up for you.

    Tony

  23. Tony says:

    Okay, more info – this is almost certainly “it.”

    When I try running the page through IIS (versus the built-in “cassini” web server in Visual Studio), I get the following error:

    ‘markitupHTML’ is undefined

    It appears to be upset with my use of that variable in the configuration of my “miuEdit” class. When I look through your example, I am not seeing where that is defined – so I had assumed it was an “internal constant” or some-such.

  24. Tony says:

    Ah, tracked it down. That markitupHTML is the name you used in your “set.js” file instead of the default mySettings. When I replaced markitupHTML with mySettings, it all worked perfectly.

    Nice job!

  25. Mika Tuupola says:

    Tony: Great! Glad you found a solution.

  26. Eiso says:

    Hi Mika,

    Thank you for this plugin, it’s fantastic and it is saving me a lot of time. I have one question though, I appended a select form and button next to Save and Cancel when the plugin (custom input) loads. This is for a user to select previous versions of edits (it’s a lightweight wiki). I have it ready to the extent that when the person selects the version and clicks on load I can pull in that text with AJAX. However I would like to replace the current textarea/MarkItUp field with that text I load. I tried everything from setting value on the text area to trying to see if there was a way to select and replace the text however nothing worked so far. Is there a way to do this?

    Thank you,

    Eiso

  27. Ankur says:

    Hello Frds,

    I have one link “edit” so that when i click on edit link can i use jeditable to edit other data? Means in one row i have “Some Text” and after that “Edit” link so when i click on Edit then jeditable can be placed on Some text and after that i can click on Save to save data.

    Is this possible ?? Please tell me…Please help me

  28. Mika Tuupola says:

    Ankur: There are many ways to do it and it depends a bit on your HTML. For example if you have following HTML:

    
    <div class="edit" id="unique_id">Editable text</div> 
    <a href="#" class="edit_trigger">Edit me!!</a>
    

    Then you can use following JavaScript:

    
    /* Bind Jeditable instances to "edit" event. */
    $(".edit").editable("http://www.example.com/save.php", {
        event     : "edit" 
    });
    /* Find and trigger "edit" event on correct Jeditable instance. */
    $(".edit_trigger").bind("click", function() {
        $(this).prev().trigger("edit");
    });
    
  29. Mika Tuupola says:

    Eiso: You might want to check MarkItUp! example on serverside scripts. Especially how example uses Tidy. To me that looks like something which might lead you to correct direction.

    Myself I have not done anything similar you describe.

  30. Scott says:

    Mika, thanks so much for this. I just started using Jeditable and it is really slick. I just wanted to comment regarding your discussion above in Sept. 2008 with John on the reset syntax $(’#original-element’).get(0).reset(). In trying to do a reset as part of the error condition of an ajax callback, I found that I needed to set the editing property to true before calling reset since the error condition would happen after the loss of focus when editing is no longer true. Just a heads up for anyone trying to do a cancel as part of error handling in the ajax call. Thanks again for your work.

  31. Mibo says:

    Thanks for JEditable. It’s a really useful pluging. I’m trying to use JEditable with WYMEditor but nothing works. I have an editable area but the editor doesn’t take control over it (like the second example on this tutorial). Any suggests?

  32. Mika Tuupola says:

    Mibo: Any example page online?

  33. Mibo says:

    Solved! Here a working (at least on FF3) demo: http://mibo.altervista.org/wymeditor-jeditable.html

    Your plugin works well with WYMEditor… Soon I’ll try to add Autogrow.

    Tanks again.

  34. ave says:

    great plugin! have it working but I am having some problems trying to figure out how to deal with the multiplication of table cell values (of current row).

    I have a table of product skus. each row contains various columns including a cost column, a markup column and price column. If someone changes the markup or cost I’d like the price column to get updated. I’m stumped how to refer to these table cells in order to do the math.

    any help appreciated.

  35. manuel says:

    Hi at all, thanks a lot for this plugin, really great. For the project I’m currently working at I also had to implement this functionality together with an editor like Wymeditor (like Mibo a few posts above). Integrations was quite easy, but the problem was, that only the “old” value of the textarea was sent to the server (a php-file to save it in a db). I copied the source of Mibo’s example but it didn’t work out of the box. BUT: after a few hours I realized the problem (probably a very small one which others might have found much faster gg): All you have to do is add a line to the JS-file where you add the new InputType:

    @$.editable.addInputType(‘wymeditor’, { element : $.editable.types.textarea.element, plugin : function(settings, original) { $(‘textarea’, this).wymeditor(settings.wymeditor); $(“button:submit”).addClass(“wymupdate”); } });@

    Important is the line with $(“button:submit”) ... as Wymeditor only updates the textarea’s content when the submit-button has a class of wymupdate! After adding this line, everything worked fine!

    Hope, this helps someone and thanks again for this cool plugin!

  36. Aamir Mahmood says:

    Hi,

    jeditable is working fine for us until we decided to use jScrolPan around the table. Now the user can scroll a table with jScrolPan, but when any user click on jeditable text, although it put the editable form, but it also scrollup the jscrolpan. Which in result hide the jeditable thing under somewhere. Now if we scrollback to that editable text, that text turned back to normal, as we have clicked outside some where (to scroll i mean).

    Please let me know if you have any solutions for this.

  37. Mika Tuupola says:

    Aamir: Sounds pretty specific problem for jScrollPan. Do you have any example page online?

  38. Aamir Mahmood says:

    Thank you Mika.

    Please check the following url

    http://pk.dynamiconlinesystems.com/jedit/

    Category title is only editable here, other links are dead, as i just took out the code from our existing application and created these files. Please let me know if they are working for you. We have fixed the issue somewhat that when we scroll the area it wont close the jeditable form.

    Waiting for your kinds comments.

  39. Aamir Mahmood says:

    Thank you Mika.

    Please check the following url

    This is the link

    Category title is only editable here, other links are dead, as i just took out the code from our existing application and created these files. Please let me know if they are working for you. We have fixed the issue somewhat that when we scroll the area it wont close the jeditable form.

    Waiting for your kinds comments.

  40. Nick says:

    Hi there,

    Firstly thanks for a great plugin and in depth examples, it has been so easy to make use of jeditable and even with other plugins.

    I have been using the ‘onreset’ function option but ideally I need an event that occurs after the reset is complete. I have looked through the plugin source but can not see what I am after. Is this possible or should I consider extending the plugin?

    Many thanks.

Leave a Reply



(will not be published)



(you can use Textile for formatting)