setTimeout vs window.setTimeout
В приведенном выше синтаксисе используется window.setTimeout. Почему?
На самом деле, setTimeout и window.setTimeout – это практически одна и та же функция. Единственная разница заключается в том, что во втором выражении мы используем метод setTimeout как свойство глобального объекта window.
Лично я считаю, что это лишь сильно усложняет код. Если бы мы определили альтернативный метод JavaScript timeout, который может быть найден и возвращен в приоритетном порядке, то столкнулись бы с еще большими проблемами.
В данном руководстве я не хочу связываться с объектом window, но в целом, вы сами решаете, какой синтаксис стоит использовать.
Что делать, если обнаружили скрытый редирект на сайте
Действия по исправлению зависят от причины, по которой появилась скрытая переадресация.
Внимание! Перед тем как что-то делать с работающим сайтом, создайте резервную копию на хостинге и проверьте, работает ли она
Если сайт взломали злоумышленники
У вас должны быть резервные работающие копии, попробуйте восстановить сайт. Для проверки на вирусы обратитесь к хостеру, обычно хостинги предоставляют такую услугу. Проверка покажет, где вирусы и что нужно удалить.
Можно поискать код вручную, часто зловредные элементы прописывают в этих местах:
-
в .htaccess — обычно это выглядит как определение устройства по юзер-агенту и переадресация;
-
в index.php в корне сайта — обфусцированный код в конце файла, огромные строки кода легко заметить и удалить;
-
в .js-файлах — аналогично, код в конце файла.
Обязательно обновите пароли — от хостинга, FTP, панели администратора и базы данных.
Если виноваты скрипты виджетов
Редирект на чужой сайт может работать через сторонние скрипты, плагины, шаблоны CMS, темы, другие элементы. Виноваты могут быть как новые недавно установленные плагины, так и те, которые давно стоят, но уже устарели — их могли взломать.
Если вы сами ничего не устанавливали, посмотрите историю доступов к сайту. Возможно, другие администраторы или модераторы поставили какой-то зараженный скрипт по незнанию или даже чтобы вам навредить
Что делать:
-
Найдите какую-то из страниц, на которой срабатывает переадресация мобильного трафика, посмотрите код. Если на ней находятся чужие скрипты и элементы — удаляйте их по одному. Код перенаправления нужно искать в тегах script и iframe . Он может иметь вид
-
После каждого удаления заходите на страницу со смартфона или через эмулятор браузера, и проверяйте, остался ли редирект.
-
Как только вы найдете этот вредный элемент, удалите его с других страниц. Если заражен был какой-то важный плагин, проверьте актуальность версии. Напишите разработчику, возможно, он уже поправил уязвимость.
Обязательно обновите CMS и плагины до последней стабильной версии, удалите все, что вызывает подозрение и подберите лицензионные решения с официальных источников.
Если веб-мастер сотрудничает с некачественными партнерками
Еще одна причина — веб-мастер специально или неосознанно сотрудничает с фейковыми партнерскими системами. Обычно они притворяются простыми партнерками с баннерной рекламой.
Часто такие партнерки рекламируются в Яндекс.Директе и Google Ads или присылают предложения сотрудничества на почту, представляясь маркетинговыми агентствами и обещая подозрительно высокий доход. Прекращайте работу с такими партнерками и отказывайтесь от подозрительных предложений.
Настройка перенаправлений на распространённых серверах
Перенаправления могут быть установлены или в настройках сервера, или в каждой директории в файле .
У модуля mod_alias есть директивы и которые, по умолчанию, устанавливают код ответа :
<VirtualHost *:80> ServerName example.com Redirect / http://www.example.com </VirtualHost>
URL будет перенаправлен к (но не к )
делает то же, но использует регулярное выражение, чтобы определить множество URL адресов, которые подпадут под эффект:
RedirectMatch ^/images/(.*)$ http://images.example.com/$1
Все документы в папке будут перенаправляться к другому домену.
Если вы не хотите устанавливать временное перенаправление, дополнительный параметр (используйте или код статуса HTTP, или ключевое слово может использоваться чтобы установить другое перенаправление:
Redirect permanent / http://www.example.com Redirect 301 / http://www.example.com
Также модуль mod_rewrite может использоваться для создания перенаправлений. Они более гибкие, но сложнее в использовании.
В Nginx, вы создаёте особый серверный блок для контента, который вы хотите перенаправлять:
server { listen 80; server_name example.com; return 301 $scheme://www.example.com$request_uri; }
Чтобы применить перенаправления к папке или подмножеству страниц, используйте директиву :
rewrite ^/images/(.*)$ http://images.example.com/$1 redirect; rewrite ^/images/(.*)$ http://images.example.com/$1 permanent;
В IIS, вы используете элемент для настройки перенаправлений.
Как настроить редирект
Настроить редирект можно несколькими способами: изменяя код в файле .htaccess, через админку сайта или в специальных сервисах
Важно: работа с файлом .htaccess возможна при использовании на хостинге веб-сервера Apache
Для работы в .htaccess нужно установить FTP-клиент (например, filezilla.ru или totalcommander.ru) и уметь работать с кодом, поэтому такой способ сложнее. Обычно его выбирают, когда нужно перенести домен и сделать это бесплатно. Более лёгкий способ — купить доступ к сервису. Тогда знания кода не нужны.
Если нужно сделать перенаправление со страницы, подойдёт более простой вариант переноса — через админку сайта.
В этой статье рассмотрим эти способы на примере самых распространённых причин для редиректа.
Перенос сайта с одного домена на другой
Этот тип перенаправления можно сделать с помощью FTP-клиента. Этот вариант подойдёт тем, кто умеет работать с кодом или готов этому научиться.
Если язык программирования не для вас, перенести домен можно без знаний кода. У RU-CENTER есть специальный сервис «Перенаправление домена».
Перенос с помощью FTP-клиента
Откройте FTP-клиент и найдите файл .htaccess в корневом каталоге вашего сайта. Уточнить путь к корневому каталогу вы можете у вашего хостинг-провайдера. Если в корневом каталоге сайта нет файла .htaccess, создайте новый файл с таким именем (точка в начале имени обязательна).
Пример класса jQuery.each()
В этом примере показано, как перебрать каждый элемент с классом productDescription:
<div class="productDescription">Красный</div> <div>Розовый</div> <div class="productDescription">Оранжевый</div> <div class="generalDescription">Синевато-зеленый</div> <div class="productDescription">Зеленый</div>
Вместе с селектором мы используем вспомогательную функцию each() вместо метода each():
$.each($('.productDescription'), function (index, value) { console.log(index + ':' + $(value).text()); });
Результат использования jQuery each function будет следующим: 0:Красный, 1: Оранжевый, 2:Зеленый.
Нам не нужно использовать индекс и значение. Это параметры, которые помогают определить, какой элемент DOM в настоящее время обрабатывается циклом. Кроме этого в сценарии можно использовать более удобный метод each():
$('.productDescription').each(function () { console.log($(this).text()); });
Результат:
Красный Оранжевый Зеленый
Нужно обернуть элемент DOM в новый экземпляр jQuery. Мы используем метод text() для получения текста элемента.
Ответы на часто задаваемые вопросы о переносе сайта с изменением URL
- Не противоречит ли рекомендациям Google перенос сайта по частям?Нет, не противоречит.
-
Как узнать, сколько страниц проиндексировано?
Выберите нужный ресурс в Search Console и откройте отчет об индексировании, в котором приводится общая статистика. Чтобы узнать, сколько страниц из перечисленных в файлах Sitemap было проиндексировано, воспользуйтесь специальным отчетом. -
Сколько времени потребуется Google, чтобы распознать изменения URL?
Точный срок назвать невозможно, поскольку он зависит от размера сайта и скорости сканирования. URL сайта переносятся поочередно. -
Не перестанут ли ссылки учитываться при оценке моих страниц, если я настрою переадресацию на новые URL?
Нет. Переадресация 301 или 302 не приводит к ухудшению оценки в системе PageRank.
Задаем стили для перетаскиваемого элемента
Иногда важно придать перетаскиваемому элементу другой вид. Например, нужно выделять перетаскиваемый элемент, или добавить тень для него, чтобы он выглядел приподнятым над страницей
При перетаскивании элемента jQuery UI использует для него класс CSS . Вы можете установить свойства для данного класса, чтобы изменить стиль перетаскиваемого элемента.
Изменим код нашего примера так, чтобы квадрат менял цвет с красного на зеленый при перетаскивании:
<style> #makeMeDraggable { width: 300px; height: 300px; background: red; } #makeMeDraggable.ui-draggable-dragging { background: green; } </style>
Работа с выборкой
После создания объекта jQuery содержащего вашу выборку, вы, вероятно, хотите что-то с ней сделать. Но до этого рассмотрим несколько принципов, которые являются ключевыми для понимания того, что делает jQuery.
Проверка выборки
Мы можем определить, соответствует ли выборка определённому критерию, с помощью метода .is(). Этот метод наиболее часто используется, чтобы предоставить селектор в качестве единственного аргумента. Он возвращает true или false в зависимости от того, соответствует ли выборка селектору:
Вы также можете передать в метод .is() объект jQuery, исходный элемент DOM или даже функцию, если вам нужна комплексная проверка. Смотрите документацию для получения подробной информации.
Получение, установка и неявный перебор
Есть много методов, которые вы можете вызвать после создания выборки. Эти методы, как правило, делятся на две категории: метод чтения (геттер) и устанавливающий метод (сеттер). Методы чтения извлекают фрагмент информации из выборки, а методы установки в некотором роде изменяют выборку. Практически во всех случаях методы чтения оперируют только первым элементом в выборке (.text() является известным исключением); методы установки же работают для всех элементов в выборке используя то, что известно как неявный перебор.
Неявный перебор означает, что jQuery автоматически перебирает все элементы в выборке, когда вы вызываете для выборки устанавливающий метод. Это означает, что если вы хотите сделать что-то для всех элементов в выборке, то не должны вызывать метод для каждого элемента в вашей выборке — просто вызываете метод для самой выборки и jQuery обработает элементы для вас.
Предположим, что вы хотите изменить HTML у всех пунктов списка на странице. Чтобы сделать это мы должны использовать метод .html(), который изменит HTML у всех выбранных пунктов списка.
Вы также можете передать функцию в метод установки jQuery. Возвращаемое значение этой функции используется в качестве нового значения и оно получает два аргумента: индекс элемента в выборке и старое значение, которое вы пытаетесь изменить. Это полезно, когда вам необходима информация о текущем состоянии элемента, чтобы правильно установить новое состояние.
Явный перебор
Иногда задача, которую вы пытаетесь решить, не вписываются ни в один из существующих методов jQuery и тогда вы должны сделать явный перебор выборки с помощью метода .each(). В следующем коде в начало пункта списка мы добавляем тег <b> содержащий индекс элемента списка.
Заметьте, что внутри функции, которую мы передаём в .each(), у нас есть два способа доступа к текущему исходному элементу DOM: через this и через elem. Как обсуждалось в разделе «Основы JavaScript», this — специальное ключевое слово в JavaScript, указатель на объект, который является текущим контекстом функции. В jQuery this почти всегда относится к исходному элементу DOM, с которым функция в данный момент работает. Так, в случае .each(), this относится к текущему элементу в наборе элементов которые мы перебираем.
Цепочки
Одной из самых выгодных частей jQuery является способность «сцеплять» методы вместе. Это означает, что мы можем вызвать набор методов для выборки без её повторения или сохранения выборки в переменной. Мы даже можем сделать новые выборки на основе предыдущих и всё без разрыва цепочки.
Цепочки возможны, потому что каждый устанавливающий метод в jQuery возвращает выборку, с которой он был вызван. Это чрезвычайно мощная особенность и многие библиотеки взяли её на вооружение
Тем не менее, она должна применяться с осторожностью. Большие цепочки могут сделать код чрезвычайно трудным для чтения, изменения и отладки
Нет жёстких правил, насколько длинной должна быть цепочка, но даже для простой цепочки выше, вероятно, следует провести рефакторинг для удобства чтения.
Отслеживайте трафик
После начала переноса следите за тем, как изменяется трафик поисковых роботов и пользователей на новом сайте и на старом. Желательно, чтобы на новом сайте трафик рос, а на старом – уменьшался. Отслеживать действия роботов и посетителей на сайте можно с помощью Search Console и других инструментов.
Отслеживайте трафик с помощью Search Console
В Search Console есть много функций, которые позволяют следить за тем, как выполняется перенос сайта:
- Файлы Sitemap. Отправьте нам два таких файла, ранее сохраненных при сопоставлении URL. Первоначально в файле Sitemap с новыми URL нет проиндексированных страниц, тогда как в файле Sitemap со старыми URL таких страниц много. По мере индексации новых URL число проиндексированных страниц из файла Sitemap со старыми URL упадет до нуля.
- Отчет об индексировании. Перенос сайта отражается на диаграммах. Число проиндексированных URL на прежнем сайте упадет, а на новом – увеличится. Регулярно проверяйте, не возникло ли непредвиденных ошибок сканирования.
- Поисковые запросы. По мере того как страницы нового сайта будут индексироваться и оцениваться системой PageRank, в отчетах по поисковым запросам станут появляться новые URL с указанием количества показов и кликов в результатах поиска.
Используйте другие инструменты для отслеживания трафика
Периодически просматривайте журналы обращений к серверам и ошибок, проверяйте результаты сканирования страниц роботом Googlebot, выявляйте URL, которые необоснованно выводят коды ошибок HTTP, и отслеживайте обычный пользовательский трафик.
Если вы установили на сайте средство веб-аналитики или если аналитику выполняет ваша система управления контентом, рекомендуем дополнительно изучать данные, полученные таким способом. Это позволит вам отмечать, как идет переориентация трафика на новый сайт. В частности, вы можете использовать сервис «Google Аналитика»
В нем доступны отчеты в режиме реального времени, а это особенно важно на начальном этапе переноса сайта. Вы должны быть готовы к тому, что трафик прежнего сайта уменьшится, а нового – увеличится
Использование метатегов HTML для редиректа
Также можно использовать базовый HTML для выполнения редиректа. Это может показаться непрофессиональным, но это работает. И не нужно беспокоиться о том, что в браузере отключен JavaScript или ранее была отправлена ошибка заголовков:
<meta http-equiv="Location" content="http://example.com/final.php"> <!-- The following line will redirect after the given number of seconds. Zero in our case. --> <meta http-equiv="refresh" content="0;url=http://example.com/final.php">
Также можно использовать последнюю строку из предыдущего примера, чтобы автоматически обновлять страницу каждые «n» секунд. Например, следующий код будет автоматически обновлять страницу каждые 8 секунд:
<meta http-equiv="refresh" content="8">
Выбор элементов по атрибуту
Основные селекторы отлично подходят в случаях, если нужно выбрать все параграфы на странице или элемент, который нужно выбрать имеет класс CSS или ID.
Однако, иногда нужно выбрать определенный элемент, у которого нет класса или ID, и нет возможности просто добавить класс или ID к данному элементу в разметке. Такая ситуация может сложиться при использовании CMS с фиксированным шаблоном HTML или при работе с контентом, созданным пользователем.
В данной ситуации возможно сузить область выбора с помощью атрибута HTML элемента, который надо выбрать. Например, можно выбрать:
- Изображение по атрибуту
- Ссылку по атрибуту
- Все поля формы, которые имеют атрибут
…и так далее.
jQuery имеет много селекторов, которые можно использовать для выбора элементов по атрибуту:
Селектор | Описание | Пример |
---|---|---|
Атрибут | Выбирает элемент(ы), которые содержат определенный атрибут вне зависимости от значения атрибута. | |
Атрибут равен | Выбирает элемент(ы), которые содержат заданный атрибут с заданным значением. | |
Атрибут не равен | Выбирает элемент(ы), которые не содержат заданного атрибута или сожержат заданный атрибут, но его значение не соответствует заданному. | |
Атрибут начинается с | Выбирает элемент(ы), которые содержат заданный атрибут, у которого значение начинается с заданной строки. | |
Атрибут заканчивается | Выбирает элемент(ы), которые содержат атрибут, у которого значение заканчивается заданной строкой. | |
Атрибут содержит | Выбирает элемент(ы), который содержит атрибут, у которого значение содержит заданную строку. | |
Атрибут содержит слово | Выбирает элемент(ы), который содержит атрибут, у которого значение содержит заданное слово. «Слово» — это последовательность символов без пробелов. | |
Атрибут содержит префикс | Выбирает элемент(ы), который содержит атрибут, у которого значение либо равно заданной строке, либо начинается с заданной строки с последующим дефисом. |
Вы можете комбинировать селекторы атрибутов для сужения области выбора. Например:
// Выбираем только те изображения, которые имеют ширину 300 px и высоту 200 px var selectedImages = $("img");
Селектор «Атрибут содержит префикс» выглядит неэффективно, но он сделан для обработки атрибутов языка, таких как и .
Принцип работы
В HTTP, перенаправление вызывается при отправке сервером специального ответа на запрос: redirects. HTTP перенаправление, это ответы с кодом статуса. Когда браузер получает ответ перенаправления, он использует новый предоставленный URL-адрес и немедленно загружает его: в большинстве случаев переадресация невидима для пользователя, за исключением небольшого влияния производительность.
Есть несколько типов перенаправлений и делятся на три категории: постоянные, временные и специальные перенаправления.
Эти перенаправления призваны длиться вечно. Они подразумевают, что оригинальный URL-адрес больше не должен использоваться, а вместо него должен быть использован новый. Поисковые роботы запускают обновление связанного URL-адреса для ресурса в своих индексах.
Код | Текст | Обработка метода | Случаи использования |
---|---|---|---|
методы неизменны. Другие методы могут быть превращены в . |
Реорганизация веб-сайта. | ||
Метод и тело запроса неизменны. | Реорганизация веб-сайта, с не-GET ссылками/операциями. |
Спецификация не была намерена разрешать изменение метода, но на практике, клиентские приложения делают это. Код был создан чтобы избавиться от неоднозначности в поведении, при использовании не- методов.
Иногда, доступ к запрашиваемому ресурсу не может быть предоставлен из определённого места, но может быть предоставлен из другого. В этом случае, могут быть использованы временные перенаправления. Поисковые роботы не запоминают новую, временную ссылку. Временные перенаправления также используются, когда создаются, обновляются, или удаляются ресурсы, которые представляют временные страницы.
Код | Текст | Обработка метода | Случаи использования |
---|---|---|---|
методы неизменны. Другие методы могут быть превращены в . |
Веб-страница недоступна по непредвиденным причинам. В этом случае поисковые роботы не будут обновлять свои ссылки. | ||
методы неизменны. Другие превращены в (тело запроса теряется). |
Используется для перенаправления после или для предотвращения обновления страницы, что может спровоцировать повторный вызов операции. | ||
Метод и тело запроса неизменны. | Веб-страница недоступна по непредвиденным причинам. В этом случае поисковые роботы не будут обновлять свои ссылки. Лучше чем код когда не-GET ссылки/операции доступны на сайте. |
Спецификация не была намерена разрешать изменение метода, но на практике, клиентские приложения делают это. Код был создан чтобы избавиться от неоднозначности в поведении, при использовании не- методов.
В добавок к обычным перенаправлениям, есть 2 специальные. Перенаправление с кодом (Not Modified) перенаправляет страницу к локальной закешированной копии (которая была устаревшей), и перенаправление с кодом (Multiple Choice) это ручное перенаправление: тело, представленное браузером, как веб-страница, перечисляет возможные перенаправления и пользователь выбирает одно из них.
Код | Текст | Случаи использования |
---|---|---|
Не так много: варианты перечислены на HTML странице. Может быть обслужен со статусом . | ||
Обновление кеша: означает, что значение кеша все ещё актуально и может быть использовано. |
Пример использования 2: таблицы
Во втором примере у нас есть таблица, которая отображает информацию о пользователе, скажем, как компонент в панели инструментов. У каждого пользователя есть идентификатор, но вместо того, чтобы показывать его, мы сохраняем его как атрибут data для каждого элемента <tr>.
<table> <!-- ... --> <tr data-userid="1"> <td> <input type="checkbox" data-action="select"> </td> <td>John Doe</td> <td>[email protected]</td> <td> <button type="button" data-action="edit">Edit</button> <button type="button" data-action="delete">Delete</button> </td> </tr> </table>
Последний столбец содержит две кнопки для редактирования и удаления пользователя из таблицы. Первая кнопка имеет атрибут data-action edit, а вторая — delete. Когда мы кликаем по любой из них, мы хотим вызвать какое-то действие (например, отправку запроса на сервер), но для этого необходим идентификатор пользователя.
Прослушиватель события клика прикреплен к глобальному объекту окна, поэтому всякий раз, когда пользователь кликает где-нибудь на странице, вызывается функция обратного вызова handleClick.
function handleClick(evt) { var { action } = evt.target.dataset; if (action) { // `action` существует только для кнопок и чек-боксов в таблице. let userId = getUserId(evt.target); if (action == "edit") { alert(`Edit user with ID of ${userId}`); } else if (action == "delete") { alert(`Delete user with ID of ${userId}`); } else if (action == "select") { alert(`Selected user with ID of ${userId}`); } } }
Если клик происходит где-то еще, кроме одной из этих кнопок, атрибут data-action не существует, следовательно, ничего не происходит. Однако при нажатии любой кнопки будет определено действие (кстати, это называется делегированием события), и на следующем шаге идентификатор пользователя будет получен путем вызова getUserId.
function getUserId(target) { // `target` - это всегда кнопка или чек-бокс. return target.closest("").dataset.userid; }
Эта функция ожидает, что узел DOM является единственным параметром, и при вызове использует его Element.closest для поиска строки таблицы, содержащей нажатую кнопку. Затем он возвращает значение data-userid, которое теперь можно использовать для отправки запроса на сервер.
Альтернативные URL
Когда настроена переадресация, Google отслеживает и исходный URL (старый), и конечный (новый). Один из них будет считаться каноническим. Какой именно – зависит от нескольких факторов, в частности от того, является ли переадресация постоянной или временной. Второй URL станет альтернативным вариантом канонического. Альтернативный URL может появиться в результатах поиска, если запрос будет указывать на то, что пользователь с большей вероятностью перейдет именно по этому адресу.
Например, после смены доменного имени сайта старые URL иногда могут появляться в результатах поиска Google даже после того, как будут проиндексированы новые URL. Это нормальное явление. Постепенно пользователи привыкнут к новому доменному имени, и альтернативные URL исчезнут из результатов поиска без вашего вмешательства.
Делаем элемент перетаскиваемым
Когда вы добавляете элемент к вашей веб странице (например, или изображение), то он фиксируется в определённом положении. Однако с помощью jQuery UI легко сделать его перетаскиваемым с помощью курсора мыши.
Чтобы сделать элемент перемещаемым, просто вызываем метод для него. Вот так:
<!doctype html> <html lang="ru"> <head> <style> #makeMeDraggable { width: 300px; height: 300px; background: red; } </style> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script> <script type="text/javascript"> $( init ); function init() { $('#makeMeDraggable').draggable(); } </script> </head> <body>
События: реагируем на перемещения
Часто, когда пользователь перетаскивает элемент, нужно знать, когда перетаскивание началось и закончилось, а также новое положение элемента. Вы можете привязать функции для обработки нескольких событий, которые генерируются операцией перетаскивания:
$('#makeMeDraggable').draggable( { eventName: eventHandler, ... } );
Список доступных событий:
- Генерируется при создании перетаскиваемого элемента вызовом функции .
- Генерируется при начале процесса перетаскивания элемента.
- Генерируется при перемещении курсора мыши в процессе перетаскивания элемента.
- Генерируется, когда пользователь отпускает кнопку мыши после перетаскивания элемента.
Обработчик события должен принимать 2 аргумента:
- Объект события ().
- Объект jQuery UI, который представляет перетаскиваемый элемент ().
Для объекта доступны 3 опции для получения информации о перетаскиваемом элементе:
- Объект jQuery, который представляет вспомогательный элемент для перетаскивания.
- Объект, который содержит положение перетаскиваемого элемента относительно оригинальной позиции. Объект имеет два свойства: (X координата от левой границы элемента), и (Y координата от верхней границы элемента).
- Объект, который содержит положение перетаскиваемого элемента относительно документа. Как и объект , он имеет два свойства и .
Изменим наш пример так, чтобы он показывал информацию о конечном положении перетаскиваемого элемента относительно документа, когда пользователь отпускает кнопку мыши:
<script type="text/javascript"> $( init ); function init() { $('#makeMeDraggable').draggable( { cursor: 'move', containment: 'document', stop: handleDragStop } ); } function handleDragStop( event, ui ) { var offsetXPos = parseInt( ui.offset.left ); var offsetYPos = parseInt( ui.offset.top ); alert( "Перетаскивание завершено!\n\nСмещение: (" + offsetXPos + ", " + offsetYPos + ")\n"); } </script>