9 октября 2011 г.

Перехват кликов на flash элементах при помощи java script


Иногда случается так что у тебя имеется flash баннер с «темной историей», т. е. не известно, кто и когда (зачем/почему?) его создал, но необходимо из него  сделать работающий баннер — чтобы при клике на него происходил переход в нужный раздел сайта.
Вариант как это делать, не обрабатывая сам flash баннер поместить под прозрачный элемент. Этот элемент может быть div элементом или gif картинкой 1 на 1 px.
Поэтому при помощи верстки необходимо разместить html объект по верх баннера,
и при помощи javascript прикрепить необходимые обработчики событий к этому объекту.

Html код:
<div class="flash-container">
<!-- Атрибут wmode="transparent" тега embed обязателен, иначе ничего не получится -->
	<embed  class="banner" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" src="http://www.tetrapolis.ru/flash/a7.swf" salign="top" autoplay="true" loop="true" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" wmode="transparent"></embed>
	<div class="flash-fon" id="click-field">
	</div>
</div>
CSS код:
/* styles for flash banners: */
/* Контейнер для flash и сам flash д.б. одного размера*/
embed.banner, .flash-container{
	width:1200px;
	height:165px;
}
.flash-container{
	/*border: 1px solid black;*/
	position:relative;
}
div.flash-fon{
	position:absolute;
	top:0;
	left:0;
	width:100%;
	height:100%;
	background:transparent;
	cursor:pointer;
}
/* :styles for flash banners */
Javascript код:
Javascript код:   
var setEvent=(function(){
if (window.addEventListener!=null){
	return function(obj,eventName,handler){
		obj.addEventListener(eventName,handler,false);
	}
}else{
	return function(obj,eventName,handler){
		obj.attachEvent("on"+eventName,handler);
	}
}
}());
setEvent(window,"load",function(){
	var clickField=document.getElementById("click-field");
	setEvent(clickField,"click",function(){
		location.href="http://tetrapolis.ru";
	});
});

23 сентября 2011 г.

Haskell. Начало программирования. Матрицы.

Небольшая предыстория о том, как начал программировать на Haskell-е
Среда
После встречи piter.rb#4 (в позапрошлую среду) познакомился через докладчиков с языком Haskell. Язык показался интересным для изучения и непонятным, с точки зрения применения. Т. е. нахрена он нужен.
Четверг
Почитал на wikipedia, на паре других ресурсах... меня терзало
Пятница
Невыдержал. Установил компилятор GHC. Накачал книжек в pdf формате. И покодил (вместо телевизара и прсомотра фильмов с торрентов). Да, я отказался от просмотра последних филтьмов с торрентов и просмотра передач с канала Discavery в пользу программирования на Haskell. На Haskell - как основной язык программирования не подсел - так чисто любительское.
Суббота
Меня осенило. Haskell чудокават, но в полне по силам его освоить. Ребята (Дронов к примеру) не так позиционирует язык. Многие термины используемые в программировании Haskell не являются чем-то не знакомым обычным (особенно после внятной расшифровки) программистам императивщикам.
Сегодня
Неделю спустя, все еще программирую на запале интереса...

Объективные "-" компилятора ghc (так как он единственный для языка то и языка )
  1. Довольно объемный исполняемый файл ~ 1 Mb,
  2. Быстрой работы пока не заметил.
Самокритика объективных "-"
  • А нужна ли эффективность-быстродействие программы?
Для практики написал программу с реализацией на Haskell алгоритма подсчета определителя матрицы, перемножения двух матриц. Функцию транспонирования матриц на Haskell позаимствовал в рунете:

main=do
	print "Matrix detrminant:"
	print (matrixDet [[1,2,3],[7,5,6],[7,8,9]])
	print (matrixDet [[1,2],[4,5]])
	print (matrixDet [[1]])
	print (matrixDet [[]])
	print $ matrixDet [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
	print $ matrixDet [[7,4,6,0],[3,1,2,4],[9,7,2,3],[1,5,8,2]]
	print $ matrixDet [[(-7.9),4.1,6.7,0],[3,1,2,4],[9,7,2.3,3],[1,5,8,2]]
	print "Get row & column:"
	print $ getRow [[1,2,3],[4,5,6],[7,8,9]] 1 
	print $ getColumn [[1,2.9,3.0],[4,5.7,6],[7,8,9]] 1
	print "Multiplication of lists:"
	print $ sum $ map (\(x,y) -> x*y) (zip [1,2,3] [3,0,6])
	print $ sum $ zipWith (*) [1,2,3] [3,0,6]
	print $ sum $ zipWith (*) [1,2,3] [3,0]
	print "Matrix transponation:"
	print $ matrixTransp [[1,2,3],[1,2,3]]
	print $ transp [[1,2,3],[1,2,3]]
	print "matrix mult:"
	print $ matrMult [[1,2,3],[7,9,8]] [[8,7],[5,4],[1,0]]
	print $ matrMult [[1,2,3],[7,9,8]] [[5],[6],[7]]
	print $ matrixDet $ matrMult [[1,2,3],[7,9,8]] [[8,7],[5,4],[1,0]]
 
-- Функция подсчета определителя матрицы
matrixDet [[]] = 0
matrixDet [[x]] = x
matrixDet [[x1, x2], [x3, x4]] = x1*x4 - x2*x3
matrixDet m = let row = head m in
	sum (indexMap (\(x,i)->x*(znakFunc i)*(matrixDet (minor m 0 i))) row)
	where
	znakFunc x = if x`mod`2==0 then 1 else (-1) -- (-1)^(i+j), i=0, j=0.. 
-- перебор списка с индексом, \(x,i) -> ... , but i is Enum
	indexMap _func _list = map _func (zip _list [0..])
-- фильтрация списка с учетом индекса элемента в списке:
	indexFilter _func _array = map (\x -> fst x) (filter _func (zip _array [0..])) 
-- функция определения матрицы минора
	minor :: (Num a, Integral b) =>[[a]] -> b ->b -> [[a]] 
	minor matrix _i _j = map (\row -> indexFilter (\(_,j)->not(j==_j)) row) 
		(indexFilter (\(_,i)-> not(i==_i) ) matrix)
 
-- примитив: функция для извлечения строки
getRow :: (Integral b, Num a) => [[a]] -> b -> [a]
getRow m i = (m!!(fromEnum i))
 
-- примитив: функция для извлечения вектора
getColumn :: (Integral b, Num a) => [[a]] -> b -> [a]
getColumn m j = map (\row -> row!!(fromEnum j) ) m
 
-- 1-й вариант транспонирования матрицы:
matrixTransp :: [[a]] -> [[a]]
matrixTransp m = [[m!!i!!j| i<-[0..((length m)-1)]] |j<-[0..(length(m!!0)-1)]]
-- 2-й вариант транспонирования матрицы. Определение транспонированной матрицы через рекурсию:
-- транспонированная матрица - это такая матрица, первая строка которой равна
-- первому столбцу исходной, а остаток равен траспонированному остатку исходной
transp ([]:_) = []
transp m = map head m: transp (map tail m)
 
-- Функция перемножения двух матриц
matrMult :: (Num m)=> [[m]]->[[m]]->[[m]]
matrMult m1 m2= let _m2 = (transp m2) in 
	map (\r1-> (map (\c2-> sum(zipWith(*) r1 c2)) _m2 )) m1
-- Здесь чтобы во второй матрице не извлекать вектор (строку у добнее) 
-- вторую матрицу просто транспонируем в _m2
 

8 августа 2011 г.

Кросдоменный ajax с помощью javascript


В прошлом посте был описан способ передачи данных на сервер с помощью тега img на странице. Но он не единственный способ.
Для этих целей можно приспособить тег script, котороый так же будет передовать данные на сервер и еще асинхронно передавать ответ обратно.
html код:
Copy Source | Copy HTML
  1. <input type="text" id="textField"/>
  2. <input type="button" id="sendMessage" value="Отправить IMG"/>
  3. <img id="imaGet" src="picture.php?add=hello" style="width:30px;height:30px;"/>
javascript код:
Copy Source | Copy HTML
  1. function ScriptDataSend(urlEncoded_str,callBack_func){
  2.     ////generate uniq id for elements (I don't check it, only random!!)
  3.     var uniqId=(Math.random()*10000000).toFixed( 0);
  4.     //console.log("uniq: %s",uniqId);
  5.     ////add script element and encoded data
  6.     var th = document.getElementsByTagName("body")[ 0];
  7.     var s = document.createElement('script');
  8.     s.setAttribute('type','text/javascript');
  9.     s.setAttribute('src',"script.php?uid="+uniqId+"&add="+urlEncoded_str);
  10.  
  11.     s.setAttribute('id',uniqId);
  12.     ////auto remove script element
  13.     s.onload=function(){
  14.         //console.log("I'm loaded");
  15.         s.parentNode.removeChild(s);
  16.         delete window.responceCollection[uniqId];
  17.     }
  18.     th.appendChild(s);
  19.     delete s;
  20.     //// add callback in globalScope!
  21.     if (window.responceCollection==undefined)
  22.         window.responceCollection={};
  23.     window.responceCollection[uniqId]=callBack_func;
  24. }
  25.  
  26. var messageField=document.getElementById("textField");
  27. var sendButton2=document.getElementById("sendMessage2");
  28. sendButton2.addEventListener("click",function(){
  29.         ScriptDataSend(encodeURIComponent(messageField.value),function(time){
  30.             console.log("Get Javascript response: %s",time);
  31.         });
  32.     },false);
Функция ScriptDataSend создает тег script с заранее определенным url адресом и уникальным id (uid),  чтобы используя этот uid задать уникальный обработчик события для этого соединения в глобальном хэше обработчиков window.responceCollection (другого "красивого" варианта реализации пока не придумал ...).
код файла script.php:
Copy Source | Copy HTML
  1. <?php
  2. header('Content-type: text/javascript');//Делаем вид что javascript
  3. $time=date("H:i:s");
  4. $uid=$_GET["uid"];
  5. // отправляем ответ
  6. echo "window.responceCollection[\"".$uid."\"]('".$time."');";
  7. //- сохраняем полученные данные
  8. $fileName="script_data.txt";
  9. if (strlen($_GET["add"])> 0){
  10.     $fh = fopen($fileName, "a+");
  11.     fwrite($fh, urldecode($_GET["add"])." ".date("H:i:s")."\n");
  12.     fclose($fh);
  13. }
  14. ?>
Как видите, script.php формирует ответ в виде набора данных и передает их в обработчик с уникальным id (uid).
Повозможности никакого управляющего кода на js в php скрипте не генирируется, чтобы было удобнее отлаживать.

Недостатки метода отправки данных сервер с помощью тега script:

  1. только запросы get
  2. вся отладка на плечи кодера
  3. добавление и удаление элемента из DOM
  4. обработчик в глобальной области видимости 

Кросдоменный ajax с помощью тега IMG

С помощью тега img можно отправить данные на сервер. Таким же образом действует и счетчик Яндекс Метрики, когда отправляет данные о кликах посетителей на страницах сайтов.
Создавать фейковую картинку 1px x 1px необязательно, картинка может быть обычной и может служить элементом декора на странице.
И при этом, главное, что, может передавать данные на сервер.
html код:
Copy Source | Copy HTML
  1. <input type="text" id="textField"/>
  2. <input type="button" id="sendMessage" value="Отправить IMG"/>
  3. <img id="imaGet" src="picture.php?add=hello" style="width:30px;height:30px;"/>
javascript код:
Copy Source | Copy HTML
  1. var messageField=document.getElementById("textField");
  2. var sendButton=document.getElementById("sendMessage");
  3. var imageElement=document.getElementById("imaGet");
  4. //Отправка данных на сервер методом get:
  5. sendButton.addEventListener("click",function(){
  6.     //определяем куда в аддресс вставлять сообщение по позиции фрагмента:
  7.     var pos= imageElement.src.indexOf("add=");
  8.     var newLink= imageElement.src.substring( 0,pos)+"add="+encodeURIComponent(messageField.value);
  9.     imageElement.src=newLink;//Присваиваем новый адресс - пофакту отправляем сообщение на сервер
  10. },false);
код файла picture.php:
Copy Source | Copy HTML
  1. <?php
  2. header('Content-type: image/jpeg');
  3. // Можно вывести картинку
  4. $content = implode ( "", file ( 'image.jpg' ) );
  5. echo $content;
  6. // Полученные данные можно отлажить куда-нибудь
  7. $fileName="data.txt";
  8. if (strlen($_GET["add"])> 0){
  9.     $fh = fopen($fileName, "a+");
  10.     fwrite($fh, urldecode($_GET["add"])." ".date("H:i:s")."\n");
  11.     fclose($fh);
  12. }
  13. ?>
Недостатки метода отправки данных сервер с помощью тега img:
  1. только запросы get;
  2. вся отладка на плечи кодера.

31 июля 2011 г.

Html5 Workers

WebWorkers - делают возможным динамическую загрузку JS файлов и запуска их в фоновом потоке.
Пояснительный пример, основная страница:
Copy Source | Copy HTML
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  5. <script>
  6. window.onload = function () {
  7.     var worker = new Worker("message.js");// Creates a Web Worker
  8.     worker.onmessage = function (e) {// Triggered by postMessage in the Web Worker
  9.         document.write('Worker said: ', e.data);// e.data is the values from the Web Worker
  10.     };
  11.     worker.onerror = function (e) {// If the Web Worker throws an error
  12.         document.write(e.data);
  13.     };
  14.     worker.postMessage('World!'); // Send data to our worker.
  15. };
  16. </script>
  17. </head>
  18. <body>
  19. </body>
  20. </html>
Для запуска фонового процесса создается экземпляр объекта Workers с указанным путем до скрипта. Сообщение  между основной запускаемой страницей и фоновым потоком происходит при помощи метода postMessage.
Пример message.js:
Copy Source | Copy HTML
  1. onmessage = function (evt) {
  2.     postMessage("hello "+evt.data+"!");
  3. };
В запускаемом файле есть допуск к объекту контекста this или self, который можно использовать:
Copy Source | Copy HTML
  1. self.addEventListener('message', function(e) {
  2.     var rez="hello "+e.data+"!";
  3.     self.postMessage(rez);
  4. }, false);

Возможности доступные в Workers

Из того что можно запустить в основоном потоке в  Workers доступны,
navigator object
location object (read-only)
XMLHttpRequest
setTimeout()/clearTimeout() and setInterval()/clearInterval()
The Application Cache
Импорт внешних скриптов при помощи вызова метода importScripts()
Запуск других фоновых объектов
Workers не имеет доступа к:
DOM (it's not thread-safe)
window object
document object
parent object

В Workers  есть возможность загрузки внешних скриптов при помощи вызова метода importScripts(). Метод importScripts может принимать несколько параметров с указанием путей до файлов:
importScripts('script1.js', 'script2.js');
Почитать больше можно на - www.html5rocks.com

Ajax Hello world! пример использования

Ajax наиболее кроссбраузерный способ передать данные на сервер и получить ответ обратно без перезагрузки страницы.
Приведу небольшой пример в стиле "Hello world!" по применению этой техники:

Всю рутиную работу с Ajax, обработкой событий можно свести в одну библиотеку которую написать самому или использовать одну из самых ходовых (например с JQuery), чтобы не мучатся с поиском ошибок.
Для демонстрации возможностей приведу примитивные варианты на js и php  без каких либо сторонних библиотек.

Свой велосипед за 5 минут:
Copy Source | Copy HTML
  1. //Небольшая подборка объектов которая может пригодится при использовании AJAX
  2. //На самом деле код немного излишний - необходимости в детектирования IE 5 уже наверное нету 
  3. //Код на скорую руку!
  4. function AjaxObject(){
  5.     var browser=detectBrowser();
  6.     if (typeof XMLHttpRequest=="undefined"){
  7.         //window.XDomainRequest
  8.         XMLHttpRequest=function(){
  9.             return new ActiveXObject(browser.isMsie5? "Microsoft.XMLHTTP":"Msxml2.XMLHTTP");
  10.         };
  11.     }
  12.     this.xhr=new XMLHttpRequest();
  13. }
  14. //property:
  15. //.postOrGet =true if post, false if get
  16. //.onResponce =function(xhr_object)
  17. //.url
  18. //.data - data for send
  19. //.type - dataType: application/x-www-form-urlencoded or text/xml
  20. AjaxObject.prototype.start=function(property){
  21.     var self=this;
  22.     if(self.xhr){
  23.         self.xhr.onreadystatechange = function(){
  24.             if (self.xhr.readyState == 4){
  25.                 property.onResponce(self.xhr);
  26.             }
  27.         };
  28.         self.xhr.open((property.postOrGet ? "POST" : "GET"),property.url,true);//true- asynchrone, false -synchrone
  29.         if (property.type && property.postOrGet){
  30.             self.xhr.setRequestHeader("Content-Type", property.type);
  31.             if(self.xhr.ovverideMimeType)
  32.                 self.xhr.setRequestHeader("Connection","close");
  33.         }
  34.         self.xhr.send((property.postOrGet ? property.data : null));
  35.     }
  36. };
  37. // Events fix
  38. function events(o, event_name, handler){
  39.     if (o.addEventListener != undefined) {
  40.         o.addEventListener(event_name, handler, false);
  41.     }else if (o.attachEvent != undefined) {
  42.         o.attachEvent(event_name, handler);
  43.     }
  44. }
  45. // IE or not IE
  46. function detectBrowser(){
  47. var _ua = navigator.userAgent;
  48. return {
  49.   isMsie: (/msie/i.test(_ua) && !/opera/i.test(_ua)),
  50.   isMsie5: (/msie 5/i.test(_ua) && !/opera/i.test(_ua)),
  51.   isMsie6: (/msie 6/i.test(_ua) && !/opera/i.test(_ua)),
  52.   isMsie7: (/msie 7/i.test(_ua) && !/opera/i.test(_ua)),
  53.   isMsie8: (/msie 8/i.test(_ua) && !/opera/i.test(_ua)),
  54.   isMsie9: (/msie 9/i.test(_ua) && !/opera/i.test(_ua)),
  55. };
  56. }

Пример #1 Необходимо передать что-то на сервер методом GET:


Copy Source | Copy HTML
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <title>Ajax with get method</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  6. <script src="ajaxObject.js"></script>
  7. <script>
  8. window.onload=function(){
  9.     //DOM elements:
  10.     var textField1=document.getElementById("textField1");
  11.     var sendButton1=document.getElementById("sendButton1");
  12.     var p_buf=document.getElementById("buf");
  13.     //Ajax objects & properties:
  14.     var ajObj= new AjaxObject();
  15.     var options={
  16.         postOrGet: false, //use Get method
  17.         onResponce:function(xhr){
  18.             if (xhr.status >= 200 && xhr.status<300){
  19.                 //Ok!
  20.                 if (p_buf.innerText!=undefined)
  21.                     p_buf.innerText=xhr.responseText;
  22.                 else
  23.                     p_buf.textContent=xhr.responseText;//in FF
  24.             }
  25.             else
  26.                 if (p_buf.innerText!=undefined)
  27.                     p_buf.innerText="trouble on recieve!";
  28.                 else
  29.                     p_buf.textContent="trouble on recieve!";//in FF
  30.  
  31.         },
  32.     };
  33.     //Event handlers:
  34.     var clickHandler=function(e){
  35.         options.url="ajax_get.php?name="+encodeURIComponent(textField1.value);
  36.         ajObj.start(options);
  37.     };
  38.     events(sendButton1, "click",clickHandler);
  39. }
  40. </script>
  41. </head>
  42. <body>
  43.     <p>Enter name:</p>
  44.     <input type="text" id="textField1"/>
  45.     <input type="button" id="sendButton1" value="Send name"/>
  46.     <p id="buf"></p>
  47. </body>
  48. </html>
Код ajax_get.php:
Copy Source | Copy HTML
  1. <?php
  2.     if ($_GET["name"]!="")
  3.         echo "hello ",$_GET["name"],"!";
  4.     else
  5.         echo "Please, Enter name and try again! ";
  6. ?>

Пример #2 Необходимо передать что-то на сервер методом POST (urlEncoded data):


Copy Source | Copy HTML
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <title>Ajax with post method</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  6. <script src="ajaxObject.js"></script>
  7. <script>
  8. window.onload=function(){
  9.     //DOM elements:
  10.     var textField1=document.getElementById("textField1");
  11.     var sendButton1=document.getElementById("sendButton1");
  12.     var p_buf=document.getElementById("buf");
  13.     //Ajax objects & properties:
  14.     var ajObj= new AjaxObject();
  15.     var options={
  16.         postOrGet: true, //use Get method
  17.         onResponce:function(xhr){
  18.             if (xhr.status >= 200 && xhr.status<300){
  19.                 //Ok!
  20.                 if (p_buf.innerText!=undefined)
  21.                     p_buf.innerText=xhr.responseText;
  22.                 else
  23.                     p_buf.textContent=xhr.responseText;//in FF
  24.             }
  25.             else
  26.                 if (p_buf.innerText!=undefined)
  27.                     p_buf.innerText="trouble on recieve!";
  28.                 else
  29.                     p_buf.textContent="trouble on recieve!";//in FF
  30.         },
  31.         type:"application/x-www-form-urlencoded",
  32.     };
  33.     //Event handlers:
  34.     var clickHandler=function(e){
  35.         options.url="ajax_post.php";
  36.         options.data="name="+encodeURIComponent(textField1.value);
  37.         ajObj.start(options);
  38.     };
  39.     events(sendButton1, "click",clickHandler);
  40. }
  41. </script>
  42. </head>
  43. <body>
  44.     <p>Enter name:</p>
  45.     <input type="text" id="textField1"/>
  46.     <input type="button" id="sendButton1" value="Send name"/>
  47.     <p id="buf"></p>
  48. </body>
  49. </html>
Код ajax_post.php:
Copy Source | Copy HTML
  1. <?php
  2.     if ($_POST["name"]!="")
  3.         echo "hello ",$_POST["name"],"!";# send data on page
  4.     else
  5.         echo "Please, Enter name and try again! ";
  6. ?>

Пример #3 Необходимо передать что-то на сервер методом POST (xml data):

Copy Source | Copy HTML
  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <title>Ajax with post method and XML</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  6. <script src="ajaxObject.js"></script>
  7. <script>
  8. window.onload=function(){
  9.     //DOM elements:
  10.     var textField1=document.getElementById("textField1");
  11.     var sendButton1=document.getElementById("sendButton1");
  12.     var p_buf=document.getElementById("buf");
  13.     //Ajax objects & properties:
  14.     var ajObj= new AjaxObject();
  15.     var options={
  16.         postOrGet: true, //use Get method
  17.         onResponce:function(xhr){
  18.             if (xhr.status >= 200 && xhr.status<300){
  19.                 //Ok!
  20.                 if (p_buf.innerText!=undefined)
  21.                     p_buf.innerText=xhr.responseText;
  22.                 else
  23.                     p_buf.textContent=xhr.responseText;//in FF
  24.             }
  25.             else
  26.                 if (p_buf.innerText!=undefined)
  27.                     p_buf.innerText="trouble on recieve!";
  28.                 else
  29.                     p_buf.textContent="trouble on recieve!";//in FF
  30.         },
  31.         type:"text/xml",
  32.     };
  33.     //Event handlers:
  34.     var clickHandler=function(e){
  35.         options.url="ajax_xml_post.php";
  36.         //this is xml data for server
  37.         options.data="<data><name>"+encodeURIComponent(textField1.value)+"</name></data>";
  38.         ajObj.start(options);
  39.     };
  40.     events(sendButton1, "click",clickHandler);
  41. }
  42. </script>
  43. </head>
  44. <body>
  45.     <p>Enter name:</p>
  46.     <input type="text" id="textField1"/>
  47.     <input type="button" id="sendButton1" value="Send name"/>
  48.     <p>That ypur have send:</p>
  49.     <textarea id="buf" style="width:400px; height:200px;"></textarea>
  50. </body>
  51. </html>
Код ajax_xml_post.php:
Copy Source | Copy HTML
  1. <?php
  2. # input xml data
  3. $xml=@file_get_contents('php://input');
  4. #send back what have you send
  5. echo $xml;
  6. ?>
Скачать все одним архивом

24 июля 2011 г.

Заметки про класс URI из Ruby stdlib

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

1. Странное результат парсера:
Пример:
require 'uri'


demo_url=["http://www.host.ru","http://www.host.ru/"]
demo_url.each{|url|
_uri=URI.parse(url)
puts "\nhost: '#{_uri.host}', path: '#{_uri.path}' query: '#{_uri.query}'"
puts "path:"
p _uri.path
puts "host:"
p _uri.host
puts "query:"
p _uri.query
} 

В этом примере на входе два url адреса один с указанием пути, другой без, но оба без указания параметров запроса (?var1=pae1&var2=pp && e.t.c.).
можно было бы подумать путь первого url адреса будет равняться nil. Но

host: 'www.host.ru', path: '' query: ''
path:
"" # <= !path.nil? == true, path.emty? ==true
host:
"www.host.ru"
query:  
nil # <= query.nil? == true , Ok!


host: 'www.host.ru', path: '/' query: ''
path:
"/"
host:
"www.host.ru"
query:
nil

В данном случае поведение парсера не логично и не понятно

2. Свойство opaque экземпляра класса URI, темное пятно в вашем url:
С английского термин можно перевести как темный, непрозрачный.
При попытка распарсить ссылку на почту (mailto:login@host) парсер выдавал ошибку opaque or fragment not null.
В документации http://www.ruby-doc.org/stdlib/libdoc/uri/rdoc/ написано:
# File uri/generic.rb, line 568
    def opaque=(v)
      check_opaque(v)
      set_opaque(v)
      v
    end
Ребята делавшие документацию ruby не тот фрагмент привели - check_opaque() ??
Метод opaque - возвращает фрагмент url, который не может быть распарсен!(Ruby cookbook стр 537 )