jQuery UI ThemeRoller Developer Tool
Еще одна небольшая статья на сегодня... Я тут ради нее даже обновил шкурку wordpress'a и jQueryUI
Сегодня днем, когда качал новую тему для jQueryUI, заметил каку-то рекламку, меня она немного насторожила, я присмотрелся, и не зря мне предложили enlarge your penis size naturally only for 20$. Там было написано "Bring ThemeRoller into any page: Get the ThemeRoller Firefox Bookmarklet!", и что вы себе думаете это работает всего за 20$ я увеличил свой член на 4 сантиметра, но только в FireFox'e. После добавления в закладки и запуска, эта штука создает небольшой поп-апчик, в котором можно менять настройки текущей темы или даже саму тему.
Результат можно посмотреть прямо на этой странице, добавьте этот линк в закладки и запустите, а вот календарик для просмотра эффекта
Но меня как всегда волнует вопрос "как это работает?". Начинаем препарировать:
(function() {
if (!/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {
alert('Sorry, due to security restrictions, this tool only works in Firefox');
return false;
}
;
if (window.jquitr) {
jquitr.addThemeRoller();
} else {
jquitr = {};
jquitr.s = document.createElement('script');
jquitr.s.src = 'http://jqueryui.com/themeroller/developertool/developertool.js.php';
document.getElementsByTagName('head')[0].appendChild(jquitr.s);
}
})();
Сам линк простой как три копейки: если фаерфокс то создает на странице новый скрипт. Какой?
if(!window.jquitr){jquitr = {};}
jquitr.trString = '';
jquitr.s1 =document.createElement('script');
jquitr.s2 =document.createElement('script');
jquitr.s1.setAttribute('src','http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js');
jquitr.s2.setAttribute('src','http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js');
document.getElementsByTagName('head')[0].appendChild(jquitr.s1);
document.getElementsByTagName('head')[0].appendChild(jquitr.s2);
//once jq and ui are loaded...
jquitr.s1.onload = function(){
jquitr.s2.onload = function(){
jquitr.addThemeRoller();
}
}
//add dev tool to page
jquitr.addThemeRoller = function(){
if(jQuery('#inline_themeroller').size() > 0){
jQuery('#inline_themeroller').fadeIn();
}
else {
jQuery('<div id="inline_themeroller" style="display: none; position: fixed; background: #111; top: 25px; right: 25px; padding: 22px 0 15px 4px;width: 245px;height:400px; -webkit-border-radius: 6px; -moz-border-radius: 6px; z-index: 9999999;">'+
'<a href="#" class="closeTR" style="font-family: Verdana, sans-serif; font-size: 10px; display: block; position: absolute; right: 0; top: 2px; text-align: right; background: url(http://jqueryui.com/themeroller/developertool/icon_bookmarklet_close.gif) 0 2px no-repeat; width: 16px;height: 16px; color: #fff; text-decoration: none;" title="Close ThemeRoller"></a>'+
'<iframe name="trApp" src="http://jqueryui.com/themeroller/developertool/appinterface.php" style="background: transparent; overflow: auto; width: 240px;height:100%;border: 0;" frameborder="0" ></iframe>'+
'</div>')
.appendTo('body')
.draggable({
start: function(){
jQuery('<div id="div_cover" />').appendTo('#inline_themeroller').css({width: jQuery(this).width(), height: jQuery(this).height(), position: 'absolute', top: 0, left:0});
},
stop: function(){
jQuery('#div_cover').remove();
},
opacity: 0.6,
cursor: 'move'
})
.resizable({
start: function(){
jQuery(this).find('iframe').hide();
},
stop: function(){
jQuery(this).find('iframe').show();
},
handles: 's'
})
.find('a.closeTR').click(function(){
jquitr.closeThemeRoller();
})
.end()
.find('.ui-resizable-s').css({
background: 'url(http://jqueryui.com/themeroller/developertool/icon_bookmarklet_dragger.gif) 50% 50% no-repeat',
border: 'none',
height: '14px',
dipslay: 'block',
cursor: 'resize-s',
bottom: '-3px'
})
.end()
.css('cursor', 'move')
.fadeIn();
}
jquitr.reloadCSS();
}
//close dev tool
jquitr.closeThemeRoller = function(){
jQuery('#inline_themeroller').fadeOut();
};
//get current url hash
jquitr.getHash = function(){
var currSrc = window.location.hash;
if(currSrc.indexOf('#') > -1){currSrc = currSrc.split('#')[1];}
return currSrc;
};
//recursive reload call
jquitr.reloadCSS = function(){
var currSrc = jquitr.getHash();
if(jquitr.trString != currSrc && currSrc != ''){
jquitr.trString = currSrc;
var cssLink = '<link href="http://jqueryui.com/themeroller/css/parseTheme.css.php?'+ currSrc +'" type="text/css" rel="Stylesheet" />';
//works for both 1.6 final and early rc's
if( jQuery("link[href*=parseTheme.css.php], link[href=ui.theme.css]").size() > 0){
jQuery("link[href*=parseTheme.css.php]:last, link[href=ui.theme.css]:last").eq(0).after(cssLink);
}
else {
jQuery("head").append(cssLink);
}
if( jQuery("link[href*=parseTheme.css.php]").size() > 3){
jQuery("link[href*=parseTheme.css.php]:first").remove();
}
}
setTimeout(jquitr.reloadCSS, 1000);
}
В двух словах он загружает jQuery и jQueryUI (нах они, ведь и так есть, наверное). Большая половина кода загружает iframe с красивенькими табами и еще одной копией jQuery и jQueryUI (фак, их уже три!!!), так же она управляет самим поп-апом (ресайз, драг, анимация). Удивляет то что iframe имеет расширение .php , хотя может это для маскировки.
Теперь вернемся к скрипту, оставшаяся меньшая половина делает магию. Как вы знаете iframe не имеет доступа к странице, то есть напрямую ей управлять не может, он имеет доступ только к window.location.hash, это та часть URL которая называется якорь (anchor). Так вот когда я в iframe выбираю тему или меняю какой-то параметр текущей, он записывает в урл моего сайта нечто вроде
#ffDefault=Segoe+UI%2C+Arial%2C+sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=333333&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=25&borderColorHeader=333333&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=000000&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=25&borderColorContent=666666&fcContent=ffffff&iconColorContent=cccccc&bgColorDefault=555555&bgTextureDefault=02_glass.png&bgImgOpacityDefault=20&borderColorDefault=666666&fcDefault=eeeeee&iconColorDefault=cccccc&bgColorHover=0078a3&bgTextureHover=02_glass.png&bgImgOpacityHover=40&borderColorHover=59b4d4&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=f58400&bgTextureActive=05_inset_soft.png&bgImgOpacityActive=30&borderColorActive=ffaf0f&fcActive=ffffff&iconColorActive=222222&bgColorHighlight=eeeeee&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=80&borderColorHighlight=cccccc&fcHighlight=2e7db2&iconColorHighlight=4b8e0b&bgColorError=ffc73d&bgTextureError=02_glass.png&bgImgOpacityError=40&borderColorError=ffb73d&fcError=111111&iconColorError=a83300&bgColorOverlay=5c5c5c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=01_flat.png&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
Тут уже его мониторит скрипт который по setTimeout каждую секунду проверяет не изменился ли window.location.hash и если да, то передает всю эту строку другому скрипту, который знает как из этой каши сделать новую тему.
Новая тема добавляется в header страницы перекрывая прошлую. Единственное маленькое НО, если вы как я вставляли CSS файлы в средину страницы, непосредственно перед их использованием, то это нихера работать не будет. Надо чтобы старые файлы находились выше по коду чем новые. Именно поэтому мне сегодня пришлось поправить десяток статей и обновить шкурку вордпресса, так что если найдете какие-нибудь баги, не стесняйтесь пишите в каменты.
Непонятным осталось только одно - зачем эта штука хранить 3 последние загруженные темы ?! Что-то я не заметил механизма отката изменений...
Свежие комментарии