• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Задача web навигации вправо влево список. Поиск альтернативы.

NetWood

Lotus Team
17.04.2008
545
93
BIT
8
Итак, стандартная задача web навигации списка имеет следующее решение:
Делаем вьюху Memo и к ней, скажем $$ViewTemplate for Memo. Внутри ставим поле $$ViewBody или посложнее. На самом вебе делаем три кнопки
"memo/"+pagename+"?Navigate&To=Prev" Назад
"memo"+"?openview" Список
"memo/"+pagename+"?Navigate&To=Next" Вперед
Это все работает, листается, но имеет ряд недостатков:
1. HTML на $$ViewTemplate for Memo с "memo?openview" имеет гадкое <meta name="robots" content="noindex">
2. По ходу дела урлы в листании идут с ID дока и они же попадут в индекс поисковиков, что не по-джедайски как-то.
3. На каждую такую тему надо создавать отдельную вьюху, форму (много Memo) и муторно это.

И вот вопрос. Может есть какая у кого написанная собако-формула или решение, чтобы генерила Назад(предыдущий док)/Список(типа вьюха, клон вьюхи и пр.)/Вперед(следующий док) из текущего дока и чтобы по окончании листания валилось в стандартный список, как по дефолту? Док может быть ограничен каким-нибудь полем Category. Имена пейджей можно задать с цифрами, но как вываливаться в список по окончании?
И чтобы не перегрузить это все DBлукапами и DBколумнами.

Чет давно я не брал я в руки шашку... Может позабыл решение. RestrictToCategory не предлагать, плиз. Это неудобно и пройденный этап.
Листание во вьюхе со start и count типа такого делал, но это не то.
Код:
REM {Create links for each page of view};
viewname:="pages/"+pagename;
count:=
@If(
@UrlQueryString("count")="" | @IsError(@TextToNumber(@UrlQueryString("count")));
@GetProfileField("Configuration_Profile"; "DefaultDisplayCount");
@TextToNumber(@UrlQueryString("count"))
);
link := "<a href=\""+viewname+"?open" + "&start=";
  path := Path_Info;
  startnum := @TextToNumber(@UrlQueryString("start"));
  countnum :=@TextToNumber(@UrlQueryString("count"));

start:=1;
@If(
   (@UrlQueryString("start")="") | (@UrlQueryString("count")="");
  @While(start <= ThreadTopic;
  linkall:=" | <b> " + @Text("все ("+@Text(ThreadTopic)) + ")</b>";
  html:=html + link + @Text(start) + "&count=" + @Text(count) + options + "\">" + @Text(1+(start-1)/count) + "</a> ";
  start:=start+count
  )
;
  @While(start <= ThreadTopic;
  linkall := " | <a href=\""+viewname+"?open"+ "\">" +@Text("все")+"</a>"+" ("+@Text(ThreadTopic)+")";
  @If(@Text(start) = @UrlQueryString("start");
  html:=html + "<b> " + @Text(1+(start-1)/count) + " </b> ";
  html:=html + link + @Text(start) + "&count=" + @Text(count) + options + "\">" + @Text(1+(start-1)/count) + "</a> ");
  start:=start+count
  )
);

  next := @If(startnum+countnum >= ThreadTopic;@Nothing;" <a title='вперед'  href="+@ReplaceSubstring (Path_Info; "start="+@Text(startnum) ; "start="+@Text(startnum+countnum))+">></a>");
  prev := @If(startnum=1;@Nothing;"<a title='назад' href="+@ReplaceSubstring (Path_Info; "start="+@Text(startnum) ; "start="+@Text(startnum-countnum))+"><</a> ");
  prev+html+next+linkall
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
1. HTML на $$ViewTemplate for Memo с "memo?openview" имеет гадкое <meta name="robots" content="noindex">
самому задать мета тег в форме
2. По ходу дела урлы в листании идут с ID дока и они же попадут в индекс поисковиков, что не по-джедайски как-то.
а с чем надо (алгоритм)?
3. На каждую такую тему надо создавать отдельную вьюху, форму (много Memo) и муторно это.
копировать дизайн ноты скриптом
Имена пейджей можно задать с цифрами, но как вываливаться в список по окончании?
а что "сейчас" (я давно не связывался генеримыми ссылками)?
 

NetWood

Lotus Team
17.04.2008
545
93
BIT
8
<meta name="robots" content="noindex"> - неудаляемо.
<meta name="robots" content="index,follow" />
1. Ну не вариант же. Даже обсуждать лениво. И что из этого ОНИ будут считать верным.
2. Формула нужна.
3. Плодить сущности.
4. Сейчас все ок, но хочется катарсиса без. п.1 п.3 на основании п.2
 

NetWood

Lotus Team
17.04.2008
545
93
BIT
8
$$HTMLTagAttributes $$HTMLFrontMatter не исправляют, к сожалению <meta name="robots" content="noindex"> во вьюхе.
Я пока решил сгенерить через GetAllEntriesByKey на Postsave навигацию для каждого дока в списке и запихать в специальное поле.

В самом начале очень кратко написал, но в идеале, надо генерить так
Код:
<li><a href="<Вычисляемое значение>" class="icon  fa-chevron-circle-left"><span class="label">Назад</span></a></li>
<li><a href="<Вычисляемое значение>" class="icon  fa-list"><span class="label">Меню</span></a></li>
<li><a href="<Вычисляемое значение>" class="icon fa-chevron-circle-right"><span class="label">Вперед</span></a></li>
Вот это <Вычисляемое значение> и надо рассчитать.
 
Последнее редактирование модератором:

NetWood

Lotus Team
17.04.2008
545
93
BIT
8
В общем, чтобы не смущать общественность открытой темой, сделал так (На оптимальность кода не претендую. Можно было один лишний NotesViewEntryCollection почикать, но лениво):
Код:
Sub Postsave(Source As Notesuidocument)
    Dim s As New NotesSession
    Set db = s.CurrentDatabase
    Dim view, vCalView, vCalView_content As NotesView  
    Dim collec As NotesDocumentCollection
    Dim vDocEntry, vDocEntry_next, vDocEntry_prev, vDocEntry_content As NotesViewEntry
    Dim vDocCollection, vDocCollection_content As NotesViewEntryCollection
    Dim doc, vDoc, vDoc_prev, vDoc_next, vDoc_content As NotesDocument
    Dim liststring As String
    Set doc = Source.Document
  
    Set vCalView = db.GetView("(LookupCategory)")
    Set vCalView_content = db.GetView("(LookupCategoryContent)")
    'Print "----------------------"  
    'Print doc.GetItemValue("Category")(0)
  
    Set vDocCollection = vCalView.GetAllEntriesByKey(doc.GetItemValue("Category")(0), True)    ' коллекшон сортированный по view, сколько доков=category
    If Not vDocCollection Is Nothing Then
        'Print "vDocCollection.count =" + Cstr(vDocCollection.count)
        Stamp= False
      
        'Определение первого пункта со списком
        Set vDocCollection_content = vCalView_content.GetAllEntriesByKey(doc.GetItemValue("Category")(0), True)    ' первый пункт меню
        Set vDocEntry_content = vDocCollection_content.GetFirstEntry() ' и он же единственный  
        Set vDoc_content = vDocEntry_content.Document  
      
        'В начале определяем первого
        Set vDocEntry = vDocCollection.GetFirstEntry()  
        Set vDoc = vDocEntry.Document  
        Set vDocEntry_next = vDocCollection.GetNextEntry(vDocEntry)
        Set vDoc_next = vDocEntry_next.Document  
        If vDoc.pagename(0)    = doc.pagename(0) And Stamp= False    Then
            liststring = vDoc_content.pagename(0)+";#;"+vDoc_content.pagename(0)+";#;"+vDoc_next.pagename(0)
            'Print  liststring+" 1"
            Call doc.ReplaceItemValue("HTML_Navigations", liststring)                               
            Call doc.Save(True,True)
            Stamp = True
        End If
      
        'Потом определяем последнего
        Set vDocEntry = vDocCollection.GetLastEntry()      
        Set vDoc = vDocEntry.Document
        Set vDocEntry_prev = vDocCollection.GetPrevEntry(vDocEntry)
        Set vDoc_prev = vDocEntry_prev.Document  
        If vDoc.pagename(0)    = doc.pagename(0) And Stamp= False    Then
            liststring = vDoc_prev.pagename(0)+";#;"+vDoc_content.pagename(0)+";#;"+vDoc_content.pagename(0)
            'Print  liststring+ " 2"  
            Call doc.ReplaceItemValue("HTML_Navigations", liststring)                               
            Call doc.Save(True,True)
            Stamp = True
        End If      
      
        'Далее в середине
        If Stamp= False Then  
            Set vDocEntry = vDocCollection.GetFirstEntry()  
          
            Do Until vDocEntry Is Nothing          
                Set vDoc = vDocEntry.Document                      
              
                If vDoc.pagename(0)    = doc.pagename(0) And Stamp= False Then
                    Set vDocEntry_prev = vDocCollection.GetPrevEntry(vDocEntry)
                    Set vDoc_prev = vDocEntry_prev.Document  
                    Set vDocEntry_next = vDocCollection.GetNextEntry(vDocEntry)
                    Set vDoc_next = vDocEntry_next.Document  
                    liststring = vDoc_prev.pagename(0)+";#;"+vDoc_content.pagename(0)+";#;"+vDoc_next.pagename(0)
                    'Print  liststring + " 3"
                    Call doc.ReplaceItemValue("HTML_Navigations", liststring)                               
                    Call doc.Save(True,True)
                    Stamp = True                  
                End If
              
                Set vDocEntry  = vDocCollection.GetNextEntry(vDocEntry )                  
            Loop      
        End If
      
    Else
        'Print "vDocCollection.count = 0"
    End If      
End Sub

На форме вычисляемая навигация и список убран в вычисляемую подформу :
Код:
REM {формирование навигации по листам из содержимого HTML_Navigations заранее вычисленного в Postsave дока Memo};
pages := @Explode(HTML_Navigations;";#;");
prev := @Subset(@Subset(pages;1);-1); REM {назад};
menu := @Subset(@Subset(pages;2);-1); REM {меню};
next := @Subset(@Subset(pages;3);-1); REM {вперед};

linkprev:=    "<li><a href=memo/"+prev+"?open class='icon  fa-chevron-circle-left'><span class='label'>Назад</span></a></li>";
linkmenu:="<li><a href=memo/"+menu+"?open class='icon  fa-list'><span class='label'>Меню</span></a></li>";
linknext:="<li><a href=memo/"+next+"?open class='icon fa-chevron-circle-right'><span class='label'>Вперед</span></a></li>";

linkprev+linkmenu+linknext

Какие плюсы?
1. Не надо плодить сущности в дизайнере.
2. Можно управлять доступом к стартовому доку из клиента, а не из дизайнера
3. Нет <noindex>
4. Нет дублей ID вьюхи и дока в URL при навигации
5. Ну и вообще правильно.
Из минусов - только пересчитывать все доки скриптом при добавлении нового. Всем спасибо за внимание. Ну надо было мне самому себе вопрос задать :).
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
liststring = vDoc_content.pagename(0)+";#;"+vDoc_content.pagename(0)+";#;"+vDoc_next.pagename(0)
это и был мой вопрос
концептуально - можно не пересчитывать все доки, если имя страницы уникально, достаточно знать Entry.Position и от них получать (динамически) предыдущую и след. "страницы" (энтирисы во вьюшке), мало того - они будут известны, т.к получив текущую - математически вычисляем следующую
 
Последнее редактирование:
  • Нравится
Реакции: NetWood

NetWood

Lotus Team
17.04.2008
545
93
BIT
8
Эта, спасибо, конечно. Но мы три класса церковно-приходской :). Entry.Position не осилю :)(. Люблю простые решения.

Забыл еще один плюс.
6. Можно отсортировать вьюшку и отображение на вебе как надо. По стандарту $$ можно отсортировать только по имени страницы (memo/pagename?open ) и навигация будет на нее же опираться. Иначе вьюшку не отсортировать. Менять потом очень муторно.
 
Последнее редактирование:

rinsk

Lotus Team
12.11.2009
1 151
125
BIT
4
При кол-ве доков свыше тыщ 5, вся эта штука будет жутко тормозить...
Моё Имхо (на личном опыте) - выкинуть все эти $$/@ и юзать джейсон от вьюшек со своей рисовалкой.
В этих джейсонах есть вся информация о позициях элементов.
UPD - ели нужно что бы вывод сразу был в HTML для индексации поисковиков -
то вместо GetAllEntriesByKey рекомендую NotesViewNavigator+Getentrybykey с последующей навигацией ...
в полученных entry так же все есть что нужно.
Для своих задач написал класс, который под нагрузкой показал в разы лучшие результаты:
Код:
%REM
    Class KeySearchClass
    Description: Класс для нечеткого поиска по ключу
%END REM
Class KeySearchClass
    Public nv As NotesViewNavigator
    Private v As NotesView
    Private colHash List As Integer
    Public ne As NotesViewEntry
    Public count As Long
    Private key As string
    Private isFirst As Boolean
    Private isCategory As Boolean
    Public exactMath As Boolean
    Sub New(vv As NotesView)
        GoTo begin
errors: MsgBox Error & "| KeySearchClass,New:"& Erl : Exit Sub
begin:On Error GoTo errors     
        Set Me.v=vv
        me.v.AutoUpdate=False
        Set me.nv=me.v.CreateViewNav
        me.nv.Entryoptions=2
        me.nv.Buffermaxentries=400
        me.isFirst=True
        me.count=0
        me.exactMath=false
        me.isCategory=v.Columns(0).isCategory
        Dim k As Integer
        For k=0 To v.Columncount-1 : colHash(LCase(v.Columns(k).itemName))=k :    Next
        If  Not v.Columns(0).isSorted Then Error 1001,"KeySearchClass:First column in view must be sorted...:" & vv.name
    End Sub
    Property Get GetByKey(key,isMath) As NotesViewEntry
        me.key=key
        me.exactMath=isMath
        If me.isCategory And me.exactMath Then
            Set me.nv=me.v.CreateViewNavFromCategory(me.key)
            me.nv.Entryoptions=2
            me.nv.Buffermaxentries=400
            Set me.ne=me.nv.GetFirstDocument         
        else 
        Set me.ne=me.v.Getentrybykey(key,me.exactMath)
        If Not me.ne Is Nothing Then
            Set me.ne=me.nv.Getentry(me.ne)
            If me.ne.Iscategory Then Set me.ne=me.nv.Getnextdocument(me.ne)
            me.count=1
            me.isFirst=False
        Else
            me.count=0
            me.isFirst=true
        End If
        End If
        Set GetByKey=me.ne
    End Property

    Private Function CompareKey(var,query) As Boolean
        ''' функция сравнивает значение 1 колонки с запросом
If me.exactMath And me.isCategory Then '' если категория и по полному ключю - нечего дальше делать
    CompareKey=True
     Exit Function
End If
        If me.exactMath Then 'если по полному ключу - то проверяем наличие в массив
     If IsArray(var) Then
         CompareKey=Not IsNull(ArrayGetIndex(var,query,5))
     Else
         CompareKey=(LCase(var)=LCase(query))
     End If
        Else 'проверяем частичное совпадение ключа
          
        If IsArray(var) Then
        ForAll d In var
            If InStr(1,d,query,5)=1 Then
                CompareKey=True
                Exit Function
            End If
        End ForAll
        Else
         CompareKey=(InStr(1,var,query,5)=1)
         End If
        End if
    End Function
    Property Get doc As NotesDocument
            Set doc=me.ne.Document 
    End Property

        Function FindFirst(key,isMath As Boolean) As boolean
                    FindFirst=(Not me.GetByKey(Key,isMath) Is Nothing)
        End Function
        Function FindNext() As Boolean
                Set me.ne=me.nv.Getnextdocument(me.ne)
                If Not me.ne Is Nothing Then
                    If me.CompareKey(me.ne.Columnvalues(0),me.key) Then
                        me.count=me.count+1
                    Else
                        Set me.ne=nothing
                    End If 
                End If
            FindNext=(Not me.ne Is Nothing)
        End Function
    Public Function GetValue(col) As Variant
              
        If IsNumeric(col) Then
            GetValue=me.ne.Columnvalues(col)
        ElseIf IsElement(me.colHash(LCase(col))) Then
            GetValue=me.ne.Columnvalues(me.colHash(LCase(col)))
        Else
            Dim tmp As String
            ForAll n In me.colHash
                tmp=tmp & ListTag(n) & ","
            End ForAll
            Error 1004,"column not found:" & col & " exist columns in view '" & me.v.Name & "': " & tmp
        End If
    End Function
    Public Function GetDocValue(Field) As Variant
        GetDocValue=me.ne.Document.GetItemValue(Field)
    End Function
    Public Function GetStrValue(col) As Variant
        Dim ret As Variant
        ret=me.GetValue(Col)
        If IsArray(ret) Then 'массив
            ret=Join(ret,"")
        Else
            ret=CStr(ret)
        End If
        GetStrValue=ret
    End Function
    Sub Delete
        Erase colHash
        Set me.nv=Nothing
        Set me.v=Nothing
    End Sub
End Class
 
Последнее редактирование:
  • Нравится
Реакции: NetWood и lmike

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
ЗЫ - эт по мотивам
там написано "праильнее" не 2, а VN_ENTRYOPT_NOCOUNTDATA ;)
делап еще и сдоступом по индексу, тогда учитывал
NotesViewNavigator.GotoPos и NotesViewEntry.GetPosition(".")
первый (NotesView .GetEntryByKey) и последний ентрисы (getAllEntriesByKey... GetLastEntry) получал по ключу, "фиксировал" позиции, надо еще преобразовывать notesViewNavigator .GetEntry( entry )
навигатор был по всей вьюшке
но это специфика - отбор по диапозону дат не позволял указывать второй критерий отбора и приходилось так изголяться (естественно - сравнение ключей запроса и т.п.)[/QUOTE]
 
Последнее редактирование:

NetWood

Lotus Team
17.04.2008
545
93
BIT
8
При кол-ве доков свыше тыщ 5, вся эта штука будет жутко тормозить...
Моё Имхо (на личном опыте) - выкинуть все эти $$/@ и юзать джейсон от вьюшек со своей рисовалкой.
Это тормозит уже на двухстах. Другой вопрос, что не динамика. Один раз посчитал и все хранится в доке. Работающее годами можно подождать пару-тройку минут и забыть. Локальный подход...
И, вообще, надо расстреливать за UI, где на 5 тыщах доках надо вправо влево листать. Дичь :).
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!