Jump to content


Photo

SearchBar component prototype

Search bar; SVG icons

  • Please log in to reply
2 replies to this topic

#1 Laksekjønn

Laksekjønn
  • Members
  • 440 posts

Posted 05 September 2017 - 01:06 AM

This is the SearchBar prototype component with SVG icons

unit uSearch;

{ ╔═════════════════════════════╗
  ║  _______  _______  _______  ║
  ║ (  ____ \(       )(  ____ \ ║
  ║ | (    \/| () () || (    \/ ║
  ║ | (_____ | || || || (_____  ║
  ║ (_____  )| |(_)| |(_____  ) ║
  ║       ) || |   | |      ) | ║
  ║ /\____) || )   ( |/\____) | ║
  ║ \_______)|/     \|\_______) ║
  ║ by warleyalex               ║
  ╚═════════════════════════════╝ }


interface

uses
  SmartCL.System,
  SmartCL.Components,
  W3C.HTML5, W3C.Console, W3C.DOM;

type
  TNotifyEvent  = procedure(Sender: TObject);

  TSearch = class(TW3CustomControl)
  private
    { Private declarations }
  protected
    { Protected declarations }
    procedure createSearchBar;
    procedure InitializeObject; override;
    { procedure FinalizeObject; override; }
    { procedure ObjectReady; override; }
    procedure StyleTagObject; override; empty;
    function  getText: String;
    procedure setText(aValue: String);
  public
    { Public declarations }
  published
    { Published declarations }
     property Text: String read getText write setText;
  end;

implementation

{ ╔════════════════════════════════════════════╗
  ║ Insert here external variables             ║
  ╚════════════════════════════════════════════╝ }
function document: variant; external "document" property;

{ ╔══════════════════════════════════════════════════╗
  ║ Insert here the innerComponent (generated code)  ║
  ╚══════════════════════════════════════════════════╝ }
procedure TSearch.createSearchBar;
begin
{ ╔═══════════════════════════════════════════════════════════════════════════╗
  ║ Since the document fragment is in memory and not part of the main DOM     ║
  ║ tree, appending children to it does not cause page reflow (computation    ║
  ║ of elements position and geometry). Consequently, using documentfragments ║
  ║ often results in better performance.                                      ║
  ╚═══════════════════════════════════════════════════════════════════════════╝ }
  var docFragment = document.createDocumentFragment(); // contains all gathered nodes

  var search = document.createElement('FORM');
  search.setAttribute("novalidate", "");
  search.setAttribute("class", "ais-SearchBox__root");
  search.setAttribute("action", "");
  search.setAttribute("role", "search");
  search.setAttribute("id", "search");
  docFragment.appendChild(search);

  var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
  svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
  svg.setAttributeNS(null, "style", "display: none;");
  search.appendChild(svg);

  var sbxiconsearch13 = document.createElementNS("http://www.w3.org/2000/svg",'symbol');
  sbxiconsearch13.setAttribute("xmlns", "http://www.w3.org/2000/svg");
  sbxiconsearch13.setAttribute("id", "sbx-icon-search-13");
  sbxiconsearch13.setAttribute("viewBox", "0 0 40 40");
  svg.appendChild(sbxiconsearch13);

  var path = document.createElementNS("http://www.w3.org/2000/svg", 'path');
  path.setAttribute("d", "M26.804 29.01c-2.832 2.34-6.465 3.746-10.426 3.746C7.333 32.756 0 25.424 0 16.378 0 7.333 7.333 0 16.378 0c9.046 0 16.378 7.333 16.378 16.378 0 3.96-1.406 7.594-3.746 10.426l10.534 10.534c.607.607.61 1.59-.004 2.202-.61.61-1.597.61-2.202.004L26.804 29.01zm-10.426.627c7.323 0 13.26-5.936 13.26-13.26 0-7.32-5.937-13.257-13.26-13.257C9.056 3.12 3.12 9.056 3.12 16.378c0 7.323 5.936 13.26 13.258 13.26z");
  path.setAttribute("fill-rule", "evenodd");
  sbxiconsearch13.appendChild(path);

  var sbxiconclear3 = document.createElementNS("http://www.w3.org/2000/svg",'symbol');
  sbxiconclear3.setAttribute("xmlns", "http://www.w3.org/2000/svg");
  sbxiconclear3.setAttribute("id", "sbx-icon-clear-3");
  sbxiconclear3.setAttribute("viewBox", "0 0 20 20");
  svg.appendChild(sbxiconclear3);

  var path_0 = document.createElementNS("http://www.w3.org/2000/svg",'path');
  path_0.setAttribute("d", "M8.114 10L.944 2.83 0 1.885 1.886 0l.943.943L10 8.113l7.17-7.17.944-.943L20 1.886l-.943.943-7.17 7.17 7.17 7.17.943.944L18.114 20l-.943-.943-7.17-7.17-7.17 7.17-.944.943L0 18.114l.943-.943L8.113 10z");
  path_0.setAttribute("fill-rule", "evenodd");
  sbxiconclear3.appendChild(path_0);

  var div_ = document.createElement('DIV');
  div_.setAttribute("role", "search");
  div_.setAttribute("class", "ais-SearchBox__wrapper");
  search.appendChild(div_);

  var input = document.createElement('INPUT');
  input.setAttribute("type", "text");
  input.setAttribute("placeholder", "Search here…");
  input.setAttribute("autocomplete", "off");
  input.setAttribute("autocorrect", "off");
  input.setAttribute("autocapitalize", "off");
  input.setAttribute("spellcheck", "false");
  input.setAttribute("required", "");
  input.setAttribute("value", "");
  input.setAttribute("class", "ais-SearchBox__input");
  div_.appendChild(input);

  var button = document.createElement('BUTTON');
  button.setAttribute("type", "submit");
  button.setAttribute("title", "Submit your search query.");
  button.setAttribute("class", "ais-SearchBox__submit");
  div_.appendChild(button);

  var svg_0 = document.createElementNS( "http://www.w3.org/2000/svg", 'svg');
  svg_0.setAttributeNS(null, "role", "img");
  button.appendChild(svg_0);

  var use = document.createElementNS("http://www.w3.org/2000/svg", 'use');
  use.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#sbx-icon-search-13");
  use.setAttributeNS(null, "fill", "rgba(144,176,179,1)");
  svg_0.appendChild(use);

  var button_0 = document.createElement('BUTTON');
  button_0.setAttribute("type", "reset");
  button_0.setAttribute("title", "Clear the search query.");
  button_0.setAttribute("class", "ais-SearchBox__reset");
  div_.appendChild(button_0);

  var svg_1 = document.createElementNS( "http://www.w3.org/2000/svg", 'svg');
  svg_1.setAttributeNS(null, "role", "img");
  button_0.appendChild(svg_1);

  var use_0 = document.createElementNS("http://www.w3.org/2000/svg",'use');
  use_0.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#sbx-icon-clear-3");
  use_0.setAttributeNS(null, "fill", "red");
  svg_1.appendChild(use_0);

  Self.Handle.appendChild( docFragment );
end;

procedure TSearch.InitializeObject;
begin
  inherited;
{ ╔══════════════════════════════════════════════════╗
  ║ this is a good place to initialize the component ║
  ╚══════════════════════════════════════════════════╝ }
  createSearchBar;

{ ╔═════════════════════════════════════════════════════════════════════╗
  ║ make the control display itself correctly when its ready in the DOM ║
  ╚═════════════════════════════════════════════════════════════════════╝ }
  Handle.ReadyExecute(procedure()
  begin
    (* call createInnerComponent *)

{ ╔══════════════════════════════════════════════════╗
  ║ some basic style attributes after render         ║
  ╚══════════════════════════════════════════════════╝ }
    Self.Handle.style['left'] := null;
    Self.Handle.style['width'] := '100%';
  end);

end;

function TSearch.getText: String;
begin
  Result := document.querySelector('.ais-SearchBox__input').value;
end;

procedure TSearch.setText(aValue: String);
begin
If visible then
  Parent.Handle.ReadyExecute( procedure ()
  begin
    document.querySelector('.ais-SearchBox__input').value := aValue;
  end);
end;

procedure InsertCSS;
(*+--------------------------------------------------------------------------+
  |  Inserts a new style rule into the current stylesheet, dynamically       |
  |  change classes, so style information can be kept in  genuine            |
  |  stylesheets "and avoid adding extra elements to the DOM").              |
  +--------------------------------------------------------------------------+*)
begin
  var returnCSS: array of string = [".ais-SearchBox__root { display: inline-block; position: relative; width: 100%; height: 46px; white-space: nowrap; box-sizing: border-box; font-size: 14px; }",".ais-SearchBox__input, .ais-SearchBox__wrapper { width: 100%; height: 100%; }",".ais-SearchBox__input { -moz-appearance: none; display: inline-block; transition: box-shadow 0.4s ease, background 0.4s ease; -moz-transition: box-shadow 0.4s ease, background 0.4s ease; background-color: rgb(248, 248, 248); color: rgb(107, 106, 106); box-shadow: rgba(85, 95, 110, 0.2) 0px 1px 1px 0px; padding: 0px 36px 0px 46px; vertical-align: middle; white-space: normal; box-sizing: border-box; border: 2px solid rgb(114, 119, 238); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; font-size: 16px; background-position: initial initial; background-repeat: initial initial; }",".ais-SearchBox__input:active, .ais-SearchBox__input:focus, .ais-SearchBox__input:hover { box-shadow: none; outline: 0px; width: 100%; }",".ais-SearchBox__submit { position: absolute; top: 0px; right: inherit; left: 0px; margin: 0px; border: 0px; border-top-left-radius: 4px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 4px; background-color: rgba(255, 255, 255, 0); padding: 0px; width: 46px; height: 100%; vertical-align: middle; text-align: center; font-size: inherit; -moz-user-select: none; }",".ais-SearchBox__submit::before { display: inline-block; margin-right: -4px; height: 100%; vertical-align: middle; content: '' }",".ais-SearchBox__submit:active, .ais-SearchBox__submit:hover { cursor: pointer; }",".ais-SearchBox__submit:focus { outline: 0px; }",".ais-SearchBox__submit svg { width: 18px; height: 18px; vertical-align: middle; fill: rgb(191, 199, 216); }",".ais-SearchBox__reset { display: none; position: absolute; top: 13px; right: 13px; margin: 0px; border: 0px; background-image: none; cursor: pointer; padding: 0px; font-size: inherit; -moz-user-select: none; fill: rgb(191, 199, 216); background-position: initial initial; background-repeat: initial initial; }",".ais-SearchBox__reset:focus { outline: 0px; }",".ais-SearchBox__reset svg { display: block; margin: 4px; width: 12px; height: 12px; }",".ais-SearchBox__input:valid ~ .ais-SearchBox__reset { display: block; -moz-animation: a 0.25s; }"];

  for var i:= returnCSS.low to returnCSS.high do
  begin
  try
    document.styleSheets[0].insertRule( returnCSS[i], i);
  except
    on E : Exception do
      console.log(E.Message);
    end;
  end;

end;

initialization
  InsertCSS;

end.

 
Basic example

var
Search1: TSearch;

Search1 := TSearch.Create(Self);
Search1.OnKeyUp := procedure(Sender: TObject; aKeyCode: Integer)
begin
WriteLn( Search1.text );
end;


  • Czar likes this

#2 Czar

Czar
  • Members
  • 153 posts

Posted 05 September 2017 - 07:15 AM

Looks nice, works well, but I am unsure what to do with it. Is it supposed to return search results from the net? Sorry, I haven't dissected the code much but the simple example seemed to return nothing and instead restarts the page.

#3 Laksekjønn

Laksekjønn
  • Members
  • 440 posts

Posted 05 September 2017 - 02:46 PM

see the console output...

yQmU8Y.gif
This prototype demonstrates: inline SVG and CSS injected in the component.

It is possible to load Ajax JSON content from a backend server, of course:
https://rawgit.com/s...ww/preview.html
(Just type a city there's web service is enabled and see the smooth effects)
  • ielite and Nico Wouterse like this




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users