[js, ajax, json] Помогите скриптик наваять...

nas1234

допустим есть такой код
 
 

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Быстрый старт</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<script src="//api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU" type="text/javascript"></script>
<script type="text/javascript">

// Дождемся загрузки API и готовности DOM.
ymaps.ready(init);

function init() {

var point1 = {type: 'wayPoint', point: [51.470415,39.0058133]}
var point2 = {type: 'wayPoint', point: [51.654445,39.1028617]}
var point3 = {type: 'wayPoint', point: [51.6824033,39.1240317]}

var ar = [point1,point2,point3]

//дальше тут идет работа с этим массивом

}
</script>
</head>

<body>
<div id="map" style="width: 1000px; height: 800px"></div>
</body>

</html>

в некоторой внешней программе я создам json файлик с этими пойнтами и положу его на сервер, где выполняется этот скрипт.
так будет выглядеть?
13.json
 
 
{
"orderID": 13,
"contents": [
{
"pointID": 1,
"pointType": "wayPoint",
"pointx": 51.470415
"pointy": 39.0058133
},
{
"pointID": 2,
"pointType": "wayPoint",
"pointx": 51.470415
"pointy": 39.0058133
},
{
"pointID": 3,
"pointType": "wayPoint",
"pointx": 51.470415
"pointy": 39.0058133
},
],
"orderCompleted": true
}

как мне в коде обратиться к этому файлику, чтобы получить из него массив ar?
желательно бы чтобы я мог в адресной строке передать номер файла 13. типа site.ru/map.php?pointID=13 и тогда парится файл 13.json

marat7256

Ajax запрос к скрипту, например, на php.
Ща пример найду.

marat7256

 
 $.ajax({
url: 'http://server.com/map.php?pointID=13,
dataType: 'json',
timeout: 20000,
success: function(jsondata) {
data=JSON.parse(jsondata);
...
},
error: function() {

}
});

На php скрипт сам напишешь?

nas1234

На php скрипт сам напишешь?
врядли. я собственно надеялся что просто соберу из кусочков и примеров на яндексе то что мне нужно, но наткнулся на своё незнание ни яваскрипта, ни пхп.

svetaslav212

Да, не видать тебе 400 к и каена. :(

Temach

так обращайся к нужному файлу сразу
 
 $.ajax({
url: 'http://server.com/13.json',
dataType: 'json',
timeout: 20000,
success: function(jsondata) {
data=JSON.parse(jsondata);
... //дальше тут идет работа с этим массивом data
},
error: function() {

}
});

artimon

Поскольку dataType: 'json' уже указан, то JSON.parse не нужен.

marat7256

Поверь, бывают исключения.

artimon

Я верю в исключения, но не понимаю как работает JSON.parse если передать ему объект.

nas1234

мне ведь не надо создавать $? оно же в src где-то уже объявлено, я правильно понимаю?
код выдаёт
error1
error2
test.json лежит где надо, если дать неправильный путь - ругается на 404. браузером файл скачивается.
 
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Быстрый старт. </title>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
     <script src="//api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU" type="text/javascript"></script>
<script src="//code.jquery.com/jquery-1.10.2.js" type="text/javascript"></script>
    <script type="text/javascript">

// Дождёмся загрузки API и готовности DOM.
ymaps.ready(init);

function init() {


 $.ajax({
url: '/test.json',
dataType: 'json',
timeout: 20000,
success: function(jsondata) {
     //дальше тут идет работа с этим массивом data
console.log('success1');
},
error: function() {
console.log('error1');
}
});

$.getJSON( "/test.json", function() {
  console.log( "success2" );
})
   .fail(function() {
    console.log( "error2" );
  })
}
</script>
</head>

<body>
    
</body>

</html>

marat7256

Попробуй указать полный путь (url), типа, http://som.server.com/test.json
Или у тебя апач не поднят и локально пытаешься работать?

nas1234

у меня iis7, сам сервер работает. и js на нём тоже работает, карты яндексовские выводятся нормально.
полный путь выдаёт такой же результат.

artimon

Попробуй посмотреть, какая именно ошибка возникает.
Если в файле ровно то, что ты написал, то там не хватает запятых между pointx и pointy. И лишняя запятая в 21 строчке

nas1234

поправил запятые, вроде пошло.
спасибо большое всем.

bav46

И лишняя запятая в 21 строчке
а точно ли ?
вроде она синтаксисом допустима

Bibi

расскажи это IE

artimon

В JSON нельзя.

nas1234

помгите ещё немножко.
в ИЕ работает через раз. в хроме всё норм.
при открытии страницы - выдаёт ошибку. при f5 - показывает.
http://vvvk.ru/test.html
при удачном открытии должно показывать маршрут.
при неудачном - грузит карту, в консоль вылезает такая ошибка:
SCRIPT5007: Не удалось получить свойство "length" ссылки, значение которой не определено или является NULL
File: combine.xml, Line: 1, Column: 385016
или
test.html, строка 28 символ 2
такое ощущение что не успевает что-то загрузиться из src, в 28 строке вызывается метод яндекс карт, хотя ранее в коде уже было обращение к яндекскартам.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Карта</title>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
    <script src="//api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU" type="text/javascript"></script>
<script src="//code.jquery.com/jquery-1.10.2.js" type="text/javascript"></script>
    <script type="text/javascript">


ymaps.ready(init);
var ar;
$.getJSON( "/test.json", function(data) {
  ar = data.points;
})
   .fail(function() {
    console.log( "error" );
  })

function init() {

var myMap = new ymaps.Map("map", {
     center: [51.674148,39.293907],
     zoom: 8
     });
myMap.behaviors.enable('scrollZoom');

ymaps.route(
ar,
{
     mapStateAutoApply: true
}).then(function (route) {
     myMap.geoObjects.add(route);
     var points = route.getWayPoints(),
     lastPoint = points.getLength() - 1;
     points.options.set('preset', 'twirl#redStretchyIcon');
     points.get(0).properties.set('iconContent', 'Точка отправления');
     points.get(lastPoint).properties.set('iconContent', 'Точка прибытия');
    }, function (error) {
     alert('Возникла ошибка: ' + error.message);
    });
}
</script>
</head>

<body>
    <div id="map" style="width: 1000px; height: 800px"></div>
</body>

</html>

khachin

Переменная ar не успевает получить свойства.
Init срабатывает до подгрузки json.
При обновлении через F5 (без Ctrl) json (т.к. статический файл и не менялся) уже лежит в кэше.

nas1234

как сделать, чтобы инит вызывался после всех приготовлений?

khachin

Делать запрос на JSON внутри Init, прокладывать маршрут после получения JSON.

ymaps.ready(init);

function init() {
var ar;
var myMap = new ymaps.Map("map", {
center: [51.674148,39.293907],
zoom: 8
});
$.getJSON( "/test.json", function(data) {
ar = data.points;

ymaps.route(
ar,
{
mapStateAutoApply: true
}).then(function (route) {
myMap.geoObjects.add(route);
var points = route.getWayPoints(),
lastPoint = points.getLength() - 1;
points.options.set('preset', 'twirl#redStretchyIcon');
points.get(0).properties.set('iconContent', 'Точка отправления');
points.get(lastPoint).properties.set('iconContent', 'Точка прибытия');
}, function (error) {
alert('Возникла ошибка: ' + error.message);
});
})
.fail(function() {
console.log( "error" );
})

myMap.behaviors.enable('scrollZoom');

}

Это на скорую руку.

marat7256

Так?
 
var ar;
$.getJSON( "/test.json", function(data) {
ar = data.points;
ymaps.ready(init);
})
.fail(function() {
console.log( "error" );
})

Kira

а оно точно будет работать, если яндекс карты инициализируются до прихода json?

nas1234

Делать запрос на JSON внутри Init, прокладывать маршрут после получения JSON.
я сначала так и сделал. тогда всегда выдаёт эту ошибку, даже по f5
если внести инит внутрь getjson - остаётся также, при загрузке ошибка, по ф5 - работает. (на одном из компов работает и без ф5, но видимо это просто вопрос быстродействия самого браузера или типа того)

nas1234

не знаю, может что-то просто оставалось в кеше и грузился старый вариант, но этот способ вроде бы помог. спасибо.

khachin

Странно. Воспроизвел у себя.
 
 
Попробуй.

marat7256

Ну, при таком способе init вызывается только при условии получения успешного ajax ответа и заполнения переменной ar.

nas1234

понял. работает.
спасибо большое.

nas1234

наткнулся на проблему с асинхронными запросами. в результате цикл отрабатывает вхолостую, не делая то, чего мне нужно.
здесь я имею на входе массив точек, далее нахожу маршруты от первой точки до каждой из остальных и выбираю кратчайший, записываю в массив и уже от этой точки повторяю действие до оставшихся. типа ищу "оптимальный" маршурт по расстоянию.
получается куча запросов на построение маршрутов к яндексу. как заставить скрипт ждать каждого ответа от сервера?
при отладке строка 57 выдаёт 10 раз "del 0", а потом уже приходят все ответы от сервера.
в инете видел что-то про вызов сторонней функции, но не могу придумать как это тут вкрячить. подскажете?

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Карта</title>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
    <script src="//api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU" type="text/javascript"></script>
<script src="//code.jquery.com/jquery-1.10.2.js" type="text/javascript"></script>
<script src="//yandex.st/jquery/1.6.4/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript">


ymaps.ready(init);

function init()
{
var ar;

var myMap = new ymaps.Map("map",
{
     center: [51.674148,39.293907],
     zoom: 8
     });
myMap.behaviors.enable('scrollZoom');

var res = [];
var temp = [];
$.getJSON( "/test.json", function(data)
{
ar = data.points;
var curPoint = ar[0];
while (ar.length > 0)
{
l = 999999;
var curID = 0;
for (var i = 0; i < ar.length; i++)
{
test = [curPoint,ar[i]];
ymaps.route(
test,
{})
.then(function (route)
{
if (route.getLength()<=l)
{
l=route.getLength();
curPoint = ar[i];
curID = i;
};
}, function (error)
{
alert('Возникла ошибка: ' + error.message);
});

};
res.push(curPoint);
ar.splice(curID,1);
console.log('del ' + curID);
}
//console.log(res);
/* ymaps.route(
res,
{mapStateAutoApply: true})
.then(function (route)
{
myMap.geoObjects.add(route);
myMap.setBounds(myMap.geoObjects.getBounds());
var points = route.getWayPoints(),
lastPoint = points.getLength() - 1;
points.options.set('preset', 'twirl#redStretchyIcon');
points.get(0).properties.set('iconContent', 'Точка отправления');
points.get(lastPoint).properties.set('iconContent', 'Точка прибытия');
}, function (error)
{
alert('Возникла ошибка: ' + error.message);
});
 */
});

}



</script>
</head>

<body>
    <div id="map" style="width: 1000px; height: 800px"></div>
</body>

</html>

marat7256

for (var i = 0; i < ar.length; i++)
Сдается мне, что тут надо начинать от 1, ибо расстояние между точкой и ей самой равно 0.

nas1234

первая точка будущего маршрута - отправная.
можно сэкономить одну итерацию, да.

agaaaa

search: jquery when all

khachin

наткнулся на проблему с асинхронными запросами. в результате цикл отрабатывает вхолостую, не делая то, чего мне нужно.
Да нет тут вроде никакой проблемы. По крайней мере она не в асинхронном запросе. Цикл отрабатывается не в холостую.
Чтобы в этом убедиться, достаточно в js добавить еще логи.

ymaps.ready(init);

function init()
{
var ar;

var myMap = new ymaps.Map("map",
{
center: [51.674148,39.293907],
zoom: 8
});
myMap.behaviors.enable('scrollZoom');

var res = [];
var temp = [];
$.getJSON( "/test.json", function(data)
{
ar = data.points;
console.log('got ' + ar.length + ' points');
var curPoint = ar[0];
while (ar.length > 0)
{
l = 999999;
var curID = 0;
console.log('processing ' + (ar.length - 1) + ' points');
for (var i = 1; i < ar.length; i++)
{
test = [curPoint,ar[i]];
ymaps.route(
test,
{})
.then(function (route)
{
if (route.getLength()<=l)
{
console.log('changing ' + l + ' to ' + route.getLength());
l=route.getLength();
curPoint = ar[i];
curID = i;
}
else
{
console.log('Not changing ' + l + ' to ' + route.getLength());
};
}, function (error)
{
alert('Возникла ошибка: ' + error.message);
});

};
res.push(curPoint);
ar.splice(curID,1);
console.log('del ' + curID);
}
});

}

Строки 25, 36, 40-42.

khachin

В Я-картах то, что находится внутри .then(), выполняется после того, как маршрут построен. Двигаться надо от этого.
Позже приведу код того, что ты хочешь (если это не сделают до меня или сам не успеешь разобраться).
А пока ключевые слова: рекурсивная функция.

nas1234

Чтобы в этом убедиться, достаточно в js добавить еще логи.
я добавлял так. проверял, что ответы приходят уже после того, как выполняется весь цикл while. вот:
про рекурсию я подумаю, спасибо.

marat7256

Попробуй на eventах сделать.
Вот пример: http://www.nczonline.net/blog/2010/03/09/custom-events-in-ja...

khachin

На рекурсии.

ymaps.ready(init);

var promise;

// Автопереносилка. Функция перемещает элемент из одного массива в другой
var moveArrayElement = function(sourceArray, index, destArray)
{
destArray.push(sourceArray[index]);
sourceArray.splice(index, 1);
console.log('del ' + index);
};

// Вместо тысячи слов: http://s.pikabu.ru/post_img/2013/05/08/9/1368018276_177184489.jpeg
var shortPath = function(
pointArray, // Массив исходных точек
destArray, // Целевой массив упорядоченных точек
index, // Индекс точки с кратчайшим расстоянием
offset, // Отступ от подходящего индекса
lenToCompare // Сравниваемая длина
)
{
if (destArray.length == 0) // Если в целевом массиве еще нет точек, заносим первую из исходного
{
moveArrayElement(pointArray, 0, destArray);
shortPath(pointArray, destArray); // Рекурсивный вызов
}
else if (pointArray.length > 1) // Если исходный массив имеет больше одного элемента
{
var i, o;
if (typeof(index) === 'undefined') // Если индекс отсутствует
{
i = 0;
o = 0;
}
else
{
i = index;
o = offset;
};
if (i + o == pointArray.length) // Если индекс в сумме с отступом равен длине массива (перевалил), то следующий индекс найден
{
moveArrayElement(pointArray, i, destArray);
shortPath(pointArray, destArray); // Рекурсивный вызов с обновленными массивами
}
else
{
path = [destArray[destArray.length - 1], pointArray[i + o]];
ymaps.route(path, {})
.then(function (route)
{
console.log('index: ' + i + ', offset: ' + o + ', length: ' + route.getLength());
if (o == 0) // Если отсуп нулевой, то нет длины для сравнения
{
shortPath(pointArray, destArray, i, 1, route.getLength()); // Рекурсивный вызов c указанием сравниваемой длины
}
else if (lenToCompare >= route.getLength()) // Если длина для сравнения больше текущей, переопределяем индекс и продолжаем от него
{
shortPath(pointArray, destArray, i + o, 1, route.getLength());
}
else
{
shortPath(pointArray, destArray, i, o + 1, lenToCompare);
};
}, function (error)
{
alert('Возникла ошибка: ' + error.message);
});
}
}
else if (pointArray.length == 1) // Если в исходном массиве осталась только одна точка, переносим ее.
{
moveArrayElement(pointArray, 0, destArray);
promise.resolve(destArray);
};
};

function init()
{
var ar;
promise = new ymaps.util.Promise();
promise.then(
function(fin){
console.log('final array is: ' + fin.length);
}
);

var myMap = new ymaps.Map("map",
{
center: [51.674148,39.293907],
zoom: 8
});
myMap.behaviors.enable('scrollZoom');

var res = [];
$.getJSON( "/test.json", function(data)
{
ar = data.points;
console.log('got ' + ar.length + ' points');
shortPath(ar, res);
});
}

nas1234

спасибо, отличная рекурсия. я бы долго с этим возился.
но всё же...

 

console.log('got ' + ar.length + ' points');
shortPath(ar, res);
console.log('res ' + res.length + ' points');

сходу добавить туда deferred() объект у меня не получилось.
за советы и помощь спасибо. думаю...

khachin

Обновил последний код (чтобы не городить тут простыни).
Что нового по сравнению с предыдущим:
строки 3, 73, 80-85;
Содержание 83 строки — это то, что будет выполняться после всех манипуляций.
Честно говоря, такая штука, как обещание, провоцирует пересмотреть и упростить код. Но сейчас этим заниматься нет времени.

nas1234

спасибо ещё раз. работает.
Оставить комментарий
Имя или ник:
Комментарий: