Полоса прогресса на javaScript

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

function ProgressBar(){
this.value = 0;
this.max = 1;
this.parent = null;
this.main = null;
this.progress = null;
this.info = null;
}

ProgressBar.prototype.Create= function (element,maximum){
this.value =0;
this.max =maximum;
this.parent =element;
this.main =appendElement(element,'div',{'className':'progressbar'});
this.progress =appendElement(this.main,'div',{'className':'progress','innerHTML':' '});
this.info =appendElement(this.main,'div',{'className':'percent'});
this.Progress(0);
}

ProgressBar.prototype.Progress= function (value){
this.value =value;
this.Repaint();
}

ProgressBar.prototype.Repaint=function(){
var percent =this.value/this.max*100;
this.progress.style.width =percent+'%';
this.info.innerHTML =Math.round(percent*10)/10+'%';
}

ProgressBar.prototype.NewMax= function (value){
this.max =value;
this.Repaint();
}

ProgressBar.prototype.Destroy= function (){
this.parent.removeChild(this.main);
}

Особенностью этой полоски является то, что она создаётся в обекте передаваемом в функцию Create.

Всё оформление задаётся через описания к классу полоски, что позволяет не грузить скрипт ненужными параметрами. Для создания полоски используется функция описанная в записи создание HTML элемента в javaScript одной функцией.


Создание HTML элемента в javaScript одной функцией

Иногда требуется создать несколько элементов в javaScript. Можно, конечно описывать все действия, но можно сделать специальную функцию создания, в которую передавать. Где создать элемент, какой у него будет тег и какие дополнительные параметры.

После чего получается, вот такая не хитрая функция:

function appendElement(to,tag,value){
var el=document.createElement(tag);
for (var name in value)
    el[name]=value[name];
to.appendChild(el);
return el;
}

Здесь не реализованы:

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

myminicity

В сети есть сайт myminicity.com, где каждому желающему предлагают построиьт свой город. Суть заключается в том, чтобы заходить по ссылкам в город увеличивая соответсвующий параметр. Всё просто и лаконично, если не считать, что каждый город можно увеличить 1 раз в сутки с 1-го IP адреса.

Можно, конечно, постоянно отключать интернет и подключать его снова, но это время и силы.

Предлагаю вашему внимания функцию загрузки страницы города, определения следующего необходимого параметра и подготовке к следующему вызову.

Collapse )

В скрипте использовано:

  • Функция writelog($text); Записывающая в файл $log текст переданный в неё и выводящий его же в браузер. (Напишете сами?)
  • Класс html - предназначенны для отрезания от текста частей текста с заданного начала или извлечения до указанных символов. (При необходимости поделюсь.)
  • Функция http_req - Запрашивающая переданную ей страницу с приведёнными параметрами запроса. (При необходимости поделюсь.)

Вызов осуществляется с передачей имени города в качесте единственного аргумента: UpdateCity('megatron.ws');

В качестве домашнего задания написания функции переподключения интернета для смены IP адреса.


Георгиевская ленточка =)

Решил добавить в стиль Smooth Sailing георгиевские ленточки, причём принудительно всем.

Для этого потребовалось в блок содержащий картинку профиля в Page::lay_print_sidebar_profile() добавить класс для выделения блока с картинкой пользователя и блок в который запихнём ленточку

        if ($.journal.default_pic.url!="") {
"""<div class="sidebarUserinfo-usericon"><a href="$*SITEROOT/allpics.bml?user=$.journal.username"><img src="$.journal.default_pic.url" alt="" border="0" class="profile-userpic" /></a><span>&nbsp;</span></div>""";
}

Далее добавил в EntryLite::lay_print_userinfo() и Entry::lay_print_userinfo() вывод такого же <span>&nbsp;</span> по два раза, для обоих вариантов отображения.

Теперь, сохранив, переходим к оформлению наших доработок, для этого в css включаем:

/* 9may fix */
.sidebarUserinfo-usericon, entryUserinfo-usericon, commentUserinfo-usericon {
position:relative;
width:100px;
height:100px;
text-align:center;
left:50%;
margin-left:-50px;
}

.sidebarUserinfo-usericon *, entryUserinfo-usericon *, commentUserinfo-usericon * {
position:absolute;
bottom:0px;right:0px;
}

.sidebarUserinfo-usericon span, entryUserinfo-usericon span, commentUserinfo-usericon span {
position:absolute;
width:100px;
height:100px;
background-image:url(http://lugavchik.com/img/9may8.png);
}

.sidebarUserinfo-usericon>span, entryUserinfo-usericon>span, commentUserinfo-usericon>span {
background-image:url(http://lugavchik.com/img/9may.png);
}

Сохранив и это. Мы видим ленточки у пользователей. Позже думаю сделать автоматическое надевание ленточек в период с 1 по 15 мая =) надо только проверку даты сделать и один общий класс =)


html парсер. Часть третья. Разбор текста.

Наверное самая большая часть кода и самая важная тут.

	function Parse($text){

$text=preg_replace($this->ReplaceTagsFrom,$this->ReplaceTagsTo,$text);

@preg_match_all('/([^<]*?)<(/?)([^s]+?)((?:(?:s+(?:[w]+?)=("|')(?:[^5]*?)(?<!\\)5)*?)(?:s*)/?)>/',$text.'<br />',$textdrop);
$tags=array();
if(count($textdrop[0])==0)
return htmlspecialchars($text);
foreach($textdrop[0] as $id=>$line){
$pretext=$textdrop[1][$id];
$closetag=$textdrop[2][$id]=='/';
$curtag=strtolower($textdrop[3][$id]);
$tagparam=$textdrop[4][$id];
if ($closetag){
// TagClose
if ((count($tags)>0)&&($tags[0]==$curtag)){
$newtext.=htmlspecialchars($pretext).'</'.$curtag.'>';
array_shift($tags);
continue;
}else{
$newtext.=htmlspecialchars($pretext).'&lt;/'.$curtag.'&gt;';
continue;
}
}
elseif (!isset($this->allow[$curtag])){
}else{
// TagOpen
preg_match_all('/s([w]+?)=("|')((?:[^2]*?)(?<!\\))2/',$tagparam,$params);
$param='';
foreach($params[0] as $pid=>$line){
if (in_array(strtolower($params[1][$pid]),$this->allow[$curtag]))
if (strtolower($params[1][$pid])=='href'){
// Провека ссылок
preg_match('/(?:(w*?):)(.*)/',$params[3][$pid],$link);
if ((count($link)==0)||(in_array(strtolower($link[1]),$this->AllowProtocols)))
$param.= ' '.$params[1][$pid].'='.$params[2][$pid].$params[3][$pid].$params[2][$pid];
}else
$param.= ' '.$params[1][$pid].'='.$params[2][$pid].$params[3][$pid].$params[2][$pid];


}
if (in_array($curtag,array_keys($this->allow))){
if (!in_array($curtag,$this->simpletag)){
array_unshift($tags,$curtag);
$newtext.=htmlspecialchars($pretext).'<'.$curtag.$param.'>';
}else{
$newtext.=htmlspecialchars($pretext).'<'.$curtag.$param.' />';
}
continue;
}
}

 


$newtext.=htmlspecialchars($pretext).'<'.($closetag?'/':'').$curtag.htmlspecialchars($tagparam).'>';

}
foreach($tags as $tag)
$newtext.='</'.$tag.'>';

return $newtext;
}

Если рассматривать работу данного скрипта по порядку, то:

  1. Сначала производится замена тегов согласно правил замены.
  2. Происходит разбор всего текста с помощью регулярного выражения. Получилось немного громоздкое, но работоспособное.
  3. Проверка количства найденых тегов, и если почему-то ничего не нашлось, то вывод текста, всё равно с экранированием лишнего, вдруг обошли регулярку.
  4. Начинается цикл по всем найденным тегам, вот и началось всё инетересное.
    1. В начале может быть странный текст не относящийся к тегам.
    2. Проверям наличие / в началетега, тем самым определяем что происходит.
    3. Вытаскиваем имя тега и его параметры.
    4. Если тег закрывается, то мы проверям допустимость закрытия его, то есть, что он был открыт последним или просто отображаем его на экране, как текст.
    5. Если тег не закрывался, то надо проверить, может ли он открываться и если может, то
      1. Производим разбор всех параметров у тега в массив.
      2. Проходим по массиву параметров и проверям доступность их применения их у тега.
      3. Если параметр является ссылкой, то ещё дополнительно разбираем её отделяя протокол если передан.
      4. Проверив протокол на правильность мы записываем параметр к тегу.
      5. Если тег может открываться, хмм... Ну ладно два раза не будет лишним проверить.
      6. В зависимости отприменения тега одиночным или нет, мы добавим в стек тегов его или нет и также занесём в код.
    6. Если мы таки не нашли что делать нам с тегом, то выведем его как есть на экран.
  5. Остаётся пробежаться по всем не закрытым тегам и закрыть их.

Вот и готов текст.


html парсер. Часть вторая, инициализация

Продолжив колдовать и создав несколько функций инициализации, мы получаем следующую картину.

function ClearAllow(){
$this->allow=array();
}

function InitAllow(){
$this->SetAllow(array(
'a' => array('href','target','style','class'),
'img' => array('src','border','alt','title','style','class','width','height','align'),
'br' => array('style','clear','class'),
'hr' => array('style','clear','class'),
'span' => array('style','class'),
'div' => array('style','class'),
'p' => array('style','title','class'),
'ul' => array('style','class'),
'li' => array('style','class'),
'ol' => array('style','class'),
'sup' => array('style','class'),
'sub' => array('style','class'),
'b' => array('style','class'),
'i' => array('style','class'),
'u' => array('style','class'),
's' => array('style','class'),
'em' => array('style','class'),
'strong' => array('style','class'),
'center' => array('style','class'),
'form' => array('style','class','action','method','target'),
'h1' => array('style','class'),
'h2' => array('style','class'),
'h3' => array('style','class'),
'h4' => array('style','class'),
'h5' => array('style','class'),
'h6' => array('style','class'),
'input' => array('type','value','name','style','class','readonly','disabled'),
'label' => array('style','class'),
'object' => array('classid','codebase','width','height'),
'param' => array('name','value'),
'embed' => array('type','height','width','wmode','src','flashvars'),
'table' => array('class','style','cellpadding','cellspacing','border','id'),
'tr' => array('class','style','id'),
'th' => array('class','style','id'),
'td' => array('class','style','col'),
'pre' => array('class','style','id'),
));
//
}

 

function AddReplace($from,$to){
$this->ReplaceTagsFrom[] =$from;
$this->ReplaceTagsTo[] =$to;
}

function SetAllow($array){
$this->allow=$array;
}

Рассмотрим функции подробнее:

ClearAllow - Является своего рода функцией инициализации, которая просто очищает список доступных тегов, тоесть воспользовался ей и ни один кусок кода не пройдёт.

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

AddReplace - Необходима, только для правильного заполения массива замен тегов. Один из важных это замена тега <lj user=""> и в будующей тега используемого на маил.ру. 

SetAllow - Применятеся для установки смассива замен созданного в функции инициализации. 

Что может потребоваться в дальнейшем: Функции отключения каких-то замен, на время работы парсера. Также функции добавления и удаления отдельных тегов и параметров тегов.

В третьей части будет рассотрена логика и сам парсер. 


И так какое-то подобие html парсера. Часть первая, подготовка.

Для начала, нам неплохо было бы и подготовить парсер к обработке.

 

if (!class_exists('HtmlParser')){
class HtmlParser{

var $allow;
var $simpletag;
var $AllowProtocols;
var $ReplaceTagsFrom, $ReplaceTagsTo;

function HtmlParser(){
$this->ClearAllow();
$this->simpletag=array('img','br','hr','input','param');
$this->AllowProtocols=array('http','ftp','skype','about','https');
$this->ReplaceTagsFrom=array();
$this->ReplaceTagsTo=array();
$this->AddReplace('/<(/?)b(s[^>]*?)>/i','<$1strong$2>');
$this->AddReplace('//i','<span class="lj_user"><a href="http://www.livejournal.com/userinfo.bml?user=$2" title="$2 profile"><img src="http://stat.livejournal.com/img/userinfo.gif" border="0" alt="[info]" /></a><a href="http://$2.livejournal.com/">$2</a></span>');
$this->InitAllow();
}
}

Это пока только заготовка, в неё нету даже реализации всех функций кроме конструктора. Но в планах:

  • Нормальная обработка одиночных тегов.
  • Обработка закрытых двойных закрытых тегов.
  • Допуск разных протоколов в ссылках.
  • Автозамена некоторых тегов, для отображения на экране.
В следующей части рассмотрим функции инициализации.

Включим, выключим форвардинг для ip

Дя этого я смастерил следующий скриптик:
test-router:~# cat iptables.sh
#!/bin/sh
IPTABLES=/sbin/iptables

if [ $3  ]; then
    $IPTABLES $1 FORWARD -m mac --mac-source $3 -s 0/0 -d $2 -j ACCEPT
    $IPTABLES $1 FORWARD -m mac --mac-source $3 -d 0/0 -s $2 -j ACCEPT
    exit
else
    $IPTABLES $1 FORWARD -s 0/0 -d $2 -j ACCEPT
    $IPTABLES $1 FORWARD -d 0/0 -s $2 -j ACCEPT
fi
Вызов:
iptables.sh -A IP/MASK [MAC]
iptables.sh -D IP/MASK [MAC]

первая, добавляется правило, вторая - удаляет.