Генератор Интерфейса



Генератор Интерфейса

Прямая ссылка на архив:
http://www.maple4.ru/a_downloads_for_maple4_ru/m4gi.zip

Для чего?

Формирование HTML-Интерфейса для программы, написанной на FoxPro.
Зачем?
Без сложных ухищрений FoxPro создает только "стандартный" интерфейс,
который в настоящий момент выглядит несколько аскетично.
Программа может предоставить интерфейс "как-бы" в стиле
web - без установки каких-либо допополнительных сервисов (например IIS
или сервера Апач :) ).

Что дает web-интерфейс?
Естественно (ради этого все и задумывалось), гораздо большие
возможности по графическому оформлению.
Используя Javascript, можно добиться таких спецэффектов, что дух
захватывает - плавающие разделы, напоминания, часы, календари и
т.д. - все зависит от знания этого самого javascript.
Простое размещение видео (+ роликов с youtube), флеш-анимации,
файлов мультимедиа непосредственно на форме - еще один плюс web-интерфейса.

Где еще можно применить данную разработку?
Программа ИДЕАЛЬНО подходит для создания пошаговых игр (и все
это - средствами FoxPro).
Или, например, "электронных" книг с реакцией на действия пользователя
(по сути - получается все та же пошаговая игра :) Помню время, когда
компьютеров не было, были очень распространены книги с сюжетом, зависящим
от случайности и личным предпочтением читателя. Это лирическое
отступление :), но вторым приложением в примере будет "Стань Стальной Крысой!" Г. Гаррисона.
Как бы авторские права не нарушить...).
Или, еще вариант, загрузчиков/инсталляторов с CD/DVD-ROM.

И вот еще...
Применяя javascript ВМЕСТЕ с FoxPro (при обработке может использоваться код FoxPro,
а не только javascript - представьте, какие открываются горизонты), можно создавать
код, срабатывающий по какому-либо событию (например, после нажатия кнопки или
в момент времени) и не требующий переформирования всей страницы.
Данная возможность "выросла" из примера на странице http://forum.foxclub.ru/read.php?29,477476,page=2
(Роме - спасибо).
При том, что данная возможность - самая интересная, используется она до
обидного меньше всего. Одна из причин - я не совсем разобрался с JavaScript.
Подробнее - чуть ниже ("Альтернатива <action>").
Ну и отдельное спасибо piva - за "запрет" возможности перехода на предыдущую
страницу по Backspace или Alt-X, причем БЕЗ применения JavaScript.

Приложенный пример (проект 2x2) всего лишь демонстрирует возможности проекта,
вот только выглядит не очень (нет оформления, файлов графики и т.д.). Причина
банальна - не хватает времени. Даже не нарисовать, не хватает времени просто
найти рисунки в Интернет-е :)
ОЧЕНЬ нужны анимированные gif-картинки золотых, серебряных и медных монет
с прозрачным слоем для использования в любом фоне. Заранее спасибо!

"Защита" с логином/паролем не претендует на что-либо, кроме демонстрации.

Согласен, в дальнейшем по тексту "многа букафф"... что делать. Во первых,
хотелось сразу ответить на предполагаемые вопросы, а во вторых - по
возможности дать некий пример использования.

Особенности программы - весь код в основном размещается в HTML-странице
(т.е. в бланке).
Но программный код, при необходимости (например, для исключения дублирования),
можно вывести в отдельный prg-файл (будет находиться в рабочем каталоге/подкаталоге).
Конечно же, самый "удобный" вариант - включить foxpro-код непосредственно
в исполняемый exe-модуль, но предлагаю делать это в самых крайних
случаях - для обеспечении безопасности или повышения скорости обработки.
На разработку проекта повлияли некоторые знания в ASP.NET и PHP
(будь оно все неладно...)




Создание интерфейса.
Процесс создания разбивается на несколько шагов.
I. Каркас.
Необходимо создать набор html-страниц (далее -> gi-форм), оформленных
в виде небольшого сайта:
меню, кнопки, картинки, ссылки на ресуры в Интернет (например - на видео Ютуба) и т.д.
Названия gi-форм ДОЛЖНЫ начинаться с m4gi_ (признак gi-формы,
без этого gi-форма обрабатываться НЕ БУДЕТ), а в содержимом - должен быть
код <!--m4gi (признак правильной gi-формы, начало комментария html, и
одновременно - процедуры инициализации и настройки) !

II. Наполнение.
1. В теле каждой gi-формы нужно разместить код загрузки и обновления
load (аналог FoxPro : Load ) и init ("аналог" Init или Refresh FoxPro).
2. Нужно создать ссылки (или изменить существующие) для запуска gi-форм
с параметрами (аналог FoxPro - передача параметров в форму) - добавление реакции.
Переданные параметры gi-форма будет обрабатывать в load перед
формированием страницы и в init после формирования.
3. Нужно разместить в gi-формах специальные теги - управляемые элементы.
Их назначение - в нужных местах gi-формы вставить текст: - значения полей,
функций или переменных или код FoxPro, который сформирует нужный текст.


Настройки формы.
ВАЖНО! Даже если в настройках ничего не будет размещаться - ОБЯЗАТЕЛЬНО
добавьте в страницу хотя бы текст <!--m4giproperties -->
Настройки задаются в секции <!--m4giproperties -->

Подпрограммы gi-формы:

<load>
Текст программы foxpro</load>
ПодПрограмма инициализации gi-формы
Срабатывает ПЕРЕД формированием страницы.
Здесь размещается код, необходимый для генерации HTML-страницы - открытие
таблиц, создание глобальных переменных.

<init>
Текст программы foxpro</init>
ПодПрограмма обновления gi-формы
Срабатывает ПОСЛЕ формирования страницы.
В init можно разместить запуск таймеров и кода обновления HTML-элементов
уже сформированной страницы.

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

Пример размещения можно посмотреть в разделе "Пример типичной gi-формы".



1. Каталог запуска программы - это каталог, где запускается exe-модуль.
Обычно в этом каталоге размещаются общие таблицы/файлы для всех приложений
или общие таблицы/файлы для всех пользователей, архивы, распаковываемые
в дальнейшем в рабочий каталог.

2. Каталог интерфейса - место, где находятся html-формы и процедуры интерфейса.
Каталог интерфейса может быть одновременно рабочим каталогом (что такое
рабочий каталог - чуть ниже).

3. Рабочий каталог - это место, где будут формироваться готовые страницы.
Зачем?
Представьте, что Вы создаете интерфейс для программы, которая будет находиться
на CD-ROM.
Куда будут формироваться готовые страницы, если CD-ROM НЕ ПОЗВОЛЯЕТ записывать
на него информацию (только считывание)?????
Рабочий каталог эту проблему снимает:
Во время ПЕРВОГО запуска все файлы из каталога интерфейса переносятся
в рабочий каталог, а уже в рабочем каталоге формируется то, что надо!

В случае, если программа НЕ находится на CD/DVD-ROM (т.е. запускается
прямо с жесткого диска) рабочим каталогом является каталог интерфейса.
В этом случае НЕТ затрат времени на копирование и html-страницы формируются
там же, где находятся gi-формы и процедуры интерфейса.



Объекты post и this_form
В процедурах load и init (а так же во всех <fp></fp>-тегах) при обработке
доступны специальные объекты post и this_form.
1. post
Если gi-форме были переданы параметры - ВСЕ свойства этих параметров
доступны через работу с этим объектом (нужно учитывать, что все
параметры - текстового вида).
2. this_form
с помощью этого объекта Вы можете напрямую обращаться к свойствам
и методам foxpro-формы.
*Например, можно задать заголовок окна:
this_form.caption="Новый заголовок"
*или изменить ширину и высоту окна:
this_form.width=800
this_form.height=600



Управляемые элементы вставляются специальными тегами - <fp></fp>
Два способа вставки:
1. Внутри может размещаться функция, переменная или поле - ОБЯЗАТЕЛЬНО
первым символом должне быть амперсанд - &
Пример:
Текущие дата/время: <fp>&datetime()</fp>

2. Внутри может размещаться код FoxPro. Если результат будет возвращен
оператором Return - текстовое значение результата будет вставлено при
формировании страницы.
Пример:
Текущие дата/время: <fp>local ii
ii=datetime()
return ii</fp>



Нужно "научить" формы реагировать на клики (по кнопкам, ссылкам,
рисункам и т.д.).
Реакция задается специальными тегами <action> </action>, внутри которых
размещается код обработки:
1. внутри ссылки <a href="<action>ЗДЕСЬ"</action>></a>
2. внутри формы <form action="<action>ЗДЕСЬ"</action>></form>

Есть еще один вариант с javascript - но об этом снова чуть ниже.

Типичные примеры использования:

Переход к странице, находящейся в рабочем каталоге
<a href="<action>return '/m4gi_gl_form.html?session=_vbrtdgd&uroven=1'</action>">I уровень</a>
или
<a href="<action>&'/m4gi_gl_form.html?session=_vbrtdgd&uroven=1'</action>">I уровень</a>

Переход к странице, которая находится в подкаталоге 2x2 рабочего каталога программы
<a href="<action>return '/2x2/m4gi_2x2_form.html?session=_vbrtdgd&uroven=1'</action>">I уровень</a>
или
<a href="<action>&'/2x2/m4gi_2x2_form.html?session=_vbrtdgd&uroven=1'</action>">I уровень</a>

Закрытие формы ссылкой
<a href="<action>this_form.close</action>">Закрыть окно</a>

Закрытие формы кнопкой
<form name="main_form" id="main_form_id" method="post" action="<action>this_form.close</action>"
onsubmit="return false;">
<input type="button" value="Закрыть" onclick="submit();">

Открытие gi-формы в новом окне:
<a href="<action>m4gi_newform('\m4gi_magazin.html')</action>">К магазину!</a>

Присвоение глобальным переменным значений
<a href="<action>
_m4gi_type_app='2x2'
_m4gi_type_lg=1
</action>">Присвоить</a>

Задание реакции в форме - с передачей процедуре (которая находится в корне
рабочего каталога программы) текущих параметров
<form name="main_form" id="main_form_id1" method="post"
action="<action>return m4gi_exec('/prg_m4gi_avtoriz.prg',post,this_form)</action>" onsubmit="return false;">
Необходимо авторизоваться (что-бы понять, а кто, собственно, здесь).<br><br>
<br>Введите имя: <input type="text" name="text_name" id="text_id1" value="" />
<br>Введите пароль: <input type="password" name="text_pwd" id="text_id2" value="" />
</form>
<input type="button" value="Войти" onclick="document.forms['main_form'].submit();">

Задание реакции в форме - с передачей процедуре (которая находится в подкаталоге 2x2
рабочего каталога программы) текущих и дополнительных параметров
<form name="main_form" id="main_form_id1" method="post"
action="<action>return m4gi_exec('/2x2/prg_m4gi_2x2_prover.prg',post,this_form,1,2)</action>" onsubmit="return false;">
<INPUT TYPE="text" NAME="proiz" ID="text_proiz" VALUE="" />
<input type="button" value="Ответить" onclick="submit();"></form>

Задание реакции в форме - с открытием другой gi-формы:
<form name="test_form_name" id="test_form_id" method="post"
action="<action>return '/2x2/m4gi_2x2_start.html'</action>" onsubmit="return false;">
<br><b>Name?</b>
<br><input type="text" name="fio" id="text_id" value="" /><br/>
<br><textarea name="textarea_notes" id="textarea_id" cols="20" rows="5" ></textarea><br/>
</form>
<br>
<input type="button" value="Отправить" onclick="document.forms['test_form_name'].submit();">
Далее, при нажатии кнопки Отправить, данные со страницы (значение полей
в fio и textarea_notes) будут переданы заданной в <form action... gi-форме.
Обратите внимание, method="post" !!!
Далее, в gi-форме /2x2/m4gi_2x2_start.html будут доступны параметры
post.fio и post.textarea_notes, которые можно будет использовать
при формировании страницы.



Внутри тегов <action></action> могут размещаться теги <fp></fp>
для формирования нужного кода реакции.
Например, открытие страницы в подкаталоге 2x2 с передачей ей параметров
<a href="<action>return '/2x2/m4gi_2x2_form.html?session=<fp>&LOWER(SYS(2015))</fp>&uroven=3'</action>">Третий уровень</a>


Тег <action></action> может размещаться в теге <fp></fp>
<fp>
return _m4gi_name+":&nbsp;&nbsp;&nbsp;"+m4gi_money(_m4gi_names.money_)+" "+;
iif(vartype(post.pwd)="C",[(запомните Ваш пароль! <font color=red size=+1><b>]+post.pwd+[</font>)],"")+;
iif(_m4gi_names.money_>0,[<br>&nbsp;<a href="<action>m4gi_newform('\m4gi_magazin.html')</action>">К магазину!</a>],"")
</fp>

Если реакция размещается внутри тега <fp></fp> и текст реакции состоит из
многострочного кода, может понадобиться специальная комбинация {{ для вставки
"перехода строки" в коде текста реакции
<fp>return iif(_m4gi_type=0,[<p align=right><i><font size=-1><a href="<action>_m4gi_type=1{{_m4gi_name=''</action>">Перейти к добавлению нового пользователя</a></font></i></p>],;
[<p align=right><i><font size=-2><br><br><a href="<action>_m4gi_type=0{{_m4gi_name=''</action>">Отказаться от добавления нового пользователя</a></font></i></p>])</fp>

А вот если бы реакция НЕ РАЗМЕЩАЛАСЬ в теге <fp></fp>, текст
<a href="<action>{{_m4gi_type=0{{_m4gi_name=''</action>">Отказаться от добавления нового пользователя</a>
мог БЫ быть несколько другим:
<a href="<action>
_m4gi_type=0
_m4gi_name=''
</action>">Отказаться от добавления нового пользователя</a>

Комбинация {{ избавляет от ошибки при выполнении кода в теге <fp></fp> при
МНОГОСТРОЧНОМ коде <action></action>

Дело в том, что при формировании страницы из gi-формы СНАЧАЛА обрабатываются теги
<fp></fp> - т.е. попросту выполняется некий одно- или многострочный FoxPro-код в этих тегах.
А так как код реакции <ation></action> ТАК ЖЕ может содержать многострочный код,
то БЕЗ {{ возникает "конфликт интересов"
ПРИМЕР НЕПРАВИЛЬНОГО написания реакции (в теге <fp></fp>):
<fp>return iif(_m4gi_type=0,[<p align=right><i><font size=-1><a href="<action>_m4gi_type=1{{_m4gi_name=''</action>">Перейти к добавлению нового пользователя</a></font></i></p>],;
[<p align=right><i><font size=-2><br><br><a href="<action>
_m4gi_type=0
_m4gi_name=''
</action>">Отказаться от добавления нового пользователя</a></font></i></p>])</fp>

...который, при попытке выполнить его вернет ошибку (можете проверить у себя в окне FoxPro :) )




Альтернатива <action></action>.
Код <action></action> срабатывает при кликах на ссылках или отправкой данных html-формы.
После чего идет переформирование текущей страницы или открытие новой.

Есть АЛЬТЕРНАТИВНЫЙ способ, который позволит сделать многое прямо с текущей страницей.
Для этого используется специальная конструкция <scriptaction></scriptaction> внутри
которого размещается код обработки.

<a onclick="<scriptaction>
wait window "Добрый день! Сегодня "+dtoc(datetime()) nowait
</scriptaction>" href="javascript:void(0)">Пример вывода в окне Wait приветствия с текущей датой</a>


Еще вариант использования <scriptaction></scriptaction> - в обработке события таймера:
(правда В РАБОЧЕЙ СТРАНИЦЕ Я ЭТОТ КОД ЗАКОММЕНТИРОВАЛ!!!! Объяснение почему - чуть ниже)
<p align=right>Текущие Дата/время: <b id="timestr"><fp>&datetime()</fp></b></p>
<script type="text/javascript">
setInterval(function(){
<scriptaction>
local jj
jj=ttoc(datetime())
this_form.caption="Кто тут? ("+jj+")"
this_form.wb.Document.getElementByID("timestr").innerHtml=jj
</scriptaction>;
}, 755);
</script>
Данный пример срабатывает через каждые 755 мс и одновременно меняет заголовок окна
и значение элемента с id равном timestr на текущей странице.
Обратите внимание - для доступа к caption формы и web-контролу (wb) на ней
используется специальный временный объект this_form (а не Thisform)
Обратите внимание - в html-странице обязательно должен быть объявлен элемент
timestr (это идентификатор позиции, куда будет вставлен результат работы fox-процедуры)
Тоже самое, наверное, можно сделать и на чистом Javascript, но тут стоит простейшая
задача - показать, что FoxPro-код выполняется :)

ВСЕ ОТЛИЧНО в работе данного кода НО... ПРИ БОЛЬШОЙ НАГРУЗКЕ на процессор setInterval
срабатывает ДАЖЕ после перехода на другую страницу. Мало того, это вообще иногда
ведет к ошибке javascript.
К сожалению, пока победить setInterval мне не удалось. А так как конструкция
<scriptaction></scriptaction> применяется при использовании в javascript, необходимо хотя-бы
начальное знание об этом javascript.
К сожалению, это как раз мой случай :( - ну не работал я с javascript вплотную.
Нужен, видимо, совет эксперта по JavaScript и IE, чтобы НАКОНЕЦ-ТАКИ разобраться,
как IE работает с таймером setInterval (если честно, думал, что при открытии новой
страницы предудущие события таймера отменяются. Наверное, это все таки не так...)
Обобщаю: НЕ РЕКОМЕНДУЕТСЯ использовать <scriptaction></scriptaction> с таймерами.
Зато в остальных случаях - пожалуйста.

ОЧЕНЬ бы хотелось бы получить примеры работы с javascript от его знатоков.
Кстати, на странице http://forum.foxclub.ru/read.php?29,477476,page=2 есть пример
запуска javascript-функции из FoxPro и обработка результатов этой функции.



Размещение <scriptaction></scriptaction> в gi-форме.
Нужно понимать, что код <scriptaction></scriptaction> может сработать
ТОЛЬКО ПОСЛЕ ЗАГРУЗКИ ВСЕЙ СТРАНИЦЫ.
Код javascript, приведенный ниже, создает объект htmlapp (), посредством которого
в дальнейшем (после совершения какого-либо события) обрабатывается код FoxPro :
<script type="text/javascript">
var htmlapp = null;
</script>

А вот нижеследующий код вызовет ОШИБКУ:
<script language="JavaScript">
document.write(<scriptaction>dtoc(date())</scriptaction>)
</script>
Ведь здесь на момент выполнения document.write html-страница ЕЩЕ НЕ ЗАГРУЖЕНА!!!



Таймер на FoxPro - гораздо более стабильный таймер.
Обычно создается в init gi-формы.
Например, следующий код делает то-же самое, что и процедура с setInterval (выше),
а именно - через определенный интервал меняет заголовок формы и время на странице:

THIS_FORM.AddObject("_timer1","cmoitimer")
local stro
TEXT TO stro TEXTMERGE NOSHOW
if left(this_form.caption,3)=="Кто" && исключение срабатывания на другой форме
local jj,zz
jj=ttoc(datetime())
this_form.caption="Кто тут? ("+jj+")"
zz=This_form.wb.Document.getElementByID("timestr")
if not isnull(zz)
zz.innerHtml=jj
endif
endif
ENDTEXT
this_form._timer1.post=post
this_form._timer1.this_form=this_form
this_form._timer1.textproc=stro
this_form._timer1.interval=100

Данный код - ГОРАЗДО более стабилен в работе.
Единственный минус - в следующей открываемой форме необходимо в load (именно в load,
а не init) работающий таймер надо удалить (c другой стороны - раз созданный таймер
будет работать все время, что иногда может быть и плюсом :) ).
Например, уже после авторизации, в load gi-форме /m4gi_list.html есть код :
this_form.RemoveObject("_timer1")
который удаляет добавленный ранее таймер.



Во внешних процедурах (prg-файлах) ОБЯЗАТЕЛЬНО наличие строки с МИНИМУМОМ
двумя параметрами:
LPARAMETERS post,this_form

Например, в /2x2/prg_m4gi_2x2_prover.prg, кроме основных параметров, есть
так же параметры ur и shag, требующиеся для работы именно этой процедуры:

LPARAMETERS post,this_form,ur,shag
IF VAL(post.proiz)=0
RETURN .T.
ENDIF
SELECT _m4gi_table_2x2
GO shag
REPLACE otvet WITH .T.,proizv WITH VAL(post.proiz),pravilno WITH IIF(mnoj1*mnoj2=VAL(post.proiz),.T.,.F.),time_ with DATETIME()
IF RECCOUNT()=shag && пройден
m4gi_newform("2x2\m4gi_2x2_rezultat.html?urrez="+ALLTRIM(STR(ur))+"&shagrez="+ALLTRIM(STR(shag)))
ENDIF
RETURN .T.



Страница HTML НЕ ДОЛЖНА реагировать на вторую (неосновную) кнопку мыши, так как
все действия с формой ведутся ТОЛЬКО с помощью основной кнопки.
В BODY html-страницы необходимо внести код oncontextmenu="return false", например:
<BODY oncontextmenu="return false">
Если этого не сделать - у пользователя "возникнут" вопросы :-) (контекстное
меню не контролируется)



Результат реакции <action></action> может быть различных типов:
1. При C(символьное) - подразумевается, что это адрес gi-формы или
html-страницы - открытие "результата", т.е. gi-формы или страницы html в том же окне.
По сути - переход к нужной форме.
2. При L(логическое) - .T. - переформирование и обновление текущей страницы
(по умолчанию, .t. возвращается, если нет в коде нет оператора Return со значением)
Обновление gi-формы требуется после выполнения каких-либо действий, например,
после окончания редактирования элемента.
3. При L(логическое) - .F. - ничего не переформировывается.



Встроенные функции для работы каталогами и файлами в рабочем каталоге

m4gi_file(file) - возвращает .t. при существовании файла.

m4gi_file_path(file) - возвращает полный путь файла из краткого (это требуется,
например, для создания временных таблиц).
m4gi_file_path("\2x2\metka.gif")


m4gi_folder(folder) - возвращает .t. при существовании каталога.
m4gi_folder(folder,type)- при type=.t. - возвращает .t., если каталог существует
или каталог был успешно создан и существует.
функция создает ТОЛЬКО каталоги, относительные к рабочему

m4gi_folder("\3x3",.t.)
будет .t. и будет создан подкаталог 3x3 в рабочем каталоге

m4gi_folder("\pr\tk\sd",.t.) -> создается (если его нет) каталог в рабочем каталоге
Функция m4gi_folder - удобный способ для быстрого создания дерева каталогов со всеми ветками.



Встроенные функции для работы c каталогами и файлами в каталоге запуска.
Данные функции работают ИМЕННО с каталогом ЗАПУСКА.
Сделано это для того, что-бы, например, разные пользователи с расшаренного
ресурса обращались к одной и той же таблице.
Или, например, различные приложения работали с теми же таблицами или файлами.

m4gi_file_default(file) - возвращает .t. при существовании файла.

m4gi_file_path_default(file) - возвращает полный путь файла из краткого.
Например, при каталоге запуска c:\m4gi результатом работы функции
m4gi_file_path_default("\2x2\metka.gif")
будет
c:\m4gi\2x2\metka.gif


m4gi_folder_default(folder) - возвращает .t. при существовании каталога.
m4gi_folder_default(folder,type)- при type=.t. - возвращает .t., если каталог
существует или каталог был успешно создан и существует.
функция создает ТОЛЬКО каталоги, относительные к главному
например, при каталоге запуска c:\m4gi результатом работы функции
m4gi_folder_default("\3x3",.t.)
будет .t. и будет создан каталог
c:\m4gi\3x3

m4gi_folder_default("\pr\tk\sd",.t.) -> создается (если его нет) каталог c:\m4gi\pr\tk\sd
Функция m4gi_folder - удобный способ для быстрого создания дерева каталогов,
вне зависимости, существуют или нет ветки каталогов.



Прочие функции

m4gi_newform(m4gi_form) - открытие модальной gi-формы в НОВОМ окне (т.е.
старое не закрывается).
например, открытие формы в новом окне с передачей ей параметра:
m4gi_newform("\m4gi_error.html?texterror=Неправильно введен пароль, либо
пользователь <font color%3Dred>"+ALLTRIM(post.text_name)+"</font> не найден!")


m4gi_money(money) - возращает результат в виде html-кода в стиле WarCraft-е,
т.е. в виде количества золотых, серебрянных и медных монет.
m4gi_money(money,img) - задается другой рисунок для отображения результата.
если img - пустой, по умолчанию будет 3 рисунка
1_money.gif
2_money.gif
3_money.gif
с путями к рабочему каталогу

При задании, например, m4gi_money(10395,"graf.jpg") функция вернет html-код с рисунками:
1_graf.jpg
2_graf.jpg
3_graf.jpg
с путями к рабочему каталогу

m4gi_money(money,img,gr1,gr2,gr3)
gr1,gr2,gr3 - задает название для рисунков (этот текст будет появляться при наведении мышкой).
Если gr1,gr2,gr3 пустые - по умолчанию gr1="золото",gr2="серебро",gr3="медь"

m4gi_exec(path_file,post,this_form,par1,par2,par3,par4,par5) - запуск процедуры с параметрами.
Применяется, для запуска процедур, находящихся в рабочем каталоге, например,
m4gi_exec('/2x2/prg_m4gi_2x2_prover.prg',post,this_form,1,2)
запустит процедуру prg_m4gi_2x2_prover.prg в подкаталоге 2x2 рабочего каталога и
передаст ее параметры post, this_form, 1, 2

m4gi_exec('/prg_m4gi_avtoriz.prg',post,this_form)
запуск процедуры, находящейся в корне рабочего каталога

m4gi_iconnected() - при .t. - доступ к Интернет существует.
Функцию удобно использовать при формировании gi-формы в зависимости от наличия
Интернет - формируется тот или иной код страницы.

m4gi_unzip("file.zip") - распаковать file.zip (БЕЗ УКАЗАНИЯ ПОЛНОГО ПУТИ!) в папку Рабочего каталога

m4gi_unzip_file_to_folder("file.zip","c:\m4gi\") - распаковать file.zip
(С ПОЛНЫМ УКАЗАНИЕМ ПУТИ!) в папку c:\m4gi\

m4gi_set_inner(this_form,element,value) - функция замены значения элемента
(element) HTML новым значением (value)
В случае невозможности замены (нет такого элемента) возвращает Null
m4gi_set_inner(this_form,"timestr",ttoc(datetime()))

m4gi_get_inner(this_form,element) - получение значения элемента (element) HTML
В случае невозможности получения значения (нет такого элемента) возвращает Null
wait window m4gi_get_inner(this_form,"timestr") nowait



ВАЖНО!!!! Краткая сводка:
I. Имя gi-формы должно начинаться с m4gi_ - иначе страница просто не будет
обрабатываться.

II.
<!--m4giproperties -->
Даже если ничего не собираетесь обрабатывать при загрузке - данная конструкция
все равно ДОЛЖНА НАХОДИТЬСЯ в HTML-файле! Иначе - страница не будет обрабатываться.

III.
<script type="text/javascript">
var htmlapp = null;
</script>
Конструкция объявляет переменную htmlapp, к которой в дальнейшем может быть
обращение (например, для замены значения HTML-элемента средствами FoxPro).
Данная конструкция ДОЛЖНА НАХОДИТЬСЯ в HTML-файле в любом случае!

IV.
<body oncontextmenu="return false">
Данная кострукция запрещает вызов контекстного меню (что изначально отсекает
массу проблем).
Если хотите получить неудобные вопросы со стороны пользователя - можете ее не использовать :)

V. Если в gi-форме применяется <form></form> , ОБЯЗАТЕЛЬНО должен быть
method="post" - иначе, данные не будут передаваться.

VI. Если в теле <fp></fp> находится многострочный текст <action></action> или
<scriptaction></scriptaction> - ОБЯЗАТЕЛЬНО в теле <action> или <scriptaction>
замените перевод строки на комбинацию {{
Иначе - в процессе обработки кода <fp></fp> получите ошибку.
Пример правильного применения:
<fp>return iif(_m4gi_type=0,[<p align=right><i><font size=-1><a href="<action>_m4gi_type=1{{_m4gi_name=''</action>">Перейти к добавлению нового пользователя</a></font></i></p>],;
[<p align=right><i><font size=-2><br><br><a href="<action>_m4gi_type=0{{_m4gi_name=''</action>">Отказаться от добавления нового пользователя</a></font></i></p>])</fp>


VII. ВСЕГДА рекомендуется записывать обращение по путям, начиная с / или \,
т.е. с начального каталога.
Для чего - сберечь себе нервы.
Примеры:
m4gi_exec('/2x2/prg_m4gi_2x2_prover.prg',post,this_form,1,2)
m4gi_file_path('\2x2\metka.gif')
<a href="<action>m4gi_newform('\m4gi_magazin.html')</action>">К магазину!</a>

VIII. Старайтесь оставлять двойные кавычки "" для html, ограничивая ими href(ссылка),
action(html-форма) или код javascript. При написании кода используйте '' или [].
Для чего - сберечь себе нервы (хотя, признаюсь, сам это правило иногда не соблюдаю).
Примеры:
<form name="main_form" id="main_form_id1" method="post"
action="<action>return m4gi_exec('/prg_m4gi_avtoriz.prg',post,this_form)</action>" onsubmit="return false;">
<a href="<action>m4gi_newform('\m4gi_magazin.html')</action>">К магазину!</a>
<a onclick="<scriptaction>wait window 'Добрый день! Сегодня '+dtoc(datetime()) nowait</scriptaction>"
href="javascript:void(0)">Пример вывода в окне Wait приветствия с текущей датой</a>

IX. РЕКОМЕНДУЕТСЯ закрывать (если, конечно, есть такая необходимость) текущую форму
ТОЛЬКО коммандой this_form.close



ПРИМЕР ТИПИЧНОЙ gi-формы - \m4gi_start.html - авторизация на <form></form>
с таймером отображения текущего времени (реализован на FoxPro):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=windows-1251">
<title>Страница Интерфейса</title>
<META HTTP-EQUIV="Keywords" CONTENT="Генератор Интерфейса">
<META name="Author" content="Igor Croschin">
<META name=keywords content="">
<META name=description content="">

<script type="text/javascript">
var htmlapp = null;
</script>

<!--m4giproperties <load>

this_form.caption="Кто тут?"
IF VARTYPE(_m4gi_name)<>"C"
PUBLIC _m4gi_name
_m4gi_name="" && ""-никто не выбран, иначе - будет проставлено в поле имени
ENDIF

IF VARTYPE(_m4gi_type)<>"N"
PUBLIC _m4gi_type
_m4gi_type=0 && 0-предполагается авторизация; 1-предполагается добавление
ENDIF

if not used("_m4gi_korzina")
select 0
create cursor _m4gi_korzina (id_ n(15),name_ c(50),id_predmet n(15))
endif

if not used("_m4gi_magazin")
local ims
ims = m4gi_file_path_default("\_m4gi_magazin.dbf")
if m4gi_file(ims)
select 0
use (ims)
else
select 0
create table (ims) (id_predmet n(15),kratkoe c(200), polnoe m, cena n(15), img_ c(200))
use (ims)
endif

endif

if not used("_m4gi_trofei")
ims = m4gi_file_path_default("\_m4gi_trofei.dbf")
if m4gi_file(ims)
select 0
use (ims)
else
select 0
create table (ims) (id_ n(15),id_predmet n(15),date_ t)
use (ims)
endif

endif

select * from _m4gi_magazin into cursor _m4gi_magazin_temp order by cena

IF USED("_m4gi_names")
SELECT _m4gi_names
USE
ENDIF

IF m4gi_file_default("_m4gi_names.dbf")
SELECT 0
USE (m4gi_file_path_default("_m4gi_names.dbf"))
ELSE
SELECT 0
CREATE TABLE m4gi_file_path_default("_m4gi_names.dbf") (id_ N(15), name_ c(50), pwd_ c(20), money_ n(15))
ENDIF

</load>

<init>

THIS_FORM.AddObject("_timer1","cmoitimer")
local stro
TEXT TO stro TEXTMERGE NOSHOW
if left(this_form.caption,3)=="Кто" && срабатывание только на этой форме
local jj,zz
jj=ttoc(datetime())
this_form.caption="Кто тут? ("+jj+")"
m4gi_set_inner(this_form,"timestr",jj)
else
this_form._timer1.enabled=.f. && таймер работает только при .t.
endif
ENDTEXT
this_form._timer1.textproc=stro
this_form._timer1.post=post
this_form._timer1.this_form=this_form
this_form._timer1.interval=100

</init>
-->

</HEAD>

<body oncontextmenu="return false">

<br>
<SCRIPT LANGUAGE="JavaScript" SRC="fly.js">
</script>


<p align=right>Текущие Дата/время: <b id="timestr"><fp>&datetime()</fp></b></p>

<!--
<script type="text/javascript">
setInterval(function(){
<scriptaction>
local jj
jj=ttoc(datetime())
this_form.caption="Кто тут? ("+jj+")"
This_form.wb.Document.getElementByID("timestr").innerHtml=jj
</scriptaction>;
}, 755);
</script>
-->


<br>

<form name="main_form" id="main_form_id1" method="post"
action="<action>return m4gi_exec('/prg_m4gi_avtoriz.prg',post,this_form)</action>" onsubmit="return false;">
<fp>

LOCAL stro
stro=""
DO CASE
CASE _m4gi_type=0
TEXT TO stro TEXTMERGE NOSHOW
Необходимо авторизоваться (что-бы понять, а кто, собственно, здесь находится).<br><br>
<br>Введите имя: <input type="text" name="text_name" id="text_id1" value="<<_m4gi_name>>" />
<br>Введите пароль: <input type="password" name="text_pwd" id="text_id2" value="" />
ENDTEXT



CASE _m4gi_type=1
TEXT TO stro TEXTMERGE NOSHOW
Добавление нового пользователя.<br><br>
<br>Введите имя: <input type="text" name="text_name" id="text_id3" value="<<_m4gi_name>>" />
<br>Отнеситесь к этому внимательно! Восстановление пароля "невозможно"!<br>
<br>Введите пароль: <input type="password" name="text_pwd1" id="text_id4" value="" />
<br>Введите пароль еще раз (для проверки): <input type="password" name="text_pwd2" id="text_id5" value="" />
ENDTEXT
ENDCASE
return stro

</fp>
</form>
<input type="button" value="<fp>&iif(_m4gi_type=0,"Войти","Добавить и войти")</fp>" onclick="document.forms['main_form'].submit();">
<fp>&iif(_m4gi_type=0,[<p align=right><i><font size=-1><a href="<action>_m4gi_type=1{{_m4gi_name=''</action>">Перейти к добавлению нового пользователя</a></font></i></p>],;
[<p align=right><i><font size=-2><br><br><a href="<action>_m4gi_type=0{{_m4gi_name=''</action>">Отказаться от добавления нового пользователя</a></font></i></p>])</fp>

<br>
<a onclick="<scriptaction>
wait window "Добрый день! Сегодня "+dtoc(datetime()) nowait
</scriptaction>" href="javascript:void(0)">Кликните! Пример вывода в окне Wait приветствия с текущей датой</a>

</body>
</html>




Вопрос-Ответ
Контакты
Визитки 
Статьи
Генератор Интерфейса 
Maple4 Report Generator
Новости 
CMS 
Недосказанное 
Ресурсы 
Карта 


Газонокосилка mtd
газонокосилок Mtd! Официальный дилер! Гарантия
mt-tehnika.ru
мерзлотная лаборатория грунтов https://mdgt.ru/
mdgt.ru

Что-то интересное

Военные кампании майя

Гугенотские войны

Грызуны

План Барбаросса

Страдающее Средневековье

Все интересное



Что-то политическое

Свобода или стены СИЗО - итоги 2018 для украинских политзаключенных

Обновленный Оппоблок поставил на Вилкула

Тайная встреча Сталина и Гитлера - ещё более ранний источник

Выступление Зеленского в Раде и отставка Кабинета Министров

За кого голосовать на выборах 21 июля. Осторожно, торчат уши Медведчука :)

Все о политике



 Контакты   Поиск   Карта сайта 

create by Maple4 Site Creator 9/2021
Яндекс.Метрика