Jump to content

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;

 

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)

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...