Удобное дерево с AJAX-подгрузкой
Эта статья показывает, как написать простое и удобное дерево с AJAX-подгрузкой узлов.
Она основана на материалах грамотное javascript-дерево и интеграция AJAX в интерфейс.
Добавить AJAX-подгрузку, используя эти две технологии - очень просто. Вообще, это может послужить основой для того, чтобы создавать любые AJAX-виджеты и сложные системы интерфейсов.
Для начала оформим дерево в виде компоненты интерфейса. Инициализацию будет осуществлять функция tree , которая получает два параметра:
- id
- ID узла DOM, который служит контейнером для дерева
- url
- Адрес, с которого подгружать узлы при помощи AJAX-запроса
Код ниже полностью описывает дерево, за исключением функции AJAX-подгрузки узлов load , которая будет разобрана ниже. Он полностью соответствует оригинальной статье, только чуть реорганизован.
Все, что он делает - это отслеживает клик на элементе element.onclick , содержащем дерево, получает узел по event.target и, если узел не содержит элементов и еще не было попыток загрузки - то получает его с сервера вызовом load . Саму функцию загрузки load разберем дальше в статье.
Функции hasClass и toggleNode - вспомогательные, для индикации скрытия-открытия ветки дерева через CSS-класс.
function tree(id, url) {
var element = document.getElementById(id)
/* вспомогательная функция */
function hasClass(elem, className) {
return new RegExp("(^|\\s)"+className+"(\\s|$)").test(elem.className)
}
function toggleNode(node) {
// определить новый класс для узла
var newClass = hasClass(node, 'ExpandOpen') ? 'ExpandClosed' : 'ExpandOpen'
// заменить текущий класс на newClass
// регексп находит отдельно стоящий open|close и меняет на newClass
var re = /(^|\s)(ExpandOpen|ExpandClosed)(\s|$)/
node.className = node.className.replace(re, '$1'+newClass+'$3')
}
function load(node) {/* ... загрузить узел с сервера, код далее ... */}
element.onclick = function(event) {
event = event || window.event
var clickedElem = event.target || event.srcElement
if (!hasClass(clickedElem, 'Expand')) {
return // клик не там
}
// Node, на который кликнули
var node = clickedElem.parentNode
if (hasClass(node, 'ExpandLeaf')) {
return // клик на листе
}
if (node.isLoaded || node.getElementsByTagName('LI').length) {
// Узел уже загружен через AJAX(возможно он пуст)
toggleNode(node)
return
}
if (node.getElementsByTagName('LI').length) {
// Узел не был загружен при помощи AJAX, но у него почему-то есть потомки
// Например, эти узлы были в DOM дерева до вызова tree()
// Как правило, это "структурные" узлы
// ничего подгружать не надо
toggleNode(node)
return
}
// загрузить узел
load(node)
}
}
Чтобы инициализовать дерево - достаточно запустить функцию tree на DOM-контейнере для дерева.
Вспомним, что согласно структуре дерева - для этого служит элемент UL .
Можно взять дерево с уже готовыми узлами, а можно и пустое дерево с единственным корневым узлом "Каталог", вот такого вида (просто картинка, рабочий вариант далее):
HTML-код:
Наше дерево:
<ul class="Container" id="tree">
<li class="Node IsRoot IsLast ExpandClosed">
<div class="Expand"></div>
<div class="Content">Каталог</div>
<ul class="Container">
</ul>
</li>
</ul>
Яваскрипт-вызов для инициализации дерева:
tree('id', '/ajax/data.php')
После этого вызова дерево становится полностью рабочим, но узлы подгружать пока не умеет.
Для этого нужно реализовать метод load и необходимые вспомогательные функции.
При описании дерева была предусмотрена AJAX-индикация, а в статье по интеграции AJAX в интерфейс - стандартные методы и последовательность вызовов. Остается применить их для дерева.
...
function load(node) {
/*
код этих трех функций -
как в статье по интеграции AJAX в интерфейсы
*/
function onSuccess(data) {... }
function onAjaxError(xhr, status) {... }
function onLoadError(error) { ...}
/*
функция showLoading использует способ
AJAX-индикации через CSS из этой же статьи.
*/
function showLoading(on) {
var expand = node.getElementsByTagName('DIV')[0]
expand.className = on ? 'ExpandLoading' : 'Expand'
}
function onLoaded(data) {
for(var i=0; i<data.length; i++) {
var child = data[i]
var li = document.createElement('LI')
li.id = child.id
li.className = "Node Expand" + (child.isFolder ? 'Closed' : 'Leaf')
if (i == data.length-1) li.className += ' IsLast'
li.innerHTML = '<div class="Expand"></div><div class="Content">'+child.title+'</div>'
if (child.isFolder) {
li.innerHTML += '<ul class="Container"></ul>'
}
node.getElementsByTagName('UL')[0].appendChild(li)
}
node.isLoaded = true
toggleNode(node)
}
showLoading(true)
$.ajax({
url: url,
data: node.id,
dataType: "json",
success: onSuccess,
error: onAjaxError,
cache: false
})
}
...
Для начала заметим, что все вспомогательные функции объявлены внутри load . Это удобно, т.к. автоматически дает им доступ к узлу node .
Можно вызвать новую загрузку load , не дожидаясь окончания текущей - конфликта доступа не произойдет, т.к обработчики через замыкание привязаны к загружаемому узлу.
Оригинальная функция здесь, пожалуй, всего одна - это onLoaded . Она принимает данные с сервера в виде массива объектов-детей:
[
{ id: 1, title: 'Node 1', isFolder: 1},
{ id: 2, title: 'Node 2', isFolder: 1},
{ id: 3, title: 'Node 3', isFolder: 0}
]
Из этих объектов создается DOM-структура дерева.
Никаких новых обработчиков событий при создании узлов на них не навешивается, т.к структура дерева использует один единый обработчик на контейнере.
Жмите на +, чтобы загрузить детей с сервера.
На стороне сервера используется скрипт, который сначала полсекунды спит (чтобы продемонстрировать индикацию загрузки), а затем возвращает 3 узла с последовательными номерами и примерно 33%-ным шансом того, что узел является листовым (isFolder=0).
Вы также можете:
|
А как изменить этот скрипт, чтобы в скрытом фрейме отправлял запрос вместо аякс, а то в ИЕ6 по умолчанию отключен activeX и не отсылается или запрашивает подтверждение для включенияактивного содержимого?
Осталось еще добавить фунуцию перетаскивания узлов в дереве и между несколькими деревьями и будет перфект контрол
Да, я это когда-то все делал. В принципе, никаких проблем - статья про drag'n'drop на сайте есть. Все что надо - замечательно реализуется.
Статья очень классная, спасибо за неё!
Но у меня есть один вопрос - как в php'шном скрипте здесь узнать значение узла по которому кликнули? (т.е. то что значится как Node 1,2,3)?
Эта информация содержится в ajax-запросе:
Если что - извиняюсь за глупые вопросы ><
то что оно в этой строке содержится я разобралась. А вот как этот node.id в php вытащить?... перечитала учебника 3 и что-то не разобралась( статьи про jquery тож не помогли(
дай хотябы ссылку на то где это объясняется
Илья, огромное спасибо за статью!
Не подскажите, как сделать подгрузку узлов для бесконечного дерева из БД.
Модифицируйте PHP-скрипт, чтобы вместо генерации узлов он брал их из базы.
Если у вас возникают проблемы с node.id - убедитесь, что у каждого DOM-узла дерева есть ID. Это и есть node.id.
Ещё раз респект и уважуха Илья! Уже присоветовал сайт пацанам на работе.
Оо! Большое спасибо за багрепорт.
Как я понял - все дело было в том, что загружаемым узлам не ставился id, да ?
Исправил в тексте статьи, обновил скрипты и архив.
Да, и ещё такой вот запрос:
Добавила, что-то не заработало
источник:http://api.jquery.com/jQuery.ajax/
Как исправить функцию onLoaded, что бы это дерево не было бесконечным?
Дерево бесконечное только потому, что ПХП-скрипт на сервере возвращает все новые узлы.
В реальной жизни все будет конечное.. Обычно
разобрался как работает... алгоритм тут хитрый
Расскажите пожалуйста как это работает. Как рисуются вертикальные палочки, как добавляется строки, как все ровно так сдвигается. Из исходников не понятно как это рисуется.
Растолкуйте плиз. очень надо такую штуку а как оно работает непонимаю.
Со html структорой разобрался, тепер надо поразбираться с функциями
Спасибо за дерево, отличная штука!
Никак не могу понять, как надо привесить обработчик клика на текст элемента дерева. Помогите пожалуйста.
Виноват, поторопился с вопросом.
Всё очень просто. Для динамически генерируемых узлов надо добавить свой onlick в функцию
Это примерно 60 строка tree.js
В том-то и дело, что ничего не надо добавлять.
onclick один на все дерево.
Просто вставляете узел и оно будет работать.
Реализовывал свой аналогичный компонент. Во многом применял похожие приёмы.
Единственное чем недоволен - тем что использовал таблицы вместо списков. Но было требование, что новое дерево должно быть совместимо по формату с предыдущей версией.
Очень полезная функция - инициализация узлов дерева on demand - демка (из JSON очень быстро строится дерево с 500.000.000 узлами). Как показала практика - существует очень много пользователей, которым очень нужна эта функция.
Я кликнул мышкой по надписи Node 2, как определить, описание какой ветки нужно вывести рядом? Я так понял Node 2 - это DIV, значить при создании нового узла, надо присваевать второму диву который является классом content, идентификатор (например "div_"+child.id), потом вешать на него обработчик onclick, и дальше обрабатывать аяксом элемент в котором должно появиться описание данного узла, можно и с пхп, но прийдеться перегружать страницу, а отсюда проблема сохранения состояния дерева!
Если я не прав, то поправьте меня, просто не вижу смысла в этом дереве, если оно просто открывает и закрывает ветки, а просмотреть информацию по данной ветки, у него, как я понял мозгов нет!
Далее--------------
Автор: TT (не зарегистрирован), дата: вт., 19/05/2009 - 20:54
#permalink
Статья очень классная, спасибо за неё!
Но у меня есть один вопрос - как в php'шном скрипте здесь узнать значение узла по которому кликнули? (т.е. то что значится как Node 1,2,3)?
* Ответить
Автор: Илья Кантор, дата: вт., 19/05/2009 - 22:56
#permalink
Эта информация содержится в ajax-запросе:
Выделить все
.ajax(
...
data: node.id
...
)
это про то что я писал выше, человек спрашивал, как отловить нажатие на надписе, и узнать по какой именно был клик! Вопрос автору: описанный мною вариант имеет смысл, или я что-накрутил? Второй день копаюсь в коде, с некоторыми приколами так и не разобрался!
Вопрос номер 2: как сохранить состояние дерева, при перезагрузке страницы! Все открытые ветки пересылать по сессии, а потом циклом выводить, и присваивать каждой открытой function() { tree("tree", "data.php") }, это, мне кажеться, и вам понятно что полная чуш!
Есть какие нить предложения?
Заранее благодарен!
Спасибо за отличный скрипт!
Но не магу разобраться с одним моментом
Как можно скриптом скрыть и загрузить заново список детей в одной из папок?
В моем приложение это дерево ещё и редактируеться
И ещё как можно средствами javascript открыть одну из папок
Спасибо большое за деревко!
Подскажите, пожалуйста, почему у меня $id не передаётся? Подставляю в запрос циферку - работает, только, конечно же, один и тот же уровень всё время.
ЗЫ Если записываю его в имя нода, то в названии появляется.
$sql = "SELECT reg_id, region, pid, lvl FROM vision.`vision_region` WHERE pid = '$id' ORDER BY region";
Вызов $.ajax автоматически интерпретирует ответ сервера как JSON - и если с этим проблемы, то хотя XmlHttpRequest выполнился успешно, но $.ajax вызывает коллбэк для ошибки и ставит status="parsererror".
как раз такая ситуация.
консоль firebug'a показывает
xhr.status 200
из data.php возвращается
[{ id: 1, title: 'Node 1', isFolder: 1},{ id: 2, title: 'Node 2', isFolder: 1},{ id: 3, title: 'Node 3', isFolder: 0}]
но парсер говорит что некорректные данные с сервера...
в чем может быть затык?
Ошибки не будет, если в ответе и ключи и их значения будут взяты в двойные кавычки.
{"id" : "1", "title": "Node 1", "isFolder": "1"}
Нашлась затыка.
С новой библиотекой jquery 1.4.2 не работает пример.
Работает с 1.3.2
не смотрел, но видимо onAjaxError по другому работает..
При выполнении примера вываливается ошибка $ is not defined в tree.js строка 81 $.ajax({
....
Что у меня не так? Куда копать?
Подключите jquery в тот же файл, куда подключили tree.js
Илья, спасибо большое за сайт и статьи.
Мелкий баг:
На слове "Скачать " ссылка не та.
Как заметили некоторые коллеги, в формировании запроса есть ошибка...
источник:http://api.jquery.com/jQuery.ajax/
После манипуляций с библиотекой jQuery (пример работает с версией 1.3.2), в эксплорере пример заработал, а в опере по прежнему пишет: Ошибка parsererror :Некорректные данные с сервера.
В чем может быть проблема?Разве этот скрипт не кроссбраузерный?
Та же беда что у Надежда_ (не зарегистрирован), не хочет работать с id из базы
Никак не пойму, почему если id генериться автоматически - скрип работает, если id берем из базы, то получаем "Ошибка parsererror: Некорректные данные с сервера"
Ключи взятые в двойные кавычки не помагают
На сколько я понял, дело в типе данных, когда берем id из базы, переменная строковая, а должна быть int, исправляется с помощью settype().
И внесите, пожалуйста, в архив эти изменения:
Для корректной работы с библиотекой jquery 1.4.2, нужно
ключи и их значения взять в двойные кавычки
{"id" : "1", "title": "Node 1", "isFolder": 1}, но значение ключа "isFolder" не нужно
брать в "", а то всегда будут узлы.
Для jquery-1.4.4., у меня заработало так:
как правильно заметил MikhailGirshberg
и в data.php
Отличный скрипт! Автору респект.
Попытался разобраться при использовании его в форме. Что-то не выходит у меня каменный цветок.
Добавляю
данные из инпута по POST не передаются. Видимо вся загвоздка в том, что данные подгружаются динамично и первоначально их нет в форме. Помогите разобраться
сбор данных из формы
Данные то собрались, а как их в POST кинуть?
Пожалуйста, подскажите, как сделать, чтобы по умолчанию при загрузке страницы узел Каталог оказался раскрытым и автоматически подгрузились его потомки
Подскажите где найти простой пример кода на AJAX:
есть таблица групп с подгруппами
в форме 2 селекта, в 1-м выбирается группа, а во 2-й подгружаются подгруппы выбранной группы.
День добрый.
Хелп!!!
Сделал первый вывод дерева из базы.
Какой вариант есть чтобы сделать вывод последующих веток был уже зависим от содержания родительской???
Здравствуйте!!!
Очень интересная статья, пытаюсь сделать, чтобы скрипт заработал на моем виртуальном сервере, но при нажатии на "плюсик" отображается картинка загрузки и всё. Прочитал все комментарии, вносил соответствующие исправления в разных комбинациях.
У меня такой вопрос, думаю что не у меня одного, подскажите пожалуйста:
в файле tree.html есть ссылка на /misc/jquery.js, однако такого файла в архиве с исходниками нет. Может быть в этом проблема? И что должно быть в этом файле?
была та же проблема. с добавлением файла всё наладилось
МОжно ли в узлах (паротив) дерева добавить пару кнопок?
Здравствуйте, а как сделать, чтобы вот только обновил, страницу, а оно само выдвигалось, тоесть что бы не надо было на плюсик жать.!
Отличный пример. Спасибо за интересную статью, жаль только что на элементы дерева надо жмякать, круто было бы, если бы они при наведении выводились.
Здравствуйте, простите за тупой может вопрос, не могу понять как считываеться id для GET запроса. Подскажите пожалуйста как передать ид в php
Сделал так но ошибку выводит.
Добрый день.
Есть база:
id parent title note
1 0 Заголовок1 описание
2 0 Заголовок2 описание
3 1 Заголовок3 описание
4 2 Заголовок1 описание
У корневых элементов parent = 0
Далее идут элементы уже с parent корневых и так далее. Получается древовидная структура.
Как будет выглядеть код php , который мне сформирует сначала корневые
элементы с parent 0 (верхний уровень) и код php, который по ID будет подгружать иp этой базы дочерние элементы ?
Если не трудно дайте плиз листинг
Подскажите пожалуйста как раскрывать элементы дерева по клику на название title, а не на +
Ребята, я новичок, поэтому учусь на подобных сайтах.
Из вышеуказанных скриптов, я скопировал код HTML и создал файл html, а код для CSS скопировал и создал отдельный файл .css, но ничего не работает
Ребята помогите со скриптом. Суть в том, что я хочу написать в поле для поиска какое нибудь слово, которое находится в списке меню. Из обычного списка выходить слово, но когда слово находится внутри ("tree" - дерево - этот скрипт для меню под дерево я взял прямо с данной темы) скрипт не находит это слово.
==
.searchinput {
xbackground-image: url('/css/searchicon.png');
xbackground-position: 8px 6px;
xbackground-repeat: no-repeat;
width: 91%;
font-size: 14px;
padding: 6px 6px 6px 40px;
padding: 6px;
border: 1px solid #ddd;
margin: 0 0 20px 10px;
}
function filterContent(elmnt) {
var x, i, val, show, showh2, showbr;
val = elmnt.value;
x = document.getElementById("leftmenuinnerinner").getElementsByTagName("*");
for (i = 1; i < x.length; i++) {
if (x[i].tagName == "H2") {
if (showh2) {
if (show == false) {
showh2.style.display = "none";
} else {
showh2.style.display = "block";
}
}
show = false;
showh2 = x[i];
}
if (x[i].tagName == "BR") {
if (showbr) {
if (show == false) {
showbr.style.display = "none";
} else {
showbr.style.display = "block";
}
}
showbr = x[i];
}
if (x[i].tagName == "A") {
if (x[i].innerHTML.toUpperCase().indexOf(val.toUpperCase()) == -1) {
x[i].style.display = "none";
} else {
x[i].style.display = "block";
show = true;
}
}
if (showh2) {
if (show == false) {
showh2.style.display = "none";
} else {
showh2.style.display = "block";
}
}
}
}
function tree_toggle(event) {
event = event || window.event
var clickedElem = event.target || event.srcElement
if (!hasClass(clickedElem, 'Expand')) {
return // клик не там
}
// Node, на который кликнули
var node = clickedElem.parentNode
if (hasClass(node, 'ExpandLeaf')) {
return // клик на листе
}
// определить новый класс для узла
var newClass = hasClass(node, 'ExpandOpen') ? 'ExpandClosed' : 'ExpandOpen'
// заменить текущий класс на newClass
// регексп находит отдельно стоящий open|close и меняет на newClass
var re = /(^|\s)(ExpandOpen|ExpandClosed)(\s|$)/
node.className = node.className.replace(re, '$1'+newClass+'$3')
}
function hasClass(elem, className) {
return new RegExp("(^|\\s)"+className+"(\\s|$)").test(elem.className)
}
.Container {
padding: 10px;
margin: 0;
}
.Container li {
list-style-type: none;
}
/* indent for all tree children excepts root */
.Node {
background-image : url(img/i.gif);
background-position : top left;
background-repeat : repeat-y;
margin-left: 18px;
zoom: 1;
}
.IsRoot {
margin-left: 0;
margin-top: -15px;
}
/* left vertical line (grid) for all nodes */
.IsLast {
background-image: url(img/i_half.gif);
background-repeat : no-repeat;
}
.ExpandOpen .Expand {
background-image: url(img/expand_minus.gif);
}
/* closed is higher priority than open */
.ExpandClosed .Expand {
background-image: url(img/expand_plus.gif);
}
/* highest priority */
.ExpandLeaf .Expand {
background-image: url(img/expand_leaf.gif);
}
.Content {
min-height: 18px;
margin-left:18px;
}
* html .Content {
height: 18px;
}
.Expand {
width: 18px;
height: 18px;
float: left;
}
.ExpandOpen .Container {
display: block;
}
.ExpandClosed .Container {
display: none;
}
.ExpandOpen .Expand, .ExpandClosed .Expand {
cursor: pointer;
}
.ExpandLeaf .Expand {
cursor: auto;
}
Thank you for your sharing! Your information is useful to me and many people are looking for them like me! The problem seems simple, but through your pen, it impresses me!
vex 3
I really need the instructions you share. I hope you will provide more information often. bmi calculator
To get a good blog I think you tried a lot. And I think this is a very interesting blog, it attracts me by the content and creative design.
geometry dash
Thanks for the nice blog. It was very useful for me. 먹튀검증사이트
I’m excited to uncover this page. I need to to thank you for ones time for this particularly fantastic read!!
I definitely really liked every part of it and
i also have you saved to fav to look at new information in your site. 개인대출
For the best sexy chat in UK you must to visit Shemales in Nottingham
If you want to find casual sex contacts with hot ladies in United Kingdom you must to visit hampshire sex
Find some fine Brithish wifes ready for free chat contacts with you at uk housewives chat
Find some fine Brithish wifes ready for free chat contacts with you at uk housewives chat
If you are looking for casual contacts with hot girls try sextreffen innsbruck
ficken luzern is great web platform for casual sex contacts with fine ladies in EU
I came to the hill and went trekking. Due to mapquest driving directions, I travel to Everest. This will be a lengthy journey. We have a group of five persons that have a keen interest in hiking and trekking. I hope we can all make it to the end of the voyage on time. We plan to fly the flag of our country from the summit of Everest. It's really hazardous, but I feel we can overcome any obstacle.
Слушайте онлайн-радиостанции на сайте: cadena 100
If you are alone in France you must to visit our web platform and find ladies for casual chat Trans a Nice
I found your essay to be very helpful, and I hope to read more of your work in the future. If you have any spare time, I recently discovered a terrific game called among us , which you are free to join and play with me if you so like.
I found your essay to be very helpful, and I hope to read more of your work in the future. If you have any spare time, I recently discovered a terrific game called among us , which you are free to join and play with me if you so like.
Transen in Neukölln is great web platform created for your sexual pleasure
огромное спасибо
Я думаю, что это будет полезно для моего проекта
Retro Bowl is an interactive arcade game app. It has many unique and amazing features. In this game you can play rugby like it’s 1987. The theme of this game is in retro style. You also have to perform the press duties and handle the fragile egos of players just like in real life. The more you play this game the more interesting you will find it. This is an addictive game, if you play this game once then you will play it again and again. It has a simple and interactive interface due to which anyone can effortlessly play this game. It also consumes very low battery power and storage. So you don’t have to worry about your phone’s battery power while playing. The reviews of this game are quite impressive as compared to other games. enyjoy~!
The hasClass and toggleNode- add-in functions, to indicate the hiding of a tree branch via a CSS class. This will make things easier and easier to adjust. wordle game
You must to try our web platform Sexe de Femme and enjoy chatting with the hot girls in France
A good article, a compelling story requires the author to have a keen sense and eye to have an in-depth look at it. I am very impressed with your article. run 3
Учитывая специфику проекта, над которым сейчас работаю(справочная система), этот плагин оказался просто незаменимым, и я использую 90% его функционала с превеликим удовольствием. И я до сих пор не видел такой же мощной альтернативы. canuckle
I'm glad I found this web site, I couldn't find any knowledge on this matter prior to.Also operate a site and if you are ever interested in doing some visitor writing for me if possible feel free to let me know, i am always look for people to check out my web site. Octordle
wordle game is a straightforward sport based mostly on phrase search. It's a phrase search sport wherein the participant has to seek out the right phrase to fill within the grid. On this sport, you may create as many phrases as you need and you can even make them as troublesome as you need. On this sport, you want a phrase that begins with a sure letter and is so long as a grid. These choices enable you to make the sport extra fascinating.
The primary sport within the well-liked horror collection has been vastly profitable. Five Nights at Freddy's 2 (aka fnaf 2): The New Expertise is a sequel to the unique and guarantees to be much more scary, with new characters, new environments, and an entire new journey! Get your scariest bounce scares prepared for this spooky sequel! This text will stroll you thru every little thing new and thrilling in regards to the sport.
Escort ireland has made great strides in adapting to a wide range of users with its instant messaging and video calling features. Customers have chosen this website over others because of these excellent features. Don't wait any longer if you are looking for your partner in crime.
You can find hot young ladies for casual contacts in France if you vist our web platform Virtuel Escort Grand Est
I wanna know more about this because this is really informative! Waffle game
wordle online is a enjoyable and difficult word puzzle game that gives you, along with the conventional gameplay, a each day problem to check your abilities. For those who like crossword puzzles and word searches, and are a fan of the game Mastermind, you'll love this nice free online game. Do you suppose you may remedy the problem of the day and share it so that everybody can see how sensible you might be?
Have you ever participated in wordle game? This is a game that always brings surprises to you. Every day, you only have 6 turns and you have to find the answer hidden inside the crosswords.
word games- popular game today. It fun game
Looking at this article, I miss the time when I didn't wear a mask. 온라인카지노 Hopefully this corona will end soon. My blog is a blog that mainly posts pictures of daily life before Corona and landscapes at that time. If you want to remember that time again, please visit us.
I think this is one of the most vital information for me. And i’m glad reading your article. tree surgeon barnet
If you are alone you must to check out our web platform with fine ladies ready for casual contacts Transexuelle á Reims
Falling For Christmas 2022 Lindsay Lohan Sequin Blazer is the ideal choice for girls because it can be worn in any season and with any outfit, thanks to its attractive and unique design. Jacket-Hub has the best and most affordable price.
Thank you for sharing this useful article information.I am really impressed with the article you provided.
creperas
Undoubtedly this is an excellent article, I gained a lot of knowledge after reading good luck. The theme of the blog is excellent, there is almost everything to read. thank!
Very great information, indeed. Keep sharing stuff like this in the future as well. Добавить AJAX-подгрузку, используя эти две технологии - очень просто. Вообще, это может послужить основой для того, чтобы создавать любые AJAX-виджеты и сложные системы интерфейсов.
I liked this stuff. I will share it on fm whatsapp
I genuinely value your excellent post Drive Mad . You honestly shared a blog post with everyone that is interesting and educational.
I would like to thank you for the efforts you have put in penning this site. I’m hoping to view the same high-grade content by you later on as well. In truth, your creative writing abilities has motivated me to get my own, personal website now. 바카라게임사이트
To dedicate the game I'm excited about making to everyone, I always hope that fnf mods will be recognized by more people, like your letter did.
I would like to express my gratitude to the author for the creation of the post because I found it to be extremely helpful and I also enjoyed reading it. I've made a note about it on the papa's freezeria , and I'd be grateful if you could take the time to read it and agree with it. I am grateful that you have taken the time to explain your problem.
All free games online to play at geeksgames
If you ever visit lowes retail company, you must share your experience about the store with the management on lowescomsurvey.co & win a $500 gift card for free. Lowes is one of the biggest home improvement store in the unkted states.
Complete guide classic games
There are numerous online games that keep us entertained; in my spare time, I frequently play 1v1.lol unblocked. It's an intriguing survival shooting game.
You can watch such information updated for free on youtube premium apk 2023
Subway breakfast is a great way to start your morning. The entire menu in the breakfast list of the subway is healthy, delicious, and fast to serve. Moreover, the cost of subway breakfast is quite affordable
Subway Breakfast Menu
Lowes Survey is an online platform that serves many questions and ratings to the customers and guests to know about their performance for every month. It will be treated as a report card for your company
Article is very well written. It will help everyone who uses it, including myself. Keep doing what you're doing—I'll definitely read more of your posts age of war
Отправить комментарий
Приветствуются комментарии:Для остальных вопросов и обсуждений есть форум.