### Example: Adding Multiple Users with IDomUserCommand
Source: https://github.com/wai818/mormot-learning/blob/master/24_领域驱动设计.html
This Delphi code demonstrates how to use the `IDomUserCommand` interface to add a batch of new `TUser` records. It illustrates resolving the command service via IoC, populating user data within a loop, calling `cmd.Add` for each user, and finally invoking `cmd.Commit` to persist all changes in a single transaction. Error handling is included.
```Delphi
var cmd: IDomUserCommand;
user: TUser;
itext: RawUTF8;
...
aServer.Services.Resolve(IDomUserCommand,cmd);
user := TUser.Create;
try
for i := 1 to MAX do begin
UInt32ToUtf8(i,itext);
user.LogonName := ' '+itext;
user.EmailValidated := evValidated;
user.Name.Last := 'Last'+itext;
user.Name.First := 'First'+itext;
user.Address.Street1 := 'Street '+itext;
user.Address.Country.Alpha2 := 'fr';
user.Phone1 := itext;
if cmd.Add(user)<>cqrsSuccess then
raise EMyApplicationException.CreateFmt('Invalid data: %s',[cmd.GetLastErrorInfo]);
end;
// here nothing is actually written to the database
if cmd.Commit<>cqrsSuccess then
raise EMyApplicationException.CreateFmt('Commit error: %s',[cmd.GetLastErrorInfo]);
// here everything has been written to the database
finally
user.Free;
end;
```
--------------------------------
### SmartPascal Client-Side TSQLRecordPeople Instantiation Example
Source: https://github.com/wai818/mormot-learning/blob/master/17_跨平台客户端.html
An example demonstrating the instantiation of the `TSQLRecordPeople` class on the client-side using SmartPascal. This illustrates how the generated client-side ORM classes can be used to interact with remote data via standard CRUD operations, as shown in the `SQLite3\Samples\29 - SmartMobileStudio Client` example.
```SmartPascal
people := new TSQLRecordPeople;
```
--------------------------------
### OpenAIModel Class Constructor
Source: https://github.com/wai818/mormot-learning/blob/master/2_架构原理.html
This snippet defines the `__init__` method for the `OpenAIModel` class, outlining the `model_name` and `provider` parameters. It's crucial for configuring the specific OpenAI model and service provider to be used.
```APIDOC
OpenAIModel:
__init__(model_name: str, provider: str = 'openai')
model_name: The name of the OpenAI model to use
provider: The provider to use (defaults to 'openai')
```
--------------------------------
### Delphi: Example of Method to be Stubbed with Custom Delegate
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
Presents a simple Subtract method from TServiceCalculator as an example of a function that could be stubbed using a custom delegate or event callback. This approach allows defining complex behavior for a method without implementing the full class.
```Delphi
function TServiceCalculator.Subtract(n1, n2: double): double;
begin
result := n1-n2;
end;
```
--------------------------------
### Global CSS Styles for Responsive Layout and UI Elements
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
This CSS snippet defines global styles for a responsive web layout, including `container-fluid` and `col` classes for a grid system with media queries for different breakpoints (md, xl). It also includes utility classes for padding, display, and positioning, as well as specific styles for a sticky table of contents (`bd-toc`), a floating action button (`#floating-button`), and a modal image viewer (`.modal-box`). Keyframe animations for highlighting (`flash`) and zooming (`zoom`) are also present.
```CSS
/* STYLE_GLOBAL_PLACE_HOLDER */ *, *::before, *::after { box-sizing: border-box; } .container-fluid { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .col, .col-1, .col-10, .col-11, .col-12, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-auto, .col-lg, .col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-auto, .col-md, .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-auto, .col-sm, .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-auto, .col-xl, .col-xl-1, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-auto { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%;
```
--------------------------------
### Incorrect: Querying Data with Direct SQL and TSQLTableJSON
Source: https://github.com/wai818/mormot-learning/blob/master/6_日常的ORM.html
Shows an example of querying data by executing a direct SQL `SELECT` statement and then manually parsing the results using `TSQLTableJSON` and iterating through fields. While `TSQLTableJSON` simplifies parsing, the direct SQL query is not the most ORM-friendly approach.
```Delphi
procedure TMyClient.FillDrives(aList: TStrings);
var
table: TSQLTableJSON;
X, FieldIndex: Integer;
begin
table := TSQLRestClientDB(GlobalClient).ExecuteList([TSQLDrives], 'SELECT * FROM drives');
if (table <> nil) then
try
FieldIndex := table.FieldIndex('drive');
if (FieldIndex >= 0) then
for X := 1 to table.RowCount do
Items.Add(UTF8ToString(table.GetU(X, FieldIndex)));
finally
table.Free;
end;
end;
```
--------------------------------
### Correct: Querying Data with ORM using CreateAndFillPrepare
Source: https://github.com/wai818/mormot-learning/blob/master/6_日常的ORM.html
Demonstrates an ORM-centric way to fill a list with data using `TSQLDrives.CreateAndFillPrepare` and `FillOne` in a loop. This method abstracts SQL operations, providing a more robust and easier-to-understand approach, even if it might not be the absolute fastest due to abstraction.
```Delphi
procedure TMyClient.FillDrives(aList: TStrings);
begin
aList.BeginUpdate;
try
aList.Clear;
with TSQLDrives.CreateAndFillPrepare(GlobalClient,'') do
try
while FillOne do
aList.Add(UTF8ToString(Drive));
finally
Free;
end;
finally
aList.EndUpdate;
end;
end;
```
--------------------------------
### Atomic Integer Operations with TSynLocker's Internal Cache in Delphi
Source: https://github.com/wai818/mormot-learning/blob/master/4_SynCommons单元.html
This example illustrates how a class inheriting from TSynPersistentLocked can leverage TSynLocker's internal padded buffer for thread-safe data storage. It demonstrates using fSafe.LockedInt64[0] to read and fSafe.LockedInt64Increment(0,1) for atomic increment of an integer field, ensuring data integrity in multi-threaded environments.
```Delphi
type
TMyClass = class(TSynPersistentLocked)
public
procedure UseInternalIncrement;
function FieldValue: integer;
end;
{ TMyClass }
function TMyClass.FieldValue: integer;
begin // value read will also be protected by the mutex
result := fSafe.LockedInt64[0];
end;
procedure TMyClass.UseInternalIncrement;
begin // this dedicated method will ensure an atomic increase
fSafe.LockedInt64Increment(0,1);
end;
```
--------------------------------
### IDomUserCommand Methods and Two-Phase Commit Pattern
Source: https://github.com/wai818/mormot-learning/blob/master/24_领域驱动设计.html
This section outlines the core methods of `IDomUserCommand` and explains the two-phase commit pattern. It details how changes are prepared and validated before being explicitly committed to the persistent storage, ensuring data integrity and allowing for external service calls before final persistence.
```APIDOC
IDomUserCommand:
Commit: The main method for two-phase commit. Nothing is actually written to persistent storage until this method is called.
Add(const aAggregate: TUser): TCQRSResult: Adds a new TUser aggregate.
Update(const aUpdatedAggregate: TUser): TCQRSResult: Updates an existing TUser aggregate.
Delete: TCQRSResult: Deletes the currently selected TUser aggregate.
DeleteAll: TCQRSResult: Deletes all selected TUser aggregates.
Rollback: TCQRSResult: Rolls back any pending changes.
Typical Workflow for Modifying Existing Records:
1. Call an IDomUserQuery.Select* method (e.g., SelectByLogonName) to define the data scope.
2. Call an IDomUserCommand method (e.g., Update) to prepare the modification.
3. Call IDomUserCommand.Commit to persist the changes to the database.
```
--------------------------------
### Initialize Dynamic Outline Panel on Page Load in JavaScript
Source: https://github.com/wai818/mormot-learning/blob/master/23_非对称加密.html
This event listener executes when the page finishes loading. It initializes the outline panel and floating container visibility, fetches all heading elements (h1-h6) from the `post-content` area, builds the table of contents (TOC) data, and then renders the TOC as an HTML tree within the outline panel. If no headings are found, the panel is hidden.
```JavaScript
window.addEventListener('load', function() { var outlinePanel = document.getElementById('outline-panel'); outlinePanel.style.display = 'initial'; var floatingContainer = document.getElementById('container-floating'); floatingContainer.style.display = 'initial'; var outlineContent = document.getElementById('outline-content'); var postContent = document.getElementById('post-content');
// Fetch the outline.
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6"); toc = []; for (var i = 0; i < headers.length; ++i) { var header = headers[i]; toc.push({ level: parseInt(header.tagName.substr(1)), anchor: header.id, title: escapeHtml(header.textContent) }); } if (toc.length == 0) { setOutlinePanelVisible(false); setVisible(floatingContainer, false); return; } var baseLevel = baseLevelOfToc(toc); var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel); outlineContent.innerHTML = tocTree; setOutlinePanelVisible(true); setVisible(floatingContainer, true); });
```
--------------------------------
### Declare a Delphi Interface (ICalculator)
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
This Delphi code snippet demonstrates how to declare an interface, `ICalculator`, which defines a contract for functionality without providing an implementation. It inherits from `IInvokable` and includes a GUID for unique identification. The interface declares a single abstract method, `Add`, for adding two integers, adhering to common Delphi interface conventions like 'I' prefixing and method-only definitions.
```Delphi
type
ICalculator = interface(IInvokable)
['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
/// add two signed 32-bit integers
function Add(n1,n2: integer): integer;
end;
```
--------------------------------
### Delphi Simplified Stub and Mock Creation
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
After interfaces are registered, this snippet shows how `TInterfaceStub.Create` and `TInterfaceMock.Create` can be used directly with the interface name, simplifying the syntax by omitting `TypeInfo()`.
```Delphi
TInterfaceStub.Create(ISmsSender,SmsSender);
TInterfaceMock.Create(IUserRepository,UserRepository,self);
```
--------------------------------
### Calculate Base Level and Perfect Table of Contents Hierarchy in JavaScript
Source: https://github.com/wai818/mormot-learning/blob/master/23_非对称加密.html
The `baseLevelOfToc` function determines the highest (smallest number) heading level present in the TOC data, serving as the starting point for hierarchy. `toPerfectToc` then adjusts the TOC structure by inserting 'empty' headers to ensure a strictly incremental level progression (e.g., h1 followed by h3 becomes h1, [EMPTY h2], h3), which is necessary for correct tree generation.
```JavaScript
var baseLevelOfToc = function(p_toc) { var level = -1; for (i in p_toc) { if (level == -1) { level = p_toc[i].level; } else if (level > p_toc[i].level) { level = p_toc[i].level; } } if (level == -1) { level = 1; } return level; };
var toPerfectToc = function(p_toc, p_baseLevel) { var i; var curLevel = p_baseLevel - 1; var perfToc = []; for (i in p_toc) { var item = p_toc[i]; while (item.level > curLevel + 1) { curLevel += 1; var tmp = { level: curLevel, anchor: '', title: '[EMPTY]' }; perfToc.push(tmp); } perfToc.push(item); curLevel = item.level; } return perfToc; };
```
--------------------------------
### Responsive Layout and UI Component Styling with CSS
Source: https://github.com/wai818/mormot-learning/blob/master/2_架构原理.html
This snippet provides a comprehensive set of CSS rules for building responsive web interfaces. It includes a Bootstrap-like grid system with `col` and `row` classes, responsive breakpoints for different screen sizes (md, xl), utility classes for padding, display, and flexbox behavior, and specific styles for UI elements like a sticky table of contents, a floating action button, and a modal for image display with zoom animation.
```CSS
/* STYLE_GLOBAL_PLACE_HOLDER */ *, *::before, *::after { box-sizing: border-box; } .container-fluid { width: 100%; padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .col, .col-1, .col-10, .col-11, .col-12, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-auto, .col-lg, .col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-auto, .col-md, .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-auto, .col-sm, .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-auto, .col-xl, .col-xl-1, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-auto { position: relative; width: 100%; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col-12 { -webkit-box-flex: 0; -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } @media (min-width: 768px) { .col-md-3 { -webkit-box-flex: 0; -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } } @media (min-width: 768px) { .col-md-9 { -webkit-box-flex: 0; -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } } @media (min-width: 1200px) { .col-xl-2 { -webkit-box-flex: 0; -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } } @media (min-width: 1200px) { .col-xl-10 { -webkit-box-flex: 0; -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } } @media (min-width: 768px) { .pt-md-3, .py-md-3 { padding-top: 1rem!important; } } @media (min-width: 768px) { .pb-md-3, .py-md-3 { padding-bottom: 1rem!important; } } @media (min-width: 768px) { .pl-md-5, .px-md-5 { padding-left: 3rem!important; } } .d-none { display: none!important; } @media (min-width: 1200px) { .d-xl-block { display: block!important; } } @media (min-width: 768px) { .d-md-block { display: block!important; } } .bd-content { -webkit-box-ordinal-group: 1; -ms-flex-order: 0; order: 0; } .bd-toc { position: -webkit-sticky; position: sticky; top: 4rem; height: calc(100vh - 10rem); overflow-y: auto; } .bd-toc { -webkit-box-ordinal-group: 2; -ms-flex-order: 1; order: 1; padding-top: 1.5rem; padding-bottom: 1.5rem; font-size: .875rem; } .section-nav { padding-left: 0; } .section-nav ul { font-size: .875rem; list-style-type: none; } .section-nav li { font-size: .875rem; } .section-nav a { color: inherit !important; } .row { display: -webkit-box; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -15px; margin-left: -15px; } @media (min-width: 1200px) { .flex-xl-nowrap { flex-wrap: nowrap !important; } } #floating-button { width: 2.5rem; height: 2.5rem; border-radius: 50%; background: #00897B; position: fixed; top: .5rem; right: .5rem; cursor: pointer; box-shadow: 0px 2px 5px #666; } #floating-button .more { color: #F5F5F5; position: absolute; top: 0; display: block; bottom: 0; left: 0; right: 0; text-align: center; padding: 0; margin: 0; line-height: 2.5rem; font-size: 2rem; font-family: 'monospace'; font-weight: 300; } .hide-none { display: none !important; } .col-expand { -webkit-box-flex: 0; -ms-flex: 0 0 100% !important; flex: 0 0 100% !important; max-width: 100% !important; padding-right: 3rem !important; } .outline-bold { font-weight: bolder !important; } @media print { #floating-button { display: none !important; } } @keyframes flash { 0% { color: rgb(128, 203, 196); } 10% { color: rgb(0, 137, 123); } 40% { color: rgb(0, 137, 123); } 50% { color: rgb(128, 203, 196); } 60% { color: rgb(0, 137, 123); } 90% { color: rgb(0, 137, 123); } } .highlighted-anchor { animation: flash 1s; } div.mark-rect { background: transparent; border: 5px solid rgb(87, 104, 196); border-radius: 2px; position: absolute; } #vnote-footer { width: 100%; text-align: center; opacity: 0.2; margin-top: 3rem; } #vnote-footer p { font-size: 0.8rem; } #vnote-footer a { color: inherit !important; } x-eqs { display: flex; flex-direction: row; align-content: space-between; align-items: center; } x-eqs > x-eqn { width: 100%; margin-left: 3rem; } x-eqs > span { text-align: right; } .view-image, .view-svg { transition: 0.3s; } .modal-box { display: none; position: fixed; z-index: 1000; padding-top: 50px; left: 0px; top: 0px; width: 100%; height: 100%; overflow: hidden; background-color: rgba(68, 68, 68, 0.952941); } .modal-content { margin: auto; display: block; width: auto; height: auto; cursor: move; } .modal-content { animation-name: zoom; animation-duration: 0.6s; } @-webkit-keyframes zoom { 0% { transform: scale(0); } 100% { transform: scale(1); } } @keyframes zoom { 0% { transform: scale(0); } 100% { transform: scale(1); } } span.modal-close { position: absolute; z-index: 1000; top: 15px; right: 35px; color: rgb(218, 218, 218); font-size: 40px; font-weight: bold; transitio
```
--------------------------------
### APIDOC: mORMot Mocking Framework Capabilities Overview
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
A comprehensive overview of the features provided by the mORMot mocking framework, detailing its capabilities for stubbing, mocking, and testing, including support for various argument matchers, return value handling, and performance considerations.
```APIDOC
- Stubbing any method to return default values.
- Defining stubbed behavior via a fluent interface using TInterfaceStub.Returns(), including simple definition of returned values for the entire method or subsequent parameter matchers.
- Handling var, out method or function results, not just function results (unlike other Delphi implementations limited by TVirtualInterface), but all output values, including arrays of values.
- Stubbed methods can run more complex processes using delegates or event callbacks defined by TInterfaceStub.Executes() rules, for the entire method or subsequent parameter matchers.
- Stubbed methods can also raise exceptions defined by TInterfaceStub.Raises() rules, for the entire method or subsequent parameter matchers, if this is the behavior to test.
- Clear distinction between mocks and stubs with two dedicated classes: TInterfaceStub and TInterfaceMock.
- Mocks directly associated with mORMot's unified testing/test-driven classes.
- Mocked methods can define triggering test case failures using TInterfaceMock.Fails(), including for the entire method or subsequent parameter matchers.
- Choice of testing patterns: "expect-run-verify" or "run-verify" (aka "spy"), depending on testing needs.
- Mocking methods or methods with parameter matching for validating effective execution counts or global execution tracing, where output counts can be compared with < <= = <> > >= operators, not just classic exact times and at least once verification.
- Most common parameters and results can be defined as simple constant arrays in Delphi code, or via providing JSON arrays (e.g., for more complex record values).
- Retrieving execution traces in an easy-to-read or write text format (instead of complex "fluent" interfaces, e.g., using When clauses).
- Automatic release of TInterfaceStub TInterfaceMock TInterfaceMockSpy generated instances when interfaces are no longer needed, minimizing typed code and avoiding potential memory leaks.
- Support for Delphi 6 to Delphi 10.3 Rio, as no generic-like syntactic sugar or RTTI.pas features are used.
- Very good performance (faster Delphi mocking framework) due to very low overhead and reuse of mORMot's underlying interface-based service kernel with JSON serialization, not relying on slow and limited TVirtualInterface.
```
--------------------------------
### Delphi Registering Service Interfaces for mORMot
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
This snippet demonstrates the recommended practice of registering service interfaces like `ISmsSender` and `IUserRepository` using `TInterfaceFactory.RegisterInterfaces`. This allows for simplified stub and mock creation without needing `TypeInfo()` later.
```Delphi
unit MyServiceInterfaces;
...
type
ISmsSender = interface(IInvokable)
...
IUserRepository = interface(IInvokable)
...
initialization
TInterfaceFactory.RegisterInterfaces(
[TypeInfo(ISmsSender),TypeInfo(IUserRepository)]);
end.
```
--------------------------------
### Page Load Event Listener for TOC Initialization
Source: https://github.com/wai818/mormot-learning/blob/master/11_客户端-服务端进程.html
This event listener executes when the page finishes loading. It initializes the outline panel, fetches all header elements (h1-h6) from the `post-content` area, processes them into a structured table of contents using helper functions, and then renders the TOC into the `outline-content` element. If no headers are found, the outline panel is hidden.
```JavaScript
window.addEventListener('load', function() {
var outlinePanel = document.getElementById('outline-panel');
outlinePanel.style.display = 'initial';
var floatingContainer = document.getElementById('container-floating');
floatingContainer.style.display = 'initial';
var outlineContent = document.getElementById('outline-content');
var postContent = document.getElementById('post-content');
// Fetch the outline.
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6");
toc = [];
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
toc.push({ level: parseInt(header.tagName.substr(1)), anchor: header.id, title: escapeHtml(header.textContent) });
}
if (toc.length == 0) {
setOutlinePanelVisible(false);
setVisible(floatingContainer, false);
return;
}
var baseLevel = baseLevelOfToc(toc);
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
outlineContent.innerHTML = tocTree;
setOutlinePanelVisible(true);
setVisible(floatingContainer, true);
});
```
--------------------------------
### JavaScript Document Load Handler for TOC Initialization
Source: https://github.com/wai818/mormot-learning/blob/master/9_外部NoSQL数据库访问.html
The main event listener that executes upon document load, responsible for fetching page headers, constructing the table of contents, and dynamically updating the UI to display the generated outline panel.
```JavaScript
var toc = [];
window.addEventListener('load', function() {
var outlinePanel = document.getElementById('outline-panel');
outlinePanel.style.display = 'initial';
var floatingContainer = document.getElementById('container-floating');
floatingContainer.style.display = 'initial';
var outlineContent = document.getElementById('outline-content');
var postContent = document.getElementById('post-content');
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6");
toc = [];
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
toc.push({ level: parseInt(header.tagName.substr(1)), anchor: header.id, title: escapeHtml(header.textContent) });
}
if (toc.length == 0) {
setOutlinePanelVisible(false);
setVisible(floatingContainer, false);
return;
}
var baseLevel = baseLevelOfToc(toc);
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
outlineContent.innerHTML = tocTree;
setOutlinePanelVisible(true);
setVisible(floatingContainer, true);
});
```
--------------------------------
### Initialize Table of Contents and UI on Page Load in JavaScript
Source: https://github.com/wai818/mormot-learning/blob/master/10_JSON RESTful客户端-服务端.html
This event listener executes when the page finishes loading. It initializes the outline panel and floating container visibility, fetches all heading elements (h1-h6) from the post content, constructs a table of contents (TOC) array, normalizes it, converts it to an HTML tree, and then displays the outline panel if TOC entries exist. It includes a nested helper function for HTML escaping.
```JavaScript
window.addEventListener('load', function() {
var outlinePanel = document.getElementById('outline-panel');
outlinePanel.style.display = 'initial';
var floatingContainer = document.getElementById('container-floating');
floatingContainer.style.display = 'initial';
var outlineContent = document.getElementById('outline-content');
var postContent = document.getElementById('post-content');
// Escape @text to Html.
var escapeHtml = function(text) {
var map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' };
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
// Fetch the outline.
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6");
toc = [];
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
toc.push({ level: parseInt(header.tagName.substr(1)), anchor: header.id, title: escapeHtml(header.textContent) });
}
if (toc.length == 0) {
setOutlinePanelVisible(false);
setVisible(floatingContainer, false);
return;
}
var baseLevel = baseLevelOfToc(toc);
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
outlineContent.innerHTML = tocTree;
setOutlinePanelVisible(true);
setVisible(floatingContainer, true);
});
```
--------------------------------
### CSS Styles for UI Elements and Syntax Highlighting
Source: https://github.com/wai818/mormot-learning/blob/master/9_外部NoSQL数据库访问.html
This snippet contains comprehensive CSS rules for styling various HTML elements, including diagram containers, image alignment, captions, scrollbars, and a custom theme for `highlight.js` syntax highlighting. It defines colors, padding, margins, and other visual properties to ensure consistent UI presentation.
```CSS
0px; overflow-y: hidden; }
div.flowchart-diagram { padding: 0px 5px; margin: 16px 0px; width: fit-content; overflow: hidden; }
div.wavedrom-diagram { padding: 0px 5px; margin: 16px 0px; width: fit-content; overflow: hidden; }
div.plantuml-diagram { padding: 5px 5px 0px; margin: 16px 0px; width: fit-content; overflow: hidden; }
.img-package { text-align: center; }
img.img-center { display: block; margin-left: auto; margin-right: auto; }
span.img-caption { min-width: 20%; max-width: 80%; display: inline-block; padding: 10px; margin: 0px auto; border-bottom: 1px solid rgb(192, 192, 192); color: rgb(108, 108, 108); text-align: center; line-height: 1.5; }
.emoji_zero, .emoji_one, .emoji_two, .emoji_three, .emoji_four, .emoji_five, .emoji_six, .emoji_seven, .emoji_eight, .emoji_nine { margin-left: 5px; margin-right: 8px; }
div.preview-hint { opacity: 0.5; margin-top: 30%; margin-bottom: 30%; align-items: center; display: flex; flex-direction: column; justify-content: center; }
table.hljs-ln tr { border: none; background-color: transparent; }
table.hljs-ln tr td { border: none; background-color: transparent; }
table.hljs-ln tr td.hljs-ln-numbers { user-select: none; text-align: center; color: rgb(170, 170, 170); border-right: 1px solid rgb(204, 204, 204); vertical-align: top; padding-right: 5px; white-space: nowrap; }
table.hljs-ln tr td.hljs-ln-code { padding-left: 10px; }
::-webkit-scrollbar { background-color: rgb(234, 234, 234); width: 14px; height: 14px; border: none; }
::-webkit-scrollbar-corner { background-color: rgb(234, 234, 234); }
::-webkit-scrollbar-button { height: 14px; width: 14px; background-color: rgb(234, 234, 234); }
::-webkit-scrollbar-button:hover { background-color: rgb(208, 208, 208); }
::-webkit-scrollbar-button:active { background-color: rgb(178, 178, 178); }
::-webkit-scrollbar-track { background-color: rgb(234, 234, 234); }
::-webkit-scrollbar-thumb { border: none; background-color: rgb(218, 218, 218); }
::-webkit-scrollbar-thumb:hover { background-color: rgb(208, 208, 208); }
::-webkit-scrollbar-thumb:active { background-color: rgb(178, 178, 178); }
::-webkit-scrollbar-button:horizontal:increment { background-image: url('data:image/svg+xml;utf8,'); background-repeat: no-repeat; background-size: contain; }
::-webkit-scrollbar-button:horizontal:decrement { background-image: url('data:image/svg+xml;utf8,'); background-repeat: no-repeat; background-size: contain; }
::-webkit-scrollbar-button:vertical:increment { background-image: url('data:image/svg+xml;utf8,'); background-repeat: no-repeat; background-size: contain; }
::-webkit-scrollbar-button:vertical:decrement { background-image: url('data:image/svg+xml;utf8,'); background-repeat: no-repeat; background-size: contain; }
::selection { background: rgb(25, 118, 210); color: rgb(238, 238, 238); }
.modal-box { background-color: rgba(234, 234, 234, 0.952941); }
span.modal-close { color: rgb(102, 102, 102); }
span.modal-close:hover, span.modal-close:focus { color: rgb(34, 34, 34); }
.hljs { display: block; overflow-x: auto; padding: 0.5em; background: rgb(224, 224, 224); }
.hljs, .hljs-subst { color: rgb(54, 54, 54); }
.hljs-comment { color: rgb(118, 118, 118); }
.hljs-keyword, .hljs-attribute, .hljs-selector-tag, .hljs-meta-keyword, .hljs-doctag, .hljs-name { color: rgb(0, 0, 238); }
.hljs-type, .hljs-string, .hljs-number, .hljs-selector-id, .hljs-selector-class, .hljs-quote, .hljs-template-tag, .hljs-deletion { color: rgb(136, 0, 0); }
.hljs-title, .hljs-section { color: rgb(136, 0, 0); font-weight: bold; }
.hljs-regexp, .hljs-symbol, .hljs-variable, .hljs-template-variable, .hljs-link, .hljs-selector-attr, .hljs-selector-pseudo { color: rgb(188, 96, 96); }
.hljs-literal { color: rgb(175, 0, 215); }
.hljs-built_in, .hljs-bullet, .hljs-code, .hljs-addition { color: rgb(0, 135, 0); }
.hljs-meta { color: rgb(31, 113, 153); }
.hljs-meta-string { color: rgb(77, 153, 191); }
.hljs-emphasis { font-style: italic; }
.hljs-stron
```
--------------------------------
### Initialize Dynamic Table of Contents on Window Load in JavaScript
Source: https://github.com/wai818/mormot-learning/blob/master/21_安全.html
This event listener executes when the window finishes loading. It initializes the outline panel and floating container, fetches all header elements (h1-h6) from the post content, constructs a Table of Contents (TOC) array, normalizes and converts it to an HTML tree, and then renders it into the outline panel.
```JavaScript
window.addEventListener('load', function() {
var outlinePanel = document.getElementById('outline-panel');
outlinePanel.style.display = 'initial';
var floatingContainer = document.getElementById('container-floating');
floatingContainer.style.display = 'initial';
var outlineContent = document.getElementById('outline-content');
var postContent = document.getElementById('post-content');
// Fetch the outline.
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6");
toc = [];
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
toc.push({ level: parseInt(header.tagName.substr(1)), anchor: header.id, title: escapeHtml(header.textContent) });
}
if (toc.length == 0) {
setOutlinePanelVisible(false);
setVisible(floatingContainer, false);
return;
}
var baseLevel = baseLevelOfToc(toc);
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
outlineContent.innerHTML = tocTree;
setOutlinePanelVisible(true);
setVisible(floatingContainer, true);
});
```
--------------------------------
### Initialize and Render Dynamic Table of Contents (TOC)
Source: https://github.com/wai818/mormot-learning/blob/master/7_数据库层.html
This script initializes the dynamic table of contents (TOC) by querying all header elements (h1-h6) within the 'post-content' area. It then processes these headers to build a structured TOC, handles cases where no headers are found, and finally renders the TOC into the 'outline-content' element, making the floating container visible.
```JavaScript
floatingContainer.style.display = 'initial';
var outlineContent = document.getElementById('outline-content');
var postContent = document.getElementById('post-content');
// Fetch the outline.
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6");
toc = [];
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
toc.push({
level: parseInt(header.tagName.substr(1)),
anchor: header.id,
title: escapeHtml(header.textContent)
});
}
if (toc.length == 0) {
setOutlinePanelVisible(false);
setVisible(floatingContainer, false);
return;
}
var baseLevel = baseLevelOfToc(toc);
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
outlineContent.innerHTML = tocTree;
setOutlinePanelVisible(true);
setVisible(floatingContainer, true);
});
```
--------------------------------
### Delphi Running a Test with Stubbed and Mocked Dependencies
Source: https://github.com/wai818/mormot-learning/blob/master/15_接口.html
This snippet shows how to instantiate the `TLoginController` with the previously defined stubbed `SmsSender` and mocked `UserRepository`. It then calls the `ForgotMyPassword` method, allowing the test to run against the fake implementations.
```Delphi
with TLoginController.Create(UserRepository,SmsSender) do
try
ForgotMyPassword('toto');
finally
Free;
end;
```
--------------------------------
### JavaScript DOM Initialization on Page Load
Source: https://github.com/wai818/mormot-learning/blob/master/7_数据库层.html
This snippet demonstrates how to execute JavaScript code once the entire page has loaded. It specifically targets and initializes the display style of an 'outline-panel' element and references a 'container-floating' element, ensuring UI components are correctly set up after the DOM is ready.
```JavaScript
window.addEventListener('load', function() {
var outlinePanel = document.getElementById('outline-panel');
outlinePanel.style.display = 'initial';
var floatingContainer = document.getElementById('container-floating');
});
```
--------------------------------
### JavaScript Page Load Initialization for TOC
Source: https://github.com/wai818/mormot-learning/blob/master/6_日常的ORM.html
This event listener executes when the page finishes loading. It initializes the outline panel and floating container visibility, fetches all heading elements (`h1`-`h6`) from the post content, constructs the Table of Contents (TOC) data, and then renders it into the outline panel, setting its initial visibility.
```JavaScript
window.addEventListener('load', function() {
var outlinePanel = document.getElementById('outline-panel');
outlinePanel.style.display = 'initial';
var floatingContainer = document.getElementById('container-floating');
floatingContainer.style.display = 'initial';
var outlineContent = document.getElementById('outline-content');
var postContent = document.getElementById('post-content');
var headers = postContent.querySelectorAll("h1, h2, h3, h4, h5, h6");
toc = [];
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
toc.push({ level: parseInt(header.tagName.substr(1)), anchor: header.id, title: escapeHtml(header.textContent) });
}
if (toc.length == 0) {
setOutlinePanelVisible(false);
setVisible(floatingContainer, false);
return;
}
var baseLevel = baseLevelOfToc(toc);
var tocTree = tocToTree(toPerfectToc(toc, baseLevel), baseLevel);
outlineContent.innerHTML = tocTree;
setOutlinePanelVisible(true);
setVisible(floatingContainer, true);
});
```