michael пре 7 година
родитељ
комит
d04b6d44ea

+ 48 - 0
demo/router/README.md

@@ -0,0 +1,48 @@
+### 2 Simple demos for the webrouter unit
+
+The 2 demos do the same, the difference is in how they achieve the same result:
+
+demorouter is the simplest. It registers 5 static routes, one for each form.
+
+demorouter2 is more advanced. It registers 1 route with a parameter.
+
+
+### Compiling for running in the browser:
+
+```
+pas2js -browser -Jc -Jirtl.js demorouter.pas
+pas2js -browser -Jc -Jirtl.js demorouter2.pas
+``` 
+
+When using lazarus, you can also open the respective .lpi files,
+and compile your project.
+
+### Choosing a history model:
+The router supports 3 models
+- Abstract (only for testing purposes)
+- Hash: the history is created by adding the route in the #hash part of te URL
+- HTML5: the history is created by using the window.history.pushState() API of the browser.
+  Most modern browsers support this, but it requires server-side support to work safely.
+
+When in doubt, use the hash mechanism :
+```
+Router.InitHistory(hkHash)  
+```
+
+### Server support.
+If the history mechanism has set the url to e.g. http://localhost:3000/Form3
+and the user returns back to this URL, the server needs to know it should serve the demorouter.html file;
+it needs to be configured that it serves the 'main page' of the project
+if it encounters an URL that it doesn't know.
+
+You can start a small node server that does this:
+
+for demorouter.html:
+```
+nodejs histsrv.js
+```
+
+for demorouter2.html:
+```
+nodejs histsrv2.js
+```

+ 15 - 0
demo/router/demorouter.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Router demo</title>
+    <meta charset="utf-8"/>
+    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
+    <script type="application/javascript" src="demorouter.js"></script>
+  </head>
+  <body>
+    <script type="application/javascript">
+     rtl.run();
+    </script>
+  </body>
+</html>
+

+ 82 - 0
demo/router/demorouter.lpi

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="demorouter"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default"/>
+      </Modes>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="pas2js_rtl"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="4">
+      <Unit0>
+        <Filename Value="demorouter.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="webrouter.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="webscroll.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="frmdemo.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="demorouter"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Other>
+      <ExecuteBefore>
+        <Command Value="$MakeExe(pas2js) -O- -Tbrowser -Jirtl.js -Jc $Name($(ProjFile))"/>
+        <ScanForFPCMsgs Value="True"/>
+      </ExecuteBefore>
+    </Other>
+    <CompileReasons Compile="False" Build="False" Run="False"/>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 36 - 0
demo/router/demorouter.pas

@@ -0,0 +1,36 @@
+program demorouter;
+{$mode objfpc}
+{$H+}
+
+uses web, classes, js, sysutils, webrouter, frmdemo;
+
+Procedure ShowForm (URl : String; aRoute : TRoute; Params: TStrings);
+
+Var
+  s : string;
+
+begin
+  document.body.innerHTML:='';
+  S:=aRoute.URLPattern;
+  if (Copy(S,Length(S),1)='/') then
+    S:=Copy(S,1,Length(S)-1);
+  Delete(S,1,4);
+  TDemoForm.Create(StrToIntDef(S,1));
+end;
+
+begin
+  // Leave this if you want to use the hash history.
+  // This will work in all cases.
+  Router.InitHistory(hkHash);
+  // Uncomment this if you want to use the HTML5 pushstate history mechanism.
+  // Note that you must server the files from a webserver then.
+  // See also the histsrv.js node server which will "correctly" serve all files.
+  // Router.InitHistory(hkHTML5,'http://localhost:3000/');
+  Router.RegisterRoute('form1',@ShowForm,True);
+  Router.RegisterRoute('form2',@ShowForm,False);
+  Router.RegisterRoute('form3',@ShowForm,False);
+  Router.RegisterRoute('form4',@ShowForm,False);
+  Router.RegisterRoute('form5',@ShowForm,False);
+  Router.Push('form1');
+end.
+

+ 15 - 0
demo/router/demorouter2.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Router 2 demo : route parameters</title>
+    <meta charset="utf-8"/>
+    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
+    <script type="application/javascript" src="demorouter2.js"></script>
+  </head>
+  <body>
+    <script type="application/javascript">
+     rtl.run();
+    </script>
+  </body>
+</html>
+

+ 78 - 0
demo/router/demorouter2.lpi

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="demorouter2"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default"/>
+      </Modes>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="pas2js_rtl"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="demorouter2.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="webscroll.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="frmdemo.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="demorouter2"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Other>
+      <ExecuteBefore>
+        <Command Value="$MakeExe(pas2js) -O- -Tbrowser -Jirtl.js -Jc $Name($(ProjFile))"/>
+        <ScanForFPCMsgs Value="True"/>
+      </ExecuteBefore>
+    </Other>
+    <CompileReasons Compile="False" Build="False" Run="False"/>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 28 - 0
demo/router/demorouter2.pas

@@ -0,0 +1,28 @@
+program demorouter2;
+
+{$mode objfpc}
+{$H+}
+
+uses web, classes, js, sysutils, webrouter, frmdemo;
+
+Procedure ShowForm (URl : String; aRoute : TRoute; Params: TStrings);
+
+Var
+  s : string;
+
+begin
+  S:=Params.Values['ID'];
+  document.body.innerHTML:='';
+  TDemoForm.Create(StrToIntDef(S,1),True);
+end;
+
+begin
+  // Leave this if you want to use the #hash history mechanism.
+  // This will work in all cases.
+  Router.InitHistory(hkHash);
+  // Uncomment this if you want to use HTML5 history.
+  // Router.InitHistory(hkHTML5,'http://localhost:3000/');
+  Router.RegisterRoute('form/:ID',@ShowForm,True);
+  Router.Push('form/1');
+end.
+

+ 102 - 0
demo/router/frmdemo.pp

@@ -0,0 +1,102 @@
+unit frmdemo;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  sysutils, classes, js, web, webrouter;
+
+Type
+
+  { TDemoForm }
+
+  TDemoForm = Class
+    Panel,
+    PanelContent,
+    labelContent : TJSElement;
+    function DismissAlert(Event: TJSMouseEvent): boolean;
+    function ButtonClick(Event: TJSMouseEvent): boolean;
+    constructor Create(aFormNo : Integer; UseSlash : Boolean = False);
+  private
+    function DoLinkClick(aEvent: TJSMouseEvent): boolean;
+  end;
+
+
+implementation
+
+
+function TDemoForm.DismissAlert(Event: TJSMouseEvent): boolean;
+begin
+  PanelContent.removeChild(labelContent);
+  Result:=true;
+end;
+
+function TDemoForm.ButtonClick(Event: TJSMouseEvent): boolean;
+begin
+  Router.Push(Event.target['data']);
+end;
+
+constructor TDemoForm.Create(aFormNo: Integer; UseSlash: Boolean);
+
+Var
+  adiv, Link, Button : TJSHTMLElement;
+  i : integer;
+
+  Function MakeLink(aID : integer; ForURL : Boolean) : String;
+
+  begin
+    Result:='/form';
+    if forURL and (Router.HistoryKind=hkHash) then
+      Result:='#'+Result;
+    if useSlash then
+      Result:=Result+'/';
+    Result:=Result+IntToStr(aID);
+  end;
+
+begin
+  Panel:=document.createElement('div');
+  // attrs are default array property...
+  Panel['class']:='panel panel-default';
+  PanelContent:=document.createElement('div');
+  PanelContent['class']:='panel-body';
+  labelContent:=document.createElement('div');
+  labelContent.innerHTML:='Hello from form '+IntToStr(aFormNo);
+  labelContent['role']:='alert';
+  labelContent['class']:='alert alert-info';
+  TJSHTMLElement(labelContent).onclick:=@DismissAlert;
+  aDiv:=TJSHTMLElement(document.createElement('div'));
+  aDiv['style']:='padding: 0px 0px 10px 0px;';
+  PanelContent.appendChild(adiv);
+  For I:=1 to 5 do
+    if (I<>aFormNo) then
+      begin
+      Link:=TJSHTMLElement(document.createElement('a'));
+      link['href']:=MakeLink(i,True);
+      link.innerHTML:='Go to form <span class="badge">'+IntToStr(i)+'</span>';
+      if (Router.HistoryKind=hkHTML5) then
+        Link.onclick:=@DoLinkClick;
+      adiv.appendChild(link);
+      end;
+  PanelContent.appendChild(labelContent);
+  For I:=1 to 5 do
+    if (I<>aFormNo) then
+      begin
+      Button:=TJSHTMLElement(document.createElement('button'));
+      Button['class']:='btn btn-default';
+      Button.InnerHTML:='Go to form '+IntToStr(i);
+      Button['data']:=MakeLink(i,false);
+      Button.onclick:=@ButtonClick;
+      PanelContent.appendChild(Button);
+      end;
+  document.body.appendChild(Panel);
+  Panel.appendChild(PanelContent);
+end;
+
+function TDemoForm.DoLinkClick(aEvent: TJSMouseEvent): boolean;
+begin
+  Router.Push(aEvent.target['href']);
+end;
+
+end.
+

+ 23 - 0
demo/router/histsrv.js

@@ -0,0 +1,23 @@
+const http = require('http')
+const fs = require('fs')
+const httpPort = 3000
+
+http.createServer((req, res) => {
+//    console.log(req);
+    console.log('Serving file.','.'+req.url);
+    var fn =  fs.existsSync('.'+req.url) ? '.'+req.url : "demorouter.html";
+    console.log('Actually Serving file.',fn);
+    fs.readFile(fn, 'utf-8', (err, content) => {
+    if (err) {
+      console.log('We cannot open "'+fn+'" file.')
+    }
+
+    res.writeHead(200, {
+      'Content-Type': 'text/html; charset=utf-8'
+    })
+
+    res.end(content)
+  })
+}).listen(httpPort, () => {
+  console.log('Server listening on: http://localhost:%s', httpPort)
+})

+ 23 - 0
demo/router/histsrv2.js

@@ -0,0 +1,23 @@
+const http = require('http')
+const fs = require('fs')
+const httpPort = 3000
+
+http.createServer((req, res) => {
+//    console.log(req);
+    console.log('Serving file.','.'+req.url);
+    var fn =  fs.existsSync('.'+req.url) ? '.'+req.url : "demorouter2.html";
+    console.log('Actually Serving file.',fn);
+    fs.readFile(fn, 'utf-8', (err, content) => {
+    if (err) {
+      console.log('We cannot open "'+fn+'" file.')
+    }
+
+    res.writeHead(200, {
+      'Content-Type': 'text/html; charset=utf-8'
+    })
+
+    res.end(content)
+  })
+}).listen(httpPort, () => {
+  console.log('Server listening on: http://localhost:%s', httpPort)
+})