官术网_书友最值得收藏!

Inline editing

Another useful design pattern that is easy to implement is to allow the user to click a piece of text, have it converted to a text input box, and save its updated value on the server.

This is very useful when you have a table of information and want to edit one field in one of the rows. Instead of loading a whole new page to just edit that row, you can edit the data inline and have it saved by the server. This is demonstrated in the following screenshot:

Inline editing

Client-side code

For this example, I've created a table of names and email addresses, to be saved in a new directory, /2-inline_editing, as the inline-editing.html file. Create a standard HTML page, including the <html>, <head>, and <body> elements. I've provided a sample row below, and you should add a few more yourself.

<table>
...
  <tr>
    <td>Bob Burry</td>
    <td>bob.burry@xyzrentals.com</td>
    <td><a href="edit.php?id=6">edit</a></td>
  </tr>
...
</table>

In the head section, include the jQuery library as usual, and also include the code for the example as follows:

<head>
  <script src="../jquery.min.js"></script>
  <script src="inline_editing.js"></script>
</head>

The example HTML will need to be edited to make it easier for jQuery to work with. Edit your table of subscribers like this:

<table id="subscribers">
...
  <tr id="subscriber_6">
    <td class="name">Bob Burry</td>
    <td class="email">bob.burry@xyzrentals.com</td>
    <td class="edit"><a href="edit.php?id=6">edit</a></td>
  </tr>
...
</table>

All that's needed is to add a few IDs (for unique elements) and classes (for non-unique elements) so that simple jQuery could be written.

The edit link is useless if the user will be able to edit inline. It is included here to show a method known as "progressive enhancement", where an application is written first with the assumption that the browser client does not have JavaScript installed or enabled, and it is then enhanced by adding JavaScript on top of the page, which makes it easier for more modern browsers to work with it.

Tip

I have an opinion on JavaScript in the browser that I should mention here—administrators, who will be editing the page contents, can be expected to have JavaScript turned on. After all, there is no point in having a tool if you are not using it, and JavaScript in the admin area (the administrative or backend part of your site) is there to make the administrator's job easier.

On the frontend, though, you cannot expect all readers to have JavaScript enabled. Clients may read with JavaScript turned off for a variety of reasons, or may simply not have JavaScript installed in the first place.

In other words, in a closed environment such as an admin area, you can assume that the user has JavaScript enabled, but on the front-facing part of the website, you should "progressively enhance" your pages, by first writing as if there is no JavaScript, and then adding it afterwards.

Here's the jQuery script, which you should save in an external file named inline-editing.js:

function inline_editing_init(){
  $('#subscribers .edit').remove();
  $('#subscribers .name,#subscribers .email')
    .click(inline_editing_edit);
}
function inline_editing_edit(){
  if(this.in_edit)return;
  this.in_edit=true;
  var str=$(this).html();
  var w=$(this).innerWidth();
  $(this).empty();
  $('<input>')
    .attr('value',str)
    .blur(inline_editing_save)
    .keypress(inline_editing_key_pressed)
    .css('width',w)
    .appendTo(this)
    .focus();
}
function inline_editing_save(){
  var id,field_name,p;
  p=this.parentNode;
  if(p.originalHTML==this.value)
    return inline_editing_restore(p);
  field_name=p.className;
  id=$(this).closest('tr')[0].id.replace(/.*_/,'');
  $.getJSON(
    'ajax_inline-editing.php',
    {'id':id,'field_name':field_name,'value':this.value},
    inline_editing_callback
  );
}
function inline_editing_key_pressed(e){
  if(!e.which)inline_editing_restore(this.parentNode);
}
function inline_editing_restore(el){
  $(el).html(el.originalHTML);
  el.in_edit=false;
}
function inline_editing_callback(data){
  var el=$('#subscriber_'+data.id+' .'+data.field_name)[0];
  if(!data.success){
    inline_editing_restore(el);
    return alert(data.error);
  }
  $(el)
    .empty()
    .text(data.value);
  el.in_edit=false;
}
$ (document).ready(inline_editing_init);

This is quite a bit more complex than the previous examples, but when broken down function by function, it should make sense.

  • inline_editing_init: This function is used to remove the edit links, and add an event to all names and emails so that the inline_editing_edit function is called if they are clicked.
  • inline_editing_edit: This function is used to convert the table cell into an input box so that it can be edited. It will save the original value. If a key is pressed, it will call the inline_editing_key_pressed function. If the input box is "blurred" (when you click outside the box or change its focus), it will call the inline_editing_save function.
  • inline_editing_save: This function will restore the table cell and exit, if the value of the field has not changed. Otherwise, it will get the ID of the subscriber from the parent <tr> element, the field name from the <td> class, and submit all of that along with the new value through Ajax to ajax_inline-editing.php, with inline_editing_callback as the callback function.
  • inline_editing_key_pressed: This function will be used if the user presses the Esc key. It will simply restore the table cell to its original value.
  • inline_editing_restore: This is the function that handles the restoring.
  • inline_editing_callback: This function will update the table cell with the new value if the server-side save was successful. Otherwise, it will restore the table cell with the original value.

The preceding jQuery script is a bit more complicated than the previous one. You should have no problem understanding each function in itself.

This example shows the jQuery $ object being called in quite a few ways. Some of them have been seen in the chapter already, but I'll describe them all again here, as it's the first example to use them all at the same time.

  • $('#subscribers .edit'): This tells jQuery to run the following method on any elements, which match that CSS. This can be extremely powerful. jQuery has its own internal CSS selector engine, which at the time of writing, is more standards-compliant than every browser's internal engine. You should feel free to use any CSS selector knowledge you have.
  • $(el) and $(this): These are examples of jQuery being run on specified elements. In this case, el is a variable, and this is like the $this variable in PHP's OOP.
  • $('<input>'): In this case, jQuery actually creates the element that it is supposed to run on.
  • $.getJSON: This is an example of jQuery being run with no particular target in mind. You can think of this as similar to calling a static function in a class. In JavaScript, functions and classes are basically the same. Functions can contain subfunctions.

Most functions in $ return an instance of $, which can be used to run further functions on. For example, $(el).empty().text(data.value); empties the el element, and then fills it with text from data.value. This is called chaining. An equivalent in PHP might be:

new jQuery($css_selector)->empty()->text($data->value);

It can sometimes be confusing to read a script and see $ used in some places and not in others. For example, we have the line $(el).html(el.originalHTML); followed immediately by el.in_edit=false;. The shortest way to explain this is that if a jQuery function is to be called, use $; and if a variable is to be set directly on an element, apply it directly.

$ usually returns a $ instance, but in some cases, you will want the actual element being worked on. In this case, you can treat the $ as an array—$(selector)[0] will return the element being worked on, and $(selector)[1] and up will return any others if there are multiple elements being worked on.

Server-side code

As before, I'll supply a sample of PHP. This one again returns success if the subscriber's ID is even and failure if it's odd. Save it as ajax_inline-editing.php.

<?php
$id=(int)$_REQUEST['id'];
$field_name=addslashes($_REQUEST['field_name']);
$value=addslashes($_REQUEST['value']);
echo ( !($id%2) )?
  "{'id':$id, 'field_name':'$field_name', 'success':1,'value':'$value'}":
  "{'id':$id, 'field_name':'$field_name', 'success':0, 'error':'Could not save data'}";
?>
主站蜘蛛池模板: 喀什市| 栖霞市| 专栏| 商洛市| 六安市| 双流县| 大竹县| 铜川市| 越西县| 班戈县| 双桥区| 白银市| 阜新市| 昆山市| 高阳县| 长子县| 满城县| 河间市| 开平市| 嵊泗县| 遵义县| 龙门县| 宽城| 新民市| 新安县| 万盛区| 张掖市| 湾仔区| 九龙县| 都匀市| 琼结县| 鄄城县| 庐江县| 溧阳市| 南充市| 施秉县| 临夏市| 娄烦县| 会同县| 邯郸县| 聊城市|