1 (изменено: mozers, 2008-01-26 19:23:59)

Тема: JS, VBS: Пример создания скриптового плагина для Internet Explorer

Вызов данного скрипта встраивается в контекстное меню Internet Explorer,
что позволяет окрывать в всплывющем окне выделенный участок с произвольной веб-страницы.
Затем этот фрагмент кода можно быстро отредактировать, убрав лишние элементы офрмления, во встроенном в плагин редакторе.
После чего, сохранить полученный html текст в заданном каталоге.

В помощь утомленным создателям панелей Поиска и Ресурсов

Save Snippet for IE
------------------

Наш вариант будет состоять аж из 4-х html файлов:
start.html (именно он вызывается из контекстного меню IE):

<script language="JavaScript">

// Каталог для сохранения отрывков:
var SaveDir = 'C:\\Snippets';

// Извлекаем со страницы выделенный текст (если ничего не выделено, то весь)
var doc = external.menuArguments.document;
var sel=doc.selection.createRange().htmlText || doc.documentElement.innerHTML;
// Получаем URL страницы
var url=doc.URL;
// Получаем заголовок страницы
var docTitle=doc.title || "none";
// используем его для создания имени файла для сохранения
var fileName = SaveDir + '\\' + docTitle.replace (/[^A-Za-zА-ё0-9. ]/g, "-") + '.html';

var textHTML = '<HTML><HEAD><TITLE>';
textHTML += 'Save Snippet for IE v.3.1 beta';
textHTML += '<\/TITLE><script language="JavaScript">';
textHTML += 'var sel=opener.sel;';
textHTML += 'var url=opener.url;';
textHTML += 'var docTitle=opener.docTitle;';
textHTML += 'var fileName = opener.fileName;';
textHTML += '<\/script><\/HEAD>';
textHTML += '<FRAMESET rows="158,30%,*" frameborder=1>';
textHTML += '<FRAME src="_menu.html" name="_menu" noresize scrolling="no" frameborder=0 marginheight=0 marginwidth=0 onLoad="_menu.PageTitle.value=docTitle; _menu.PageURL.value=url; _menu.filename.value=fileName; _menu.arrUndo[0].value=sel;">';
textHTML += '<FRAME src="_form.html" name="_form" scrolling="auto" frameborder=0 onLoad="_form.SaveSnippet.innerHTML=sel;">';
textHTML += '<FRAME src="_source.html" name="_source" scrolling="no" frameborder=1 onLoad="_source.HTMLtext.value=sel;">';
textHTML += '<\/FRAMESET><\/FRAMESET><\/HTML>';
// Открываем новое окно
var wind = window.open("", "", "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes, resizable=yes, top=50, left=50, width=500, height=600");
// и пишем в него заготовленный код
wind.document.write(textHTML);

</script>

Из start.html открыватся 3 фрейма:
_menu.html (содержит код всех управляющих элементов):

<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<style type="text/css">
body, td {font-family:MS Sans Serif; font-size:8px; background-color:threedface; margin:0; overflow:auto;}
input {font-family:MS Sans Serif; font-size:8px;}
b {color:#000099}
</style>
<script language="JavaScript">
var last_tags='';

function SaveFile() {
    var FSO = new ActiveXObject('Scripting.FileSystemObject');
    var fileName = self.filename.value;
    var folderspec = fileName.replace(/[^\\]*?$/,"");
    if (!FSO.FolderExists(folderspec)) {FSO.CreateFolder(folderspec)};
    if (FSO.FileExists(fileName)) {if (!((window.confirm("Файл с заданным именем уже существует!\nПереписать?")))) {return(0)};};
    var File = FSO.CreateTextFile(fileName, 2, false);
    s = parent._source.HTMLtext.value;
    url=self.PageURL.value;
    File.Write ('<!-- Saved from URL: '+url+' -->\r\n'+s);
    alert ('Отрывок успешно сохранен!');
    parent.close();
}

function Undo(){
    var i=self.Index.value;
    var gi=self.gIndex.value;
    if (gi>=0){
        i--;
        if (i<0) {i=self.arrUndo.length-1;}
        parent._form.SaveSnippet.innerHTML=arrUndo[i].value;
        parent._source.HTMLtext.value=arrUndo[i].value;
        self.Index.value=i;
        self.gIndex.value--;
        if (gi==1){self.btnUndo.disabled=true;}
    }
}

function Change(newText){
    var i=self.Index.value;
    var imax=self.arrUndo.length-1;
    i++;
    if (i>imax) {i=0;}
    self.arrUndo[i].value=newText;
    parent._form.SaveSnippet.innerHTML=newText;
    self.btnUndo.disabled=false;
    self.Index.value=i;
    if (self.gIndex.value<imax) {self.gIndex.value++;}
}

function Edit(checked,tags) {
    if (checked){
        var s = parent._source.HTMLtext.value;
        if (tags=='form'){
            s = s.replace (/^[^°]*?(<FORM [^°]*?<\/FORM>)[^°]*$/gi,"$1");
        }
        else if (tags=='table'){
            s = s.replace (/<[/]?TABLE.*?>/gi,'');
            s = s.replace (/<[/]?TBODY.*?>/gi,'');
            s = s.replace (/<[/]?TH.*?>/gi,'');
            s = s.replace (/<[/]?TR.*?>/gi,'');
            s = s.replace (/<[/]?TD.*?>/gi,'');
        }
        else if (tags=='style'){
            s = s.replace (/class=[^ \">]+/gi,'');
            s = s.replace (/style=[\"][^\"]+[\"]/gi,'');
            s = s.replace (/style=\S+? /gi,'');
            s = s.replace (/ bgColor=[^ >]+/gi,'');
        }
        else if (tags=='image'){
            s = s.replace (/<IMG [^>]*( onClick=\".*[^\"])+[^>]*/gi,'<INPUT type=button value="Go!" $1');
            s = s.replace (/<IMG [^>]*>/gi,' ');
        }
        else if (tags=='all'){
            s = s.replace (/(<[/]?SPAN.*?>)|(<[/]?DIV.*?>)/gi,'');
        }
        else if (tags=='action'){
            var tform = s.replace (/^[^°]*?(<FORM [^°]*?>)[^°]*$/gi,"$1");
            var re = /action=["]?(http:\/\/)?([^ ]+)["]?/i;
            re.exec(tform);
            if (!RegExp.$1) {s = s.replace (re,'action="'+self.PageURL.value+'-!-$2"');}
            re = /target/i;
            if (!re.test(tform)) {s=s.replace (/(<FORM [^>]*)>/i,'$1 target=_blank>');}
        }
        parent._source.HTMLtext.value=s;
        Change(s);
        last_tags=tags;
    }else{
        if (last_tags==tags) {Undo()}
    }
}

function fReplace(TextIn, TextOut){
    var s = parent._source.HTMLtext.value;
    var re = new RegExp(TextIn,"gi");
    s = s.replace (re,TextOut);
    parent._source.HTMLtext.value=s;
    Change(s);
}
</script>
</HEAD><BODY bgcolor=threedface><FIELDSET>
        <TABLE border=0 width=100% cellspacing="1" cellpadding="0" STYLE="font-family:'MS Shell Dlg';">
            <TR><TD align=right><B>Page:&nbsp;</B><TD colspan=2 width=100%> <input name=PageTitle style="width=100%">
            <TR><TD align=right><B>URL:&nbsp;</B><TD colspan=2 width=100%> <input name=PageURL style="width=100%">
            <TR><TD align=right><B>Filename:&nbsp;</B><TD width=100%> <input name=filename style="width=100%"><TD> <input type=button value=Save onClick="SaveFile()">
            <TR><TD colspan=3><TABLE border=0 width=100% cellspacing="0" cellpadding="0" STYLE="margin:0;">
                <TR><TD><input type=checkbox onClick="Edit(this.checked,'form')">Только &lt;FORM&gt;-содержимое-&lt;/FORM&gt;
                <TD><input type=checkbox onClick="Edit(this.checked,'image')">Убрать картинки [img]
                <TR><TD style="white-space:nowrap;"><input type=checkbox onClick="Edit(this.checked,'table')">Убрать таблицы [TABLE,TBODY,TH,TR,TD]
                <TD><input type=checkbox onClick="Edit(this.checked,'all')">Убрать другие "лишние" теги [SPAN,DIV]
                <TR><TD><input type=checkbox onClick="Edit(this.checked,'style')">Убрать стили [style,class,bgColor]
                <TD><input type=checkbox onClick="Edit(this.checked,'action')">Откорректировать запрос [FORM action]
            </TABLE>
                <TR><TD colspan=3><TABLE border=0 width=100% cellspacing="0" cellpadding="0" STYLE="margin:0;">
                    <TR><TD>Заменить:&nbsp;<TD width=50%><input type=text name=tFind style="width=100%" title="Используйте регулярные выражения!"><TD>&nbsp;на:&nbsp;<TD width=50%><input type=text name=tReplace style="width=100%" title="Используйте регулярные выражения!"> <TD>&nbsp;<input type=button value=Replace onClick="fReplace(self.tFind.value, self.tReplace.value)" title="По всему тексту
Без учета регистра">&nbsp;
                        <TD>&nbsp;&nbsp;&nbsp;<input type=button value=Undo name=btnUndo onClick="Undo()" DISABLED>
                            <input type=hidden name=gIndex value=0><SELECT style="display:none" NAME="arrUndo"><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option><option></SELECT><input type=hidden name=Index value=0>
                </TABLE>
            </TABLE>
        </TABLE></FIELDSET>
</BODY></HTML>

Во фрейм _form.html попадает код фрагмента с веб-страницы (отображается как есть):

<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<style type="text/css">
body, table {font-family:MS Sans Serif; font-size:8px; margin:0; overflow:auto;}
input, textarea {font-family:MS Sans Serif; font-size:8px;}
a {color:#000080; text-decoration:none;}
a:hover {color:red;}
</style>
</HEAD><BODY><center>
    <TABLE border=0 height=100%><TR><TD valign=center>
    <TABLE bgcolor=#FFFFEE border=0><TR><TD>
        <div id=SaveSnippet><h1>none</h1></div>
    </TABLE>
    </TABLE>
</center></BODY></HTML>

Во фрейм _source.html попадает код фрагмента с веб-страницы (отображается как html код):

<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<style type="text/css">
body {margin:0; overflow:auto;}
textarea {font-size:8pt; font-family:verdana; width:100%; height:100%; overflow:auto;}
</style>
<script language="Javascript">
function Change(newText){
    var i=parent._menu.Index.value;
    var imax=parent._menu.arrUndo.length-1;
    strUndo=parent._menu.arrUndo[i].value;
    if (newText!=strUndo){
        i++;
        if (i>imax) {i=0;}
        parent._menu.arrUndo[i].value=newText;
        parent._form.SaveSnippet.innerHTML=newText;
        parent._menu.btnUndo.disabled=false;
        parent._menu.Index.value=i;
        if (parent._menu.gIndex.value<imax) {parent._menu.gIndex.value++;;}
    }
}
</script>
</HEAD><BODY>
<TEXTAREA NAME="HTMLtext" onMouseOut="Change(this.value)" value="">
</TEXTAREA>
</BODY></HTML>

Еще один вспомогательный файл предназначен для быстрой установки и удаления регистрации плагина в Internet Explorer.
Изменив значения 2х переменных (plug_name, start_page) Вы сможете использовать его и для регистрации своих собственных плагинов.
Setup.vbs:

'  File:         Setup.vbs
'  Description:  Install & UnInstall plugin for IE
'  Author:       mozers™  <http://myie.pp.ru>
' _________________________________________________________

plug_name = "Сохранить отрывок"
start_page = "start.html"

Set WshShell = WScript.CreateObject("WScript.Shell")
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
reg_path = "HKCU\Software\Microsoft\Internet Explorer\MenuExt\" & plug_name & "\"

installHead = "Установка """ & plug_name & """"
installText = "Вы хотите установить """ & plug_name & """?"
installFinish = """" & plug_name & """ успешно установлен!" & vbNewLine & "Вызов - через контекстное меню Internet Explorer."

errorHead = "Ошибка установки"
errorText = "Запустите Setup.vbs из каталога с файлами плагина!"

uninstallHead = "Удаление """ & plug_name & """"
uninstallText = """" & plug_name & """ у Вас уже установлен" & vbNewLine & "Вы хотите его удалить?"
uninstallFinish = "Регистрация """ & plug_name & """ удалена из системы :("

If RegExistKey (reg_path) Then
    If MsgBox(uninstallText, vbOKCancel + vbInformation, uninstallHead) = vbCancel Then WScript.Quit
    ' Удаление пункта из контекстного меню IE
    WSHShell.RegDelete reg_path
    MsgBox uninstallFinish, vbInformation, uninstallHead
Else
    If MsgBox(installText, vbOKCancel + vbInformation, installHead) = vbCancel Then WScript.Quit
    if Not FSO.FileExists(start_page) then MsgBox errorText, vbExclamation, errorHead : WScript.Quit
    ' Добавление пункта в контекстное меню IE
    Set regEx = New RegExp
    regEx.Pattern = "(^.+\\).+"
    start_page = regEx.Replace(WScript.ScriptfullName, "$1") & start_page
    WSHShell.RegWrite reg_path, start_page
    WSHShell.RegWrite reg_path & "Contexts", "59", "REG_DWORD"

    ' Разрешать запуск активного содержимого файлов на моем копьютере (Разрешено)
    WSHShell.RegWrite "HKCU\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\iexplore.exe", "0", "REG_DWORD"
    ' Использование элементов ActiveX, не подписанных как безопасные (Спросить)
    WSHShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\1201", "1", "REG_DWORD"

    MsgBox installFinish, vbInformation, installHead
End If
WScript.Quit

Function RegExistKey (key)
    Dim bExistKey
    bExistKey = False
    On Error Resume Next
    WSHShell.RegRead key
    If Err.Number = 0 Then bExistKey = True
    On Error GoTo 0
    RegExistKey = bExistKey
End Function

Установка:
----------
После того, когда Вы сохраните представленный код под заданными именами, запустите Setup.vbs

Настройка:
----------
Исправьте на Ваш каталог по умолчанию для сохранения отрывков в файле start.html

Удаление:
----------
Запустите Setup.vbs

Замечания:
----------
Beta - это потому, что у меня нет абсолютной уверенности в 100% правильной работе кнопочек
для быстрого редактирования текста. Так что - посматривайте...
Если что - жмите Undo

Код наверняка можно доработать и оптимизировать. Сообщите, pls, если улучшите...

=============================================================

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

<script language="JavaScript">
// открываем новое пустое окно
var wind = window.open("", "", "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes, resizable=yes, top=50, left=50, width=500, height=600");
// создаем в этом окне TEXTAREA
wind.document.write('<TEXTAREA NAME="HTMLtext" style="width=100%; height=100%">');
// загоняем в TEXTAREA выделенный на странице текст
wind.HTMLtext.value=external.menuArguments.document.selection.createRange().htmlText;
</script>