Как да се изгради уеб джаджа (с помощта на JQuery)
Original on http://alexmarandon.com/articles/web_widget_jquery/
Въвеждане
Наскоро създадохме някои уеб джаджи за Design Museum в Лондон и научих някои полезни неща в този процес. Въпреки, че цялата необходима информация може да се намери в интернет, аз не можах да намеря наистина подробен наръчник за правите това с JQuery, така че реших да напиша тази. Аз ще обхваща само техники, които са специфични за уеб джаджи, така че трябва да вече да е запознат с JavaScript, JQuery и уеб разработки, ако искате да следват лесно.
Интересното точки ще бъдат:
- гарантира, код на джаджа не случайно бъркотия с останалата част от страницата,
- динамично натоварване на външни файлове CSS и JavaScript,
- Bypass браузъри “единен произход политика, които използват JSONP.
Не се притеснявайте, ако всичко това не прави смисъл за вас все още, ще видим в детайли какви са тези техники се използват в контекста на изграждане на уеб джаджи.
Какво е уеб джаджа?
Уеб джаджа е компонент, “парче на уеб страница”, които се предоставят за други хора, за показване на данни, идващи от вашия сайт на собствените си страници. А джаджа обикновено съдържа малко по-сложна смес от HTML, CSS и JavaScript. Вие ще искате да скриете, че сложността и то възможно най-лесно за хората да включите вашия джаджа на техните страници.
Widget ползване
Джаджа, разработени в този урок, може да бъде вграден в уеб страница с HTML тагове script един скрипт маркер за зареждане на притурка и една тагове контейнер div обикновено DIV), за да покаже къде искаме да постави джаджа на страницата:
<script src="http://example.com/widget/script.js" type="text/javascript"></script>
<div id="example-widget-container"></div>
Това е наистина всички, че собственик на уеб сайт, ще трябва да включат нашите джаджа върху нея страници. Код препратки с тагове на script ще се погрижи за изтегляне на различните активи, които влизат в състава на джаджа и актуализиране на съдържанието на контейнера.
Не мога да бъде още по-лесно?
Това е технически възможно да се създаде уиджет, който не изисква контейнер дестинация, като използвате document.write() в рамките на кода на джаджата. Въпреки че някои доставчици на джаджа не използват този подход, и тя може да намали код, необходим на хост страница само script скрипт тагове, ние вярваме, че това не си струва, защото:
-
document.write()не може да се нарече веднъж Страницата е заредена. Това означава, че кода на нашите джаджа ще трябва да стартира веднага, когато браузъра се намира маркера на скрипта. Тъй като ние искаме този код, за да донесе на данни от нашия сървър, това може да доведе до зареждане на страницата да бъде прекъснат за известно време и това ще направи страницата се чувстват бавно, - с помощта на отделен етикет, който ще съдържа джаджа на страницата, ние сме свободни да нашето място скрипт навсякъде маркер. Ние, например, може да го поставят в дъното на страницата , която е препоръчителна практика.
Код изолация
Защото не може да предскаже какво JavaScript код ще работи на страница, която използва нашата джаджа, имаме нужда от начин да се гарантира, че тя не се сблъскват с друг код на JavaScript, включени на хост страница. За да направите това, ние просто приложете всички наши код в рамките на анонимна функция и ние наричаме тази функция. Променливите, които ние създаваме в нашите функции няма да се намесва с останалата част на страницата.
Ето един прост пример за използването на тази техника:
var foo = "Hello World!";
document.write("<p>Before our anonymous function foo means '" + foo + '".</p>');
(function() {
// The following code will be enclosed within an anonymous function
var foo = "Goodbye World!";
document.write("<p>Inside our anonymous function foo means '" + foo + '".</p>');
})(); // We call our anonymous function immediately
document.write("<p>After our anonymous function foo means '" + foo + '".</p>');
Можете да видите резултата в вашия браузър. Както можете да видите foo променлива, определени в анонимна функция, не се сблъскват foo глобален Foo променлива.
Винаги декларират променливи с var
За да се избегне досег с JavaScript променливи, определени извън нашите джаджа, ние трябва да декларират всички наши променливи var Var ключова дума, в противен случай бихме могли да се актуализира съществуващите променливи вместо за създаване на нашите собствени. Това е така или иначе е добра практика да се използват var всеки път, когато създавате променлива.
Зареждане на JavaScript библиотеки
Ако вашият джаджа ще използва справедлива стойност на JavaScript, най-вероятно ще искате да използвате JavaScript, като JQuery рамка. Тъй като ние не можем да разчитаме на JQuery, натоварени на хост страница, ние ще се зареди JQuery динамично с помощта на JavaScript:
(function() {
// Localize jQuery variable
var jQuery;
/******** Load jQuery if not present *********/
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2') {
var script_tag = document.createElement('script');
script_tag.setAttribute("type","text/javascript");
script_tag.setAttribute("src",
"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
script_tag.onload = scriptLoadHandler;
script_tag.onreadystatechange = function () { // Same thing but for IE
if (this.readyState == 'complete' || this.readyState == 'loaded') {
scriptLoadHandler();
}
};
// Try to find the head, otherwise default to the documentElement
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
} else {
// The jQuery version on the window is the one we want to use
jQuery = window.jQuery;
main();
}
/******** Called once jQuery has loaded ******/
function scriptLoadHandler() {
// Restore $ and window.jQuery to their previous values and store the
// new jQuery in our local jQuery variable
jQuery = window.jQuery.noConflict(true);
// Call our main function
main();
}
/******** Our main function ********/
function main() {
jQuery(document).ready(function($) {
// We can use jQuery 1.4.2 here
});
}
})(); // We call our anonymous function immediately
Първо ние създаваме една локална променлива, която ще проведе нашата версия на JQuery. След това ние проверяваме за наличието на версия на JQuery, от което се нуждаем, така че ние не го изтеглите отново, ако случайно той вече е там на хост страница. Тук ние сме стриктни за номера на версията, но ако сте изпробвали код с няколко версии, можете да позволят на тези версии, както и, или дори да използвате редовно expresion да съвпадне с основен номер на версията. За да се зареди библиотеката, ние след това трябва script да създадете скрипт елемент, който сочи към URL на библиотеката файл. В случай, че сте се занимават с лошо написани страница, която не разполага с head, ние просто добавяне нашия script маркер към елемент на документа.
Разбира се, ние искаме да използвате библиотеката в нашия код, но преди да правим това, трябва да сме сигурни, че библиотеката се зареди напълно. Ние правим това чрез определяне на scriptLoadHandler функция, която ще се нарича, след като се зареди библиотеката. За повечето браузъри (Firefox, Safari, Opera, Chrome и др.) Ние просто трябва да зададете тази функция на onload атрибут на елемент на script. Internet Explorer, както често, има свой собствен начин. Тук се изисква от нас да се onreadystatechange onreadystatechange манипулатора, който ще призове нашата основна функция, когато на complete loaded завършена или зареден.
Защо тест за двете държави в Internet Explorer, onreadystatechange манипулатор?
След като скриптът е готов за употреба, Internet Explorer ще определят readyState или complete или loaded, в зависимост от това, ако това е заредена от кеша или да се изтеглят от мрежата. Например, ако сте тест само за loaded, основната функция няма да се нарича, ако излезете от страницата, като натиснете върху линка и след това се върна да го използвате бутона “Назад” на вашия браузър.
В нашата scriptLoadHandler функция, ние сме сигурни, че JQuery може да се използва с други библиотеки, а също и с други версии на себе си. Следния ред заслужава специално внимание:
jQuery = window.jQuery.noConflict(true);
Преди тази линия получава изпълнява window.jQuery точки за нашата собствена версия на JQuery, които биха презаписани всяка стара версия на библиотеката. Набиране window.jQuery.noConflict(true) възстановява window.jQuery към старата си стойност и връща референция към прясно заредени нашата версия, която се съхранява в нашите местни променлива. Той също така възстановява $ променлива към старата си стойност, така че ние все още може да използвате друга библиотека като Prototype.
Накрая, scriptLoadHandler призовава нашите main функции, в които можем да използваме нашата версия на JQuery и да изградим нашите джаджа.
Ето два примера на тази техника. В двата примера Prototype е бил натоварен. Единствената разлика между двете е, че тук друга версия на JQuery е бил натоварен , като има предвид, че тук същата версия на JQuery е бил натоварен.
Сега, когато сме разглеждат основните водопровод, най-накрая можем да стигнем до интересната част.
Зареждане на данни от нашия сайт
Тъй като нашата джаджа е за показване на данни на хост страница като HTML, там вероятно няма нужда да се използва междинен формат като XML или JSON, за да получите данни от нашия сървър. Ние можем директно да се HTML и актуализиране на съдържанието на контейнера с джаджа, че HTML.
Да, казват, че нашата джаджа е ще покаже списък от заглавия. Сървърът може да подаде парче на HTML, като например:
<ul>
<li><a href="http://example.com/a-first news">A first news</a></li>
<li><a href="http://example.com/another-news">Another news</a></li>
<li><a href="http://example.com/an-interesting-news">An interesting news</a></li>
</ul>
Ако приемащата страница се намира в същия домейн, бихме могли просто да използват редовно AJAX (или да бъде педантичен в този случай AHAH), за да получите този HTML и DOM актуализира. Но в контекста на милион уеб джаджа, на страница домакин и сървъра, предоставяне от джаджа данни ще обикновено да бъдат в различни области и браузъри просто не ще позволи на един AJAX искане да бъдат направени до една различен домейн от който е обслужен страницата. Това ограничение за сигурност е познат като една и съща политика за произход.
За щастие, има начин да заобиколите този: браузъри позволяват да използвате скрипт тагове, да се включат скриптове от други домейни. Ние можем да използваме тази отворена врата, за да получите данни от нашия сървър, използвайки проста техника, известна като JSONP. Идеята на JSONP е да се създаде script етикет, който ще донесе JSON данни, увити в функция. Ако ние създаваме таг скрипт, като например:
<script type="text/javascript" src="http://example.com/widget/data.js"></script>
Съдържанието на http://example.com/widget/data.js ще изглежда така:
our_callback( {"foo": 42, "bar": 23 } )
След това се дефинира функция, която ще получите JSON данни като параметър:
function our_callback(json_data) {
// do stuff with json_data
}
Сега добрата новина е, че JQuery поддържа JSONP роден и ще се погрижи за нас от създаването на маркера на скрипта, създаване на функция за обратно извикване и приема името на това обратно извикване на сървър като параметър. В този случай само данните, които ние сме заинтересовани в парчето на HTML, искаме да вмъкнете в контейнера на джаджата. От страна на сървъра, ние ще използвате този параметър, за да се изгради парче на JSONP, като например:
# Store HTML in a variable rather than returning in to the browser
html = render_to_string
# Build a JSON object containing our HTML
json = {"html" => html}.to_json
# Get the name of the JSONP callback created by jQuery
callback = params[:callback]
# Wrap the JSON object with a call to the JSONP callback
jsonp = callback + "(" + json + ")"
# Send result to the browser
render :text => jsonp, :content_type => "text/javascript"
Ето един пример за генериране JSONP на сървъра, използвайки Ruby по релси:
(function() {
// Localize jQuery variable
var jQuery;
/******** Load jQuery if not present *********/
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2') {
var script_tag = document.createElement('script');
script_tag.setAttribute("type","text/javascript");
script_tag.setAttribute("src",
"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
script_tag.onload = scriptLoadHandler;
script_tag.onreadystatechange = function () { // Same thing but for IE
if (this.readyState == 'complete' || this.readyState == 'loaded') {
scriptLoadHandler();
}
};
// Try to find the head, otherwise default to the documentElement
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
} else {
// The jQuery version on the window is the one we want to use
jQuery = window.jQuery;
main();
}
/******** Called once jQuery has loaded ******/
function scriptLoadHandler() {
// Restore $ and window.jQuery to their previous values and store the
// new jQuery in our local jQuery variable
jQuery = window.jQuery.noConflict(true);
// Call our main function
main();
}
/******** Our main function ********/
function main() {
jQuery(document).ready(function($) {
/******* Load CSS *******/
var css_link = $("<link>", {
rel: "stylesheet",
type: "text/css",
href: "style.css"
});
css_link.appendTo('head');
/******* Load HTML *******/
var jsonp_url = "http://al.smeuh.org/cgi-bin/webwidget_tutorial.py?callback=?";
$.getJSON(jsonp_url, function(data) {
$('#example-widget-container').html("This data comes from another server: " + data.html);
});
});
}
})(); // We call our anonymous function immediately
В кода на клиента, той ще изглежда като нормално повикване на AJAX връщане JSON.
#!/usr/bin/python
import cgi
params = cgi.FieldStorage()
print "Content-Type: text/javascript\n"
if not 'callback' in params:
print "ERROR: you must pass a callback parameter"
else:
jsonp = "%s ( {'html': '<strong>Hello World!</strong>' } )"
print jsonp % params['callback'].value
Не забравяйте да включите стринг, callback=?? във Вашия URL адрес, в противен случай сървъра няма да получи името на обратното като параметър.
Сега сме в състояние за извличане на HTML от нашия сървър и я поставете в контейнер на джаджа на хост страница. Ние сме почти готови, бихме могли просто искате да добавите малко стил.
Зареждане на CSS
За да заредите нашите стилове, ние просто се създаде връзка маркер, използване на JavaScript:
#!/usr/bin/python
import cgi
params = cgi.FieldStorage()
print "Content-Type: text/javascript\n"
if not 'callback' in params:
print "ERROR: you must pass a callback parameter"
else:
jsonp = "%s ( {'html': '<strong>Hello World!</strong>' } )"
print jsonp % params['callback'].value
Поставянето на нещата заедно
Сега, когато сме виждали различни битове, ние трябва да изградим уеб уиджет, ние може да сложи всичко заедно и да изградят един прост пример. Тук е JavaScript код:
( function () { // Localize jQuery variable var jQuery; /******** Load jQuery if not present *********/ if (window.jQuery === undefined || window.jQuery.fn.jquery!== ' 1.4.2 ' ) { var script_tag = document.createElement( ' script ' ); script_tag.setAttribute( " type ", " text/javascript " ); script_tag.setAttribute( " src ", " http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js " ); script_tag.onload = scriptLoadHandler; script_tag. onreadystatechange = function () { // Same thing but for IE if ( this.readyState == ' complete ' || this.readyState == ' loaded ' ) { scriptLoadHandler(); } }; // Try to find the head, otherwise default to the documentElement (document.getElementsByTagName( " head " )[ 0 ] || document.documentElement).appendChild(script_tag); } else { // The jQuery version on the window is the one we want to use jQuery = window.jQuery; main(); } /******** Called once jQuery has loaded ******/ function scriptLoadHandler () { // Restore $ and window.jQuery to their previous values and store the // new jQuery in our local jQuery variable jQuery = window.jQuery.noConflict( true ); // Call our main function main(); } /******** Our main function ********/ function main () { jQuery(document).ready( function ( $ ) { /******* Load CSS *******/ var css_link = $ ( " <link> ", { rel : " stylesheet ", type : " text/css ", href : " style.css " }); css_link.appendTo( ' head ' ); /******* Load HTML *******/ var jsonp_url = " http://al.smeuh.org/cgi-bin/webwidget_tutorial.py?callback=? " ; $.getJSON(jsonp_url, function (data) { $ ( ' #example-widget-container ' ).html( " This data comes from another server: " + data.html); }); }); } })(); // We call our anonymous function immediately******/( function () { // Localize jQuery variable var jQuery; /******** Load jQuery if not present *********/ if (window.jQuery === undefined || window.jQuery.fn.jquery!== ' 1.4.2 ' ) { var script_tag = document.createElement( ' script ' ); script_tag.setAttribute( " type ", " text/javascript " ); script_tag.setAttribute( " src ", " http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js " ); script_tag.onload = scriptLoadHandler; script_tag. onreadystatechange = function () { // Same thing but for IE if ( this.readyState == ' complete ' || this.readyState == ' loaded ' ) { scriptLoadHandler(); } }; // Try to find the head, otherwise default to the documentElement (document.getElementsByTagName( " head " )[ 0 ] || document.documentElement).appendChild(script_tag); } else { // The jQuery version on the window is the one we want to use jQuery = window.jQuery; main(); } /******** Called once jQuery has loaded ******/ function scriptLoadHandler () { // Restore $ and window.jQuery to their previous values and store the // new jQuery in our local jQuery variable jQuery = window.jQuery.noConflict( true ); // Call our main function main(); } /******** Our main function ********/ function main () { jQuery(document).ready( function ( $ ) { /******* Load CSS *******/ var css_link = $ ( " <link> ", { rel : " stylesheet ", type : " text/css ", href : " style.css " }); css_link.appendTo( ' head ' ); /******* Load HTML *******/ var jsonp_url = " http://al.smeuh.org/cgi-bin/webwidget_tutorial.py?callback=? " ; $.getJSON(jsonp_url, function (data) { $ ( ' #example-widget-container ' ).html( " This data comes from another server: " + data.html); }); }); } })(); // We call our anonymous function immediately
И тук е пример за прилагането на сървъра, като използва един прост скрипт на GCI, написани на Python:
#!/usr/bin/python
import cgi
params = cgi.FieldStorage()
print "Content-Type: text/javascript\n"
if not 'callback' in params:
print "ERROR: you must pass a callback parameter"
else:
jsonp = "%s ( {'html': '<strong>Hello World!</strong>' } )"
print jsonp % params['callback'].value
Разбира се, реалните джаджи свят ще бъде много по-сложно, както на клиента и на сървъра, но се надяваме, че сега имаме по-добро разбиране на основните стъпки.
Надявам се този урок е на интереси. Аз съм нито JavaScript гуру, нито талантлив писател, така се чувстват свободни да напуснат обратна информация за съдържанието и формата. Благодаря на всички за четене и специални благодарности на Кори Харт за ценните му помогне с динамично натоварване на JQuery.
