Возможность перетаскивания была основой настольных приложений в течение многих лет.
С появлением Ajax, возможность перетаскивания теперь нашла свое применение в веб-приложениях. В этой записи я оживлю созданное нами приложение для ведения блогов с возможностью перетаскивания комментариев в корзину. Это подходящая функция для добавления, так как наши собственные блоги здесь на java.net были подвержены спам-атакам через комментарии, которые требуют очистки.
Настройка вещей
Я собираюсь продолжить с того места, где заканчивается учебник « Использование Ajax с Ruby on Rails» . Однако я буду использовать NetBeans 6.1 и Rails 2.0, поэтому вы можете начать с этой обновленной версии проекта rubyweblog, которая была обновлена до Rails 2.0 (вся серия учебников находится в процессе обновления).
Протестируйте существующий проект rubyweblog
- Откройте проект rubyweblog.
- Обратите внимание: если вы начинаете с предоставленного проекта rubyweblog, вам также необходимо создать базу данных rubyweblog_development (Run Rake Task> db> create) и запустить миграцию.
- Запустите проект и перейдите по адресу http: // localhost: 3000 / posts, чтобы убедиться, что он работает. Добавьте хотя бы одну запись в блоге с парой комментариев.
План
В настоящее время приложение не предоставляет средства для удаления комментария. Теперь я знаю, что в этом приложении отсутствует какая-либо пользовательская модель или административный интерфейс, но я намерен показать, как делать классные вещи с помощью Rails, а не создавать замену роликам , поэтому я сжимаю возможности там, где могу. В этом случае я собираюсь добавить значок мусорной корзины на страницу и позволить пользователям перетаскивать комментарии в корзину для удаления.
Шаг 1. Сделайте комментарии перетаскиваемыми
Здесь мы будем использовать помощник draggable_element , оболочку Rails вокруг объекта Scriptaculous Draggable , чтобы сделать комментарии перетаскиваемыми.
- Откройте _comment.html.erb, который является частичным для отображения отдельного комментария, и сделайте его перетаскиваемым, добавив помощник перетаскиваемого элемента в конец файла, как показано ниже жирным шрифтом:
<% comment_id = "comment_#{comment.id}" %>
<li id=<%= comment_id %> >
<%= h comment.comment %><br>
<div style="color: #999; font-size: 8pt">
Posted on <%= comment.created_at.strftime("%B %d, %Y at %I:%M %p") %>
</div>
</li>
<%= draggable_element(comment_id, :revert=>true) %>Обратите внимание, поскольку comment_id используется дважды, я вытащил его в локальную переменную, чтобы сделать код немного чище. Возврат возвращает комментарий в его исходное местоположение, если мы уроним его где-нибудь, кроме корзины (которую мы еще не добавили).
- Добавьте визуальный индикатор того, что комментарии можно перетаскивать. Откройте scaffold.css (Public> stylesheets) и добавьте следующий стиль:
#comments {
cursor: -moz-grab;
} - Проверьте свои изменения. Комментарии теперь можно перетаскивать, но мы пока не указали, где их можно удалить.
Шаг 2. Добавьте значок корзины
- Сохраните (trashfull.jpg) в каталог public / images вашего каталога проекта rubyweblob.
- Откройте show.html.erb и добавьте следующий <image_tag> после <text_area> :
<%= text_area 'comment', 'comment' %>
<%= image_tag "trash.jpg", :id=>'trash'%>
Шаг 3: сделайте значок корзины получателем
Здесь мы будем использовать помощник drop_receiving_element , обертку Rails вокруг метода Scriptaculous Droppables.add, чтобы дать комментарию пункт назначения удаления и вызвать действие для удаления комментария.
- Откройте show.html.erb и добавьте drop_receiving_element в конец файла, как показано ниже:
<%= drop_receiving_element('trash', # The id of the receiving element
:accept => "comment", # The CSS class of the dropped element
:with => "'comment=' + (element.id.split('_').last())", # The query string parameters
:url => {:action=>:trash_comment} # The action to call
)%>Обратите внимание на параметр : with — это фрагмент кода JavaScript, который извлекает идентификатор комментария из идентификатора DOM, который, если вы помните сверху, выглядит как «comment_123». Нам также предстоит проделать определенную работу: во-первых, у нас нет ничего с классом CCS с именем «comment», а во-вторых, нам нужно кодировать действие trash_comment .
- Откройте _comment.html.erb и добавьте class = "comment" в тег <li> :
<li class="comment" id=<%= comment_id %> >
- Откройте posts_controller.rb и добавьте следующее действие trash_comment :
def trash_comment
comment_id = params[:comment]
Comment.delete(comment_id)
render :update do |page|
page.replace_html "comment_#{comment_id}", ""
end
end - Проверьте свои изменения. Перетаскивание комментария в мусорное ведро должно удалить его и удалить его из списка, хотя маркер все еще остается. Это потому, что метод replace_html выше заменяет html внутри элемента маркированного списка. Обтекание маркированных элементов списка в <div> решает эту проблему.
- Откройте _comment.html.erb и оберните <li> в <div> , также переместив свойства class и id в <div> :
<% comment_id = "comment_#{comment.id}" %>
<div class="comment" id=<%= comment_id %> >
<li>
<%= h comment.comment %><br>
<div style="color: #999; font-size: 8pt">
Posted on <%= comment.created_at.strftime("%B %d, %Y at %I:%M %p") %>
</div>
</li>
</div>
<%= draggable_element(comment_id, :revert=>true) %> - Теперь комментарии должны полностью удалить.
Шаг 4: Добавление визуальных подсказок о том, что происходит
- Сохраните (trashfull.jpg) в каталог public / images вашего каталога проекта rubyweblob.
- Добавьте пару методов JavaScript в show.html.erb, чтобы поменять источник изображения корзины с пустого на полный и обратно:
<script>
function fill_trash() {
$('trash').src = "/images/trashfull.jpg";
}
function empty_trash() {
$('trash').src = "/images/trash.jpg";
}
</script> - Добавьте пару свойств к drop_receiving_element метода : onHover и : полная:
<%= drop_receiving_element('trash', # The id of the receiving element
:accept => "comment", # The CSS class of the dropped element
:with => "'comment=' + (element.id.split('_').last())", # The query string parameters
:url => {:action=>:trash_comment}, # The action to call
:onHover => "function() {fill_trash()}",
:complete => "empty_trash()"
)%>Обратите внимание, я не могу сказать вам почему : onHover требует определения функции while : complete принимает любой произвольный JavaScript, но это так.
- Проверьте свои изменения. Теперь вы должны увидеть полную корзину для мусора, когда перетащите комментарий поверх нее, а затем снова очистите ее после завершения удаления.
- Есть еще одна небольшая проблема — если вы перетащите комментарий на корзину, но на самом деле не удалите ее, ваша корзина останется заполненной. Мы можем исправить это, используя событие onMouseOut . Добавьте его к тегу image следующим образом:
<%= image_tag "trash.jpg", :id=>'trash', :onMouseOut=>"empty_trash()"%>
И это должно в значительной степени завершить функциональность перетаскивания. Не забудьте обновить браузер, чтобы получать изменения в Javascript. Кроме того, Firebug — ваш друг, когда вы работаете с Ajax и не видите того, чего ожидаете.