Oracle DB, Oracle APEX, Linux etc.

понедельник, 5 октября 2009 г.

ApEx: обновление переменных в сессии без сабмита

Частенько так бывает, что нужно воспользоваться новым значением элемента на странице в скриптах или запросах без сабмита этой страницы. Например, обновить интерактивный отчёт или простой PPR-отчёт, выполнить процесс по требованию etc. Чтобы значение переменной, соответствующей этому элементу, изменилось в сессии, есть пара приёмов.

Чтобы ассинхронно обновить значение переменной в JavaScript, можно воспользоваться классом apex.ajax.ondemand:

/* Сохранить в сессии значение элемента асинхронно */
function saveThisItemAsync(p){
/* создаём пустой вызов к БД - без имени процесса и callback-функции */
var aget = new apex.ajax.ondemand();
/* добавляем нашу переменную-элемент */
aget.ajax.add(p.id, $v(p));
aget._get();
}


Для синхронного обновления можно воспользоваться им же, просто вызвав ajax.get(). :) Вот JS-функция для синхронного обновления значения переменной в сессии:

/* Сохранить в сессии значение элемента */
function saveThisItem(p){
var get = new apex.ajax.ondemand();
get.ajax.add(p.id, $v(p));
get.ajax.get();
}


Если кто-то хочет посмотреть, что там внутри apex.ajax.ondemand находится - пожалуйста:

apex.ajax = {
...
ondemand : function (pWidget,pReturn){
var that = this;
this.ajax = new htmldb_Get(null,$x('pFlowId').value,'APPLICATION_PROCESS='+pWidget,0);
this._get = _get;
this._set = _set;
this._return = !!pReturn?pReturn:_return;
return;
function _get(pValue){
that.ajax.GetAsync(that._return);
}
function _set(pValue){}
function _return(pValue){}
}
}

Таким образом, всё, что можно делать с htmldb_Get, можно делать и с apex.ajax.ondemand. Просто иногда короче. :)
Спасибо за информацию для размышления и написания этого поста kvad на sql.ru: Oracle APEX за этот пост
.


Читать далее

пятница, 2 октября 2009 г.

SyntaxHighlighter: Подсветка кода в блоге

В определённый момент мне захотелось добавить подсветку кода в блог. После непродолжительных поисков я наткнулся на SyntaxHighlighter. Всё что нужно, чтобы использовать его, это...
  • Скачать с сайта набор скриптов и таблиц стилей и загрузить их на какой-либо хостинг ИЛИ не скачивать, а воспользоваться бесплатным хостингом проекта.
  • Изменить HTML-макет Вашего блога, добавив в тег HEAD библиотеку jQuery, стили и скрипты SyntaxHighlighter. Вариат первый - Вы загрузили всё это на хостинг, тогда указывайте соответствующие пути к файлам на хостинге. Например, для кистей (так называются классы с определённым синтаксисом содержащегося кода) Shell, JavaScript, XML/HTML, SQL:
    <script type='text/javascript' src="http://path/to/jquery" /> 
    <link href='http://path/to/SyntaxHighlighter/styles/shCore.css' rel='stylesheet' type='text/css'/>
    <link href='http://path/to/SyntaxHighlighter/styles/shThemeRDark.css' rel='stylesheet' type='text/css'/>
    <script src='http://path/to/SyntaxHighlighter/scripts/shCore.js' type='text/javascript'/>
    <script src='http://path/to/SyntaxHighlighter/scripts/shBrushBash.js' type='text/javascript'/>
    <script src='http://path/to/SyntaxHighlighter/scripts/shBrushJScript.js' type='text/javascript'/>
    <script src='http://path/to/SyntaxHighlighter/scripts/shBrushXml.js' type='text/javascript'/>
    <script src='http://path/to/SyntaxHighlighter/scripts/shBrushSql.js' type='text/javascript'/>
    

    Полный список кистей находится здесь.

    А вот вариант с использованием бесплатного хостинга проекта:
    <script src='http://www.google.com/jsapi' type='text/javascript'/>
    <script type='text/javascript'> google.load('jquery', '1');</script>
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeRDark.css' rel='stylesheet' type='text/css'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
    


    За тему расцветки синтаксиса отвечает файл shThemeRDark.css. Если хотите изменить тему расцветки - выберите подходящую из этого списка.
  • Нужно добавить запуск SyntaxHighlighter при полной загрузке документа (страницы). Для этого я использую jQuery, тег HEAD и следующий скрипт:
    $(document).ready(
    function runSyntaxHighlighter(){
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
    SyntaxHighlighter.all();
    }
    );
    

    Если Вы пользуетесь не бесплатным хостингом проекта, а своим собственным, то замените путь http://alexgorbatchev.com/pub/sh/current на соответствующий.
  • И теперь, чтобы включить для кода подсветку, заключите его в теги:
    <pre class="brush: brushName">ваш код</pre>
    

Всё. :) Есть ещё масса настроек, возможностей и прочего, что я советую прочитать на сайте этого проекта.

ИЗМ: Небольшое изменение в блоге.


Читать далее

ApEx: Popup Key LOV, null key и небольшой баг

Недавно наткнулся на подобный баг: есть страница, на ней есть элемент типа Popup Key LOV (выбор нужного значения из списка во всплывающем окне). Если разрешить отображать строку с ключом NULL (aka return value) и, например, описанием "Это строка с ключом NULL", то обработчик для щелчка по ней во всплывающем окне будет следующим:
<a href="javascript:passBack('');">Это строка с ключом NULL</a>

В функцию passBack передаётся один фактический параметр, хотя формальных там два. И вот второй, который отвечает за ключ списка, будет неопределённым. Поэтому при сабмите мы запишем в значение переменной для этого элемента undefined, и, соответственно, произойдёт ошибка при выполнении запроса, определяющего LOV.

Решение: 0. Поменять запрос LOV, добавив в него
select 'Это строка с ключом NULL' d, null r from dual union all

1. Добавить Computation на страницу, где можно выбирать значение с ключом NULL, для элемента, основанного на этом LOV, заменяя его значение либо функцией:
FUNCTION f_lov_null(p_item_name IN VARCHAR2) Return VARCHAR2 IS
BEGIN
IF v(p_item_name) = 'undefined' THEN
Return(NULL);
ELSE
return(v(p_item_name));
END IF;
END;

либо каждый раз конкретно:
nullif(lower(v('YOUR_ITEM_NAME')), 'undefined')


Мне пока хватило варианта с nullif.

Читать далее

вторник, 15 сентября 2009 г.

ApEx: Асинхронность и часть страницы

Вначале отписал на sql.ru, дублирую здесь.

У htmldb_Get().get второй и третий параметры - теги, которые ограничивают необходимую часть результата (по умолчанию "<!--START-->" и "<!--END-->"). У htmldb_Get().getAsync параметр всего один - функция обратного вызова. А мне нужны и асинхронность, и часть результата, ограниченная определёнными тегами. И поскольку нигде я подобной штуки не нашёл, то сделал сам. Пишу здесь, авось кому-то пригодится.

Итак, у нас есть страница M, в которой будем через AJAX асинхронно обновлять HTML-код региона с id=RESULT_REGION (в принципе, обновлять можем любой не-input DOM-элемент, у которого есть атрибут innerHTML). В качестве содержимого для этого региона берём что-нибудь со страницы N, ограниченное тегами "<!--START_X-->" и "<!--END_X-->".

У htmldb_Get есть метод getPartial, который возвращает часть ответа между двумя тегами (первый и второй параметры метода). Но этот метод работает с полем htmldb_Get.response, которое при вызове GetAsync не заполняется. Поэтому, чтобы не писать собственный Trim для ответов сервера, а использовать уже готовый, надо присваивать этому полю p.response.

Ниже идёт JS-код из заголовка страницы M:
<script type="text/javascript">
var get;

function doIt(){
get = new htmldb_Get(null, $v('pFlowId'),null,N /*Номер страницы с нужным содержимым*/ );
get.GetAsync(f_AsyncReturn);
};

function f_AsyncReturn(){
if (p.readyState==4) {
/*Присваиваем текст ответа нашей переменной get*/
get.response = p.responseText;
/*Присваиваем содержимому нужного элемента часть ответа между двух тегов*/
$x('RESULT_REGION').innerHTML=get.getPartial("", "");
get = null;
}
}
</script>


Полезные ссылки по теме: примеры Карла Бэкстрома по htmldb_Get.get() и htmldb_Get.GetAsync(), описание XMLHttpObject на w3schools.

UPD: Здесь kvad предложил улучшенный вариант, чтобы уйти от возможных проблем с переменной get при множественных асинхронных запросах. Привожу его ниже с небольшими изменениями:

/*В функцию добавлены параметры - регион и страница, которую запрашиваем*/
/*Кроме того, я добавил параметры тегов, с которого и по который считывать страницу*/
function doIt(frame, page, from_tag, to_tag){
var get;
get = new htmldb_Get(null, $v('pFlowId'),null,page);
get.p = get.GetAsync(function(){f_AsyncReturn(get, frame, from_tag, to_tag)});
};

function f_AsyncReturn(get, frame, from_tag, to_tag){
if (get.p && get.p.readyState==4) {
get.response = get.p.responseText;
$x(frame).innerHTML = get.getPartial(from_tag, to_tag);
get = null;
}
}

Читать далее

вторник, 8 сентября 2009 г.

ApEx 3.2.1: Что-то не срослось...

Поставил ApEx 3.2.1 дома. По пока непонятным причинам пришлось удалять 3.2 и ставить патч начисто. Неясными в руководстве по установке оказались два момента:
0. Нигде не сказано, что вначале нужно остановить экземпляр и запустить его уже в режиме апгрейда. Без этого лично я на Oracle 11.1.0.6 for Linux x86 получаю ORA-39702. Ладно, домашний сервер остановить не проблема, но вот зачем - вопрос открыт. По-моему, достаточно просто отключить HTTP-сервер, чтобы убрать пользовательские сеансы.
1. Запускаю apxpatch - отрабатывает без проблем. Запускаю apxldimg - всё отлично. Запускаю прослушиватель, HTTP-сервер, захожу в ApEx - в углу всё та же версия 3.2.0.00.27. То есть, патч не применился. Что не так - разберусь уже позже.

UPD: Может быть, всё из-за того, что я скачивал полный ApEx 3.2.1, а не патчсет с Металинка. Тем не менее, apxpatch в нём был, а значит, должен был отработать нормально.

PS: По прошлой заметке - к сожалению, всё оказалось плохо. Скрипты шапки намертво прописаны в WWV_FLOW_UTILITIES, потому пользуюсь внешними JS-библиотеками через связку Substitution strings+Templates.
Читать далее

пятница, 4 сентября 2009 г.

ApEx и автоматическое добавление в HEAD страницы скриптов и стилей

На sql.ru я уже задал этот вопрос, но решил написать и здесь.

Чего хочется: чтобы Апекс, генерируя страницу, автоматом дописывал в <HEAD> нужные либы и таблицы стилей.

Где-то тут:

<head>
<title>Edit Page Template</title>
<link type="image/x-icon" href="/i/favicon.ico" rel="icon"/>
<link type="image/x-icon" href="/i/favicon.ico" rel="shortcut icon"/>
<script type="text/javascript" src="/i/javascript/apex_ns_3_1.js"></script>
<script type="text/javascript" src="/i/javascript/apex_3_1.js"></script>
<script type="text/javascript" src="/i/javascript/apex_get_3_1.js"></script>
<script type="text/javascript" src="/i/javascript/apex_builder.js"></script>
<script type="text/javascript"></script>
<link type="text/css" href="/i/css/apex_3_1.css" rel="stylesheet"></link>
<script type="text/javascript"></script>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<link type="text/css" href="/i/css/apex_builder_3_1.css" rel="stylesheet"></link>
<!-- То, что хочу подключить -->
</head>


Знаю, что дока говорит: подключайте скрипты и CSS через шаблоны страниц либо через атрибут HTML Header. Используя строки подстановки, можно всё это поддерживать в актуальном состоянии при изменениях. Знаю, что ещё можно создать страницу #0, на ней создать HTML-регион, в него вписать нужное.

Но хочется простого инсёрта или вызова процедуры, куда передать "jquery-1.3.2.js" и путь в XML DB. :) Откуда-то же тянет Апекс всё это дело в заголовок каждой страницы...

После поисков в таблицах и пакетах наткнулся в заврапированном теле WWV_FLOW_UTILITIES на такое:

1G_PAGE_HTML_HEAD:
1<link rel="stylesheet" href=":
1css/apex_3_1.css" type="text/css" /><!--[if IE]><link rel="stylesheet" href=":
1css/apex_ie_3_1.css" type="text/css" /><![endif]--><script src=":
1javascript/apex_ns_3_1.js" type="text/javascript"></script><script src=":
1javascript/apex_3_1.js" type="text/javascript"></script><script src=":
1javascript/apex_get_3_1.js" type="text/javascript"></script>:


Хардкод налицо. :( Тем не менее, есть ма-а-аленькая надежда, что на дело влияет не он. Вечерком попробую скопировать и анврапнуть flowu.plb, поменять этот хардкод, добавив к нему jQuery UI, и установить заново. Если получится, и Апекс будет возвращать страницы с нужным мне хэдером - плохо. Править пакеты на тесте и продакшнах, понятное дело, мне никто не даст, потому такой способ подойдёт только на девелоперской или домашней базе побаловаться.

Читать далее

среда, 17 июня 2009 г.

Oracle APEX: 2.x -> 3.2

Чтоб учить быстрее, апгрейднул домашнюю версию до рабочей. Если всё делать по руководству - проблем не возникает...

Единственный совет, который могу дать, состоит в том, чтобы распаковывать загруженный с OTN архив в /tmp под *никсами и C:\TEMP под виндой. Есть там одно запоздалое уточнение в руководстве, что они под этими папками в скриптах подразумевают путь, куда распаковали архив с APEX.
Читать далее