Jump to content
Sign in to follow this  
Laksekjønn

SearchBar component prototype

Recommended Posts

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;

 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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/smartpascal/smartms/master/games/SearchBar/www/preview.html

(Just type a city there's web service is enabled and see the smooth effects)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×