Mingcedar

Product: Mingcedar Studio DESIGNER

Geometry and advanced layout | Mingcedar Studio

Map input values to movement, rotation, and scale. Check limits, pivots, resize edges, and the boundary between declarative behaviors and page scripts.

Published Updated

<section id="preface" class="docs-block docs-block-intro"> <span class="section-kicker">Manual</span> <h2>Before Use</h2> <p>Map input values to movement, rotation, and scale. Check limits, pivots, resize edges, and the boundary between declarative behaviors and page scripts.</p> </section> <section id="move-core" class="docs-block"> <span class="section-kicker">Geometry</span> <h2>Move: input range and output displacement</h2> <p>Map a number to a horizontal or vertical offset from the original position, for sliders, level markers and indicators.</p> <div class="docs-detail-list"> <article id="move-core-item-1" class="docs-detail-row"> <strong>Overview</strong> <p>Move is a Geometry behavior for numeric single-axis motion. Use Rotate for angles and Scale for size changes.</p> </article><article id="move-core-item-2" class="docs-detail-row"> <strong>How to use it: every control in the editor</strong> <p>Move clamps Source value to Limit minimum / Limit maximum and maps that interval to At limit minimum / At limit maximum. The output is a canvas distance relative to the original component position. Source minimum / Source maximum are available as ValueMin / ValueMax aliases. Changing the source range alone does not update the input limits.</p> <ul> <li>Behavior name is editable; Component name is read-only.</li><li>Quality override / Override border by quality configures Good and Bad borders for data quality, separately from process limits.</li><li>JS functions... inserts a method into the focused expression field.</li><li>Source value returns a number, for example ReadTagDouble(&quot;PLC_LINE01.TANK01.LEVEL&quot;, 0). Condition returns a boolean; false skips the behavior and does not hide the component.</li><li>Source minimum / Source maximum default to 0 / 100 and supply the ValueMin / ValueMax expression aliases.</li><li>At limit minimum / At limit maximum specify movement offsets, initially 0 / 120 for a new Move behavior, at the input-limit endpoints. Capture calculates an endpoint from the component geometry.</li><li>Limit minimum / Limit maximum start as independent values 0 / 100 and control clamping and normalization. Enter ValueMin / ValueMax to follow the source range.</li><li>Move axis: Horizontal or Vertical. Hide outside input limits controls visibility on an out-of-range input.</li><li>Save / Ctrl+S validates and saves; Cancel / Esc discards the edit.</li> </ul> <pre class="docs-code-block"><code>// Source value

ReadTagDouble(&quot;PLC_LINE01.TANK01.LEVEL&quot;, 0)

// Source minimum / maximum: 0 / 100

// Limit minimum / maximum: ValueMin / ValueMax

// At limit minimum / maximum: 0 / -shape.height

// Move axis: Vertical</code></pre> </article><article id="move-core-item-3" class="docs-detail-row"> <strong>How the Capture buttons work</strong> <p>Capture beside At limit minimum / At limit maximum calculates the offset from the same component in PowerPoint. The editor records the original geometry, writes the difference between target and original coordinates, and then attempts to restore the original position.</p> <ul> <li>Choose Move axis first: Horizontal uses the Left difference and Vertical uses the Top difference.</li><li>Move the component to the desired endpoint, then use Capture beside that endpoint.</li><li>The offset uses 0.### formatting and can be replaced with a numeric expression.</li><li>The same component must remain selected. Unavailable original or current geometry produces an error.</li><li>If restoration fails, the saved offset remains; restore the component before continuing.</li> </ul> </article><article id="move-core-item-4" class="docs-detail-row"> <strong>When to use it</strong> <p>Use a measured value to drive linear motion, for example:</p> <ul> <li>Tank level: map the level percentage into a vertical offset so the liquid block floats up and down with the level</li><li>Slider / horizontal indicator: map a 0-100 value into a horizontal offset to produce slider or horizontal indicator bar motion</li> </ul> </article><article id="move-core-item-5" class="docs-detail-row"> <strong>Limitations and troubleshooting</strong> <p>Check these settings:</p> <ul> <li>Movement outputs use canvas distance. Use shape.width for one component width; 100 means 100 canvas units.</li><li>Limit minimum / Limit maximum controls the actual mapping, with out-of-range visibility controlled separately.</li><li>Check the movement axis before Capture to avoid recording the wrong coordinate difference.</li><li>After changing the source range, update input limits or enter ValueMin / ValueMax to follow it.</li> </ul> </article> </div> <div class="docs-note-grid"> <figure id="move-core-image-1" class="docs-note-card manual-doc-image-card"> <img src="/WEB_img/HQPPT/current/geometry/move.png" alt="Move behavior editor" loading="lazy" decoding="async"> <figcaption> <strong>Move editor</strong> <p>Set the source range, offset range, and axis to map a value proportionally into a single-axis offset.</p> </figcaption> </figure> </div> </section><section id="rotate-core" class="docs-block"> <span class="section-kicker">Geometry</span> <h2>Rotate: angles and pivot points</h2> <p>Rotate a component around a chosen pivot by an input angle, for pointers, valve plates and fan blades.</p> <div class="docs-detail-list"> <article id="rotate-core-item-1" class="docs-detail-row"> <strong>Overview</strong> <p>Drag Geometry → Rotate onto the component. It applies the supplied angle directly without percentage mapping.</p> </article><article id="rotate-core-item-2" class="docs-detail-row"> <strong>How to use it: every control in the editor</strong> <p>Rotation input returns an angle in degrees. Maximum angle defines a symmetric allowed range and PIVOT POINT sets the pivot. Rotate does not perform source-range percentage mapping.</p> <ul> <li>Behavior name is editable; Component name is read-only.</li><li>Override border by quality configures Good / Bad borders for data quality.</li><li>JS functions... inserts a method into the focused expression field.</li><li>Rotation input: an angle expression, such as ReadTagDouble(&quot;PLC_LINE01.VALVE01.ANGLE&quot;, 0).</li><li>Condition: a boolean; false skips rotation and does not hide the component.</li><li>Maximum angle defaults to 360. A value of 90 permits -90° to +90°. Preset buttons enter 45, 90, 180, 270, or 360.</li><li>PIVOT POINT: Center, Top, Bottom, Left, or Right, according to the mechanical pivot.</li><li>Hide outside angle range hides an out-of-range angle; otherwise the angle is clamped to the boundary.</li><li>Save / Ctrl+S validates and saves; Cancel / Esc discards the edit.</li> </ul> <pre class="docs-code-block"><code>// Rotation input

ReadTagDouble(&quot;PLC_LINE01.VALVE01.ANGLE&quot;, 0)

// Maximum angle: 90

// PIVOT POINT: Center</code></pre> </article><article id="rotate-core-item-3" class="docs-detail-row"> <strong>When to use it</strong> <p>Use it for angle-driven motion, for example:</p> <ul> <li>Gauge pointer: read the angle for the pressure/temperature value and turn the needle around its center</li><li>Valve angle: rotate the valve icon by its opening angle, with the pivot on the real stem center</li><li>Fan / mixer blade: rotate the blade by its running angle to show motion</li> </ul> </article><article id="rotate-core-item-4" class="docs-detail-row"> <strong>Limitations and troubleshooting</strong> <p>Check these limits:</p> <ul> <li>Rotation input uses degrees. Convert an opening percentage explicitly when the Tag is not an angle.</li><li>Match the pivot to the mechanical axis. Use Bottom for a bottom-hinged pointer and Center for a center-mounted component.</li><li>Angle presets only update Maximum angle, not Rotation input.</li><li>A false Condition only skips rotation. Use the hide option or a separate visibility behavior to control visibility.</li> </ul> </article> </div> <div class="docs-note-grid"> <figure id="rotate-core-image-1" class="docs-note-card manual-doc-image-card"> <img src="/WEB_img/HQPPT/current/geometry/rotate.png" alt="Rotate behavior editor" loading="lazy" decoding="async"> <figcaption> <strong>Rotate editor</strong> <p>Apply an angle value to the component so it turns around the chosen pivot, with a max-rotation limit.</p> </figcaption> </figure> </div> </section><section id="scale-core" class="docs-block"> <span class="section-kicker">Geometry</span> <h2>Scale: resize edges and limits</h2> <p>Map a numeric value to component size, for data bars, level fills and size indicators.</p> <div class="docs-detail-list"> <article id="scale-core-item-1" class="docs-detail-row"> <strong>Overview</strong> <p>Drag Geometry → Scale onto a component to drive its size from a number.</p> </article><article id="scale-core-item-2" class="docs-detail-row"> <strong>How to use it: every control in the editor</strong> <p>Scale clamps Source value to Limit minimum / Limit maximum and maps that interval to At limit minimum / At limit maximum. The output is a scale factor; 1 preserves the original size. Source minimum / Source maximum are available as ValueMin / ValueMax aliases. Changing the source range alone does not update the input limits.</p> <ul> <li>Behavior name is editable; Component name is read-only.</li><li>Quality override / Override border by quality configures Good and Bad borders for data quality, separately from process limits.</li><li>JS functions... inserts a method into the focused expression field.</li><li>Source value returns a number, for example ReadTagDouble(&quot;PLC_LINE01.TANK01.LEVEL&quot;, 0). Condition returns a boolean; false skips the behavior and does not hide the component.</li><li>Source minimum / Source maximum default to 0 / 100 and supply the ValueMin / ValueMax expression aliases.</li><li>At limit minimum / At limit maximum specify scale factors, initially 0.5 / 1.5 for a new Scale behavior (change them to 0 / 1 for the level-fill example), at the input-limit endpoints. Capture calculates an endpoint from the component geometry.</li><li>Limit minimum / Limit maximum start as independent values 0 / 100 and control clamping and normalization. Enter ValueMin / ValueMax to follow the source range.</li><li>Moving edge: Top moves the top edge and fixes the bottom; Right moves the right edge and fixes the left.</li><li>Save / Ctrl+S validates and saves; Cancel / Esc discards the edit.</li> </ul> <pre class="docs-code-block"><code>// Source value

ReadTagDouble(&quot;PLC_LINE01.TANK01.LEVEL&quot;, 0)

// Source minimum / maximum: 0 / 100

// Limit minimum / maximum: ValueMin / ValueMax

// At limit minimum / maximum: 0 / 1

// Moving edge: Top</code></pre> </article><article id="scale-core-item-3" class="docs-detail-row"> <strong>How the Capture buttons work</strong> <p>The editor records the original size. Resize the same component in PowerPoint and click Capture beside an endpoint. It calculates target size / original size using Moving edge, writes the factor and attempts to restore the original geometry.</p> <ul> <li>Choose Moving edge first, because it decides whether the calculation uses width or height and which edge defines the target size.</li><li>Top / Bottom use height: Top uses original bottom minus current top, and Bottom uses current bottom minus original top.</li><li>Left / Right use width: Left uses original right minus current left, and Right uses current right minus original left.</li><li>If the original width/height is zero, the target size would be negative, or the selected object is not the same component, Target warns and refuses to write.</li><li>Capture writes a 0.### factor. If you need a fixed expression instead, you can still overwrite At limit minimum / At limit maximum by hand.</li> </ul> </article><article id="scale-core-item-4" class="docs-detail-row"> <strong>When to use it</strong> <p>Use size to represent a value, for example:</p> <ul> <li>Level fill: a fill block inside a tank rises with the level percentage; set Moving edge to Top so the bottom stays fixed.</li><li>Bar growth: a throughput or load bar grows from one end with the value; set Moving edge to the edge it grows toward.</li><li>Icon response: an icon scales between At limit minimum and At limit maximum with a value as a strength indicator.</li> </ul> </article><article id="scale-core-item-5" class="docs-detail-row"> <strong>Limitations and troubleshooting</strong> <p>Check these Scale settings:</p> <ul> <li>Moving edge is the edge that moves, not the fixed one: choosing Top means the top edge moves and the bottom is fixed; Left means the left moves and the right is fixed. To keep an edge still, pick its opposite.</li><li>At limit minimum / At limit maximum are scale factors, not percentages: the original size is 1.0, not 100.</li><li>One Moving edge means one direction: if you pick Right, do not expect it to scale toward both sides; the fixed edge does not move.</li><li>Scale has no out-of-range hiding option. A false Condition only skips scaling; use Visibility in State Color or Script Color when the component must be hidden.</li><li>Recheck Limit minimum / Limit maximum when changing the input range, or use ValueMin / ValueMax to keep the effective range aligned with the source range.</li> </ul> </article> </div> <div class="docs-note-grid"> <figure id="scale-core-image-1" class="docs-note-card manual-doc-image-card"> <img src="/WEB_img/HQPPT/current/geometry/scale.png" alt="Scale behavior editor" loading="lazy" decoding="async"> <figcaption> <strong>Scale editor</strong> <p>Map a value into a scale factor and use Moving edge to choose which edge moves and which stays fixed.</p> </figcaption> </figure> </div> </section><section id="post-ops" class="docs-block"> <span class="section-kicker">Feature</span> <h2>Shared behavior options and script scope</h2> <p>Understand data-quality indicators, the behavior-specific meaning of Condition, and visibility options. Available controls depend on the behavior editor.</p> <div class="docs-detail-list"> <article id="post-ops-item-1" class="docs-detail-row"> <strong>Data quality and display state</strong> <p>Data quality indicates whether Tag data is valid; process states such as running, stopped and alarmed are separate. In Script Text, select Use quality outline colors under Quality Override and set Good and Bad colors. State Color provides Follow data quality (border / hide), with an option to hide on bad quality.</p> </article><article id="post-ops-item-2" class="docs-detail-row"> <strong>What Condition means</strong> <p>Condition has a different role in each behavior. Use the table and the corresponding editor to configure it.</p> </article><article id="post-ops-item-3" class="docs-detail-row"> <strong>Three visibility options</strong> <p></p> </article><article id="post-ops-item-4" class="docs-detail-row"> <strong>Expressions and verification</strong> <p>For example, enter the expression below in Script Text Condition to evaluate its text only when the specified Tag has good quality. Replace the example name with your project Tag and verify both good and bad quality. Configure the corresponding Quality Override when a persistent quality indication is required.</p> <ul> <li>Condition must return a Boolean immediately; do not use fetch, promises or timers.</li><li>Condition does not replace Mingcedar write permissions or equipment interlocks.</li><li>Move / Rotate / Scale currently have no separate Post Operations input.</li> </ul> <pre class="docs-code-block"><code>ReadTagQualityGood(&quot;PLC_LINE01.PUMP01.SPEED&quot;)</code></pre> </article><article id="post-ops-item-5" class="docs-detail-row"> <strong>Start with the five script locations</strong> <p>Code location determines scope, execution timing, and async/write permissions. Mingcedar Studio has no global script document spanning all pages.</p> <ul> <li>Page Script: belongs to the current page. Top-level var, let, const, class, and function declarations are available to animations and expressions on that page.</li><li>hqVisuDesignerPageReady(ctx): runs once after the page runtime is ready and suits component initialization; constants and helpers needed by the first animation evaluation still belong at Page Script top level.</li><li>Setup Script: prepares variables and intermediate results for one behavior only; it is not a page-global area.</li><li>Condition / Value / Display Text / Fill / Border / Visibility / Source value: synchronous expression slots that must immediately return one result.</li><li>Click / Hover / Press-Release Script: full event-driven script bodies. WriteTag is allowed only for a genuine Click, Press, or Release; Hover cannot write device data.</li> </ul> </article><article id="post-ops-item-6" class="docs-detail-row"> <strong>Recommended animation-script split</strong> <p>Keep shared Tag prefixes, ranges, and conversion functions in Page Script. Color and text behaviors that provide Setup Script can prepare local results there. Move, Rotate, and Scale have no Setup Script or Post Operations field. Put reads and conversions directly in Source value or Rotation input and reusable helpers in Page Script.</p> <pre class="docs-code-block"><code>// Current Page Script

const tankTagPrefix = &quot;PLC_LINE01.TANK01&quot;;

function percent(value, min, max) {

return Math.max(0, Math.min(100, (value - min) * 100 / (max - min)));

}

// Scale: Source value

percent(ReadTagDouble(tankTagPrefix + &quot;.LEVEL&quot;, 0), 0, 10)

// Source minimum / maximum: 0 / 100

// Limit minimum / maximum: 0 / 100

// At limit minimum / maximum: 0 / 1

// Moving edge: Top</code></pre> </article><article id="post-ops-item-7" class="docs-detail-row"> <strong>Synchronous, asynchronous, and write boundaries</strong> <p>Do not put fetch, Promise, setTimeout, or setInterval directly in an expression slot because animation evaluation needs an immediate result. Prepare asynchronous data in an async function in Page Script, hqVisuDesignerPageReady, Click Script, or Hover Script, then expose a page variable or host data source for the animation to read. await is valid only inside an async function; top-level await and import/export module syntax are unsupported. Device writes require a genuine user click, press, or release and remain subject to host permission, confirmation, reason, and audit controls.</p> </article><article id="post-ops-item-8" class="docs-detail-row"> <strong>Navigation parameters: supported content</strong> <p>In Open Link, select Internal page to enter values under Parameters (optional). For other Destinations, fill the fields for that target type. Scripted navigation passes parameters in the second hqVisuDesigner.openPage argument. Values may be strings, numbers, booleans, or null; the destination reads strings and reads null as an empty string.</p> <ul> <li>parameters must be an array whose entries have { key, value }.</li><li>The array preserves order and repeated keys. A plain object is not the formal openPage parameter shape.</li><li>frameTarget supports frame, fullscreen, and _blank; openInNewWindow: true is equivalent to _blank.</li><li>Use openPage within one package. Use openScreen(screenCode) across packages, but generic Jump Parameters are not guaranteed across a screen-package boundary.</li><li>Website / File URL parameters become URL query values and are read according to the destination system&#39;s query rules.</li> </ul> <pre class="docs-code-block"><code>hqVisuDesigner.openPage(&quot;device_details&quot;, {

frameTarget: &quot;frame&quot;,

parameters: [

{ key: &quot;PLC&quot;, value: &quot;PLC_LINE01&quot; },

{ key: &quot;Device&quot;, value: &quot;PUMP_01&quot; },

{ key: &quot;Mode&quot;, value: 1 },

{ key: &quot;Enabled&quot;, value: true }

]

});</code></pre> </article><article id="post-ops-item-9" class="docs-detail-row"> <strong>Destination reads and type conversion</strong> <p>Read parameters in the destination Page Script and validate before use. GetPageParameter returns the first matching value; GetPageParameterValues returns every value for a repeated key; GetPageParameters returns every { key, value } in original order. All three also have hqVisuDesigner namespace forms. Every read value is a string, so explicitly convert numbers and booleans and constrain allowed characters before building a Tag name.</p> <pre class="docs-code-block"><code>var plc = GetPageParameter(&quot;PLC&quot;, &quot;&quot;);

var device = GetPageParameter(&quot;Device&quot;, &quot;&quot;);

var modeText = GetPageParameter(&quot;Mode&quot;, &quot;0&quot;);

var enabledText = GetPageParameter(&quot;Enabled&quot;, &quot;false&quot;);

if (!/^[A-Za-z0-9_-]{1,64}$/.test(plc) ||

!/^[A-Za-z0-9_-]{1,64}$/.test(device)) {

throw new Error(&quot;Invalid page parameter&quot;);

}

var mode = Number.parseInt(modeText, 10);

var enabled = enabledText === &quot;true&quot;;

var statusTag = plc + &quot;.&quot; + device + &quot;.STATUS&quot;;</code></pre> </article><article id="post-ops-item-10" class="docs-detail-row"> <strong>Popup parameters and close results</strong> <p>The static Open Page as Popup input accepts a JSON object, not a top-level array. With Build page parameters with an expression enabled, the runtime accepts an object or an ordered array of { key, value } entries; use an array for repeated keys. The popup destination still reads values through GetPageParameter*. Close Current Popup&#39;s Result expression is a reverse result channel from the popup to its opener and may return a boolean, number, string, or object; it is separate from the query parameters used to open the popup.</p> </article><article id="post-ops-item-11" class="docs-detail-row"> <strong>Count, length, and security limits</strong> <p>The Runtime keeps at most 64 navigation parameters. A key is limited to 256 characters and a value to 2048 characters; invalid entries are ignored. Parameters enter the URL query and must not carry passwords, tokens, authorization proof, sensitive personal data, or large JSON payloads. Cookie, localStorage, and sessionStorage depend on origin, iframe, and host loading details and are not a formal cross-page parameter protocol. Page parameters cannot expand host-granted Tag, page, or user permissions.</p> </article><article id="post-ops-item-12" class="docs-detail-row"> <strong>Separate four value mechanisms and troubleshoot in order</strong> <p>Template variables, Runtime Variables, PLC Tags, and page parameters solve different problems. Template variables are substituted on an instance and before export; Runtime Variables link state on the current page; PLC Tags belong to the host data layer; page parameters carry context only when a destination is opened. If a read is empty, check whether the target type supports parameters, key spelling and case, whether parameters is an array, count/length limits, whether the host took over navigation, whether the destination URL contains the query, and whether a cross-package relative path was used by mistake.</p> </article> </div> </section><section id="imperative-layout" class="docs-block"> <span class="section-kicker">Feature</span> <h2>Change component layout through scripts</h2> <p>Add runtime logic to the current page with JavaScript. Top-level Page Script variables, constants, classes, and functions are available to every animation and expression on that page. Use ReadTag helpers for Tag values and hqVisuDesigner to drive components and navigation; hqVisuDesignerPageReady runs when the page is ready. Read one bit with the &quot;TAGNAME[bit]&quot; bracket syntax.</p> <div class="docs-detail-list"> <article id="imperative-layout-item-1" class="docs-detail-row"> <strong>Overview</strong> <p>Scripts add runtime logic to the current page, all in JavaScript. The plugin does not provide a Global Script document shared by the whole PowerPoint file. The Scripts group on the ribbon has one current-page entry point, Page Script; alarm.js is also a protected document for that page. Page Script top-level declarations are available to behaviors on the same page but do not automatically exist on other pages. ReadTag helpers read Tag values, while hqVisuDesigner changes component text, color, visibility, layout, and navigation. WriteTag helpers are allowed during real user click, press or release actions, not in Page Script, Setup Script, or Hover Script. Behavior Setup Script / Condition / Value / Text fields use the same ECMAScript 2022 syntax boundary; expression fields must return one synchronous result.</p> </article><article id="imperative-layout-item-2" class="docs-detail-row"> <strong>Use Script Workspace from New to Save</strong> <p>Open Scripts → Page Script. Select a document, or click New and enter Folder and Name. Write in Code; clear Enabled to keep a document without exporting it. Save validates and writes all enabled documents on this page.</p> <ul> <li>Scope: confirm that the target page is active.</li><li>New or Ctrl+N: create a script document.</li><li>Folder: optional slash-separated path.</li><li>Name: document name without the .js extension.</li><li>Enabled: a disabled document is retained but not exported or validated on Save.</li><li>Script Library or Ctrl+J: insert a method or template at the caret.</li><li>Save or Ctrl+S: validate and save the complete workspace.</li><li>Help or F1: open script help.</li> </ul> </article><article id="imperative-layout-item-3" class="docs-detail-row"> <strong>Quick Methods library</strong> <p>Open Quick Methods: filter categories on the left, select a method in the middle, and review its purpose, example and parameters on the right. Search and click Insert to add a snippet. Available methods depend on the installed version.</p> </article><article id="imperative-layout-item-4" class="docs-detail-row"> <strong>Delete documents and keep protected alarm.js</strong> <p>Select a custom document, click Delete and confirm. Protected alarm.js cannot be deleted; edit its alarm configuration to disable or change page alarm display.</p> <ul> <li>Before deleting, confirm no behavior or other document uses its functions or variables.</li><li>Delete applies only to removable custom documents.</li><li>alarm.js is protected; edit its configuration instead.</li><li>Choose Cancel, not Save, when you want to discard all pending workspace edits.</li> </ul> </article><article id="imperative-layout-item-5" class="docs-detail-row"> <strong>How to use it: common methods and syntax</strong> <p>Set window.hqVisuDesignerPageReady in Page Script for initialization; it runs once when the page runtime is ready. Common methods follow:</p> <ul> <li>Read tags, ReadTag family: ReadTagBoolean / ReadTagInteger / ReadTagDouble / ReadTagString; the second argument is the fallback value used when the tag cannot be read</li><li>Date/time helpers: GetCurrentDate() returns yyyy-MM-dd, GetCurrentDateTime() returns yyyy-MM-dd HH:mm:ss, and FormatDateTime(value, &quot;yyyy/MM/dd HH:mm:ss&quot;) formats an existing date/time value; search keywords include time, date, datetime, 时间, 日期</li><li>Read a single bit (key point): append a bracketed bit number to the complete tag name, for example &quot;PLC_LINE01.PUMP01.STATUS[3]&quot;, and read it with ReadTagBoolean; the bit number is zero-based, range 0-31, with no spaces inside the brackets</li><li>Tag quality: ReadTagQuality(name, &quot;bad&quot;) returns the quality text, ReadTagQualityGood(name) tests whether it is good (quality is only good / bad, not the process value)</li><li>Write tags, WriteTag family: use only in a real user-click script; the host still decides permission, confirmation, reason capture, and the final asynchronous outcome</li><li>Drive components, hqVisuDesigner: setComponentText(nameOrId, value), setComponentFill, setComponentBorder, setComponentVisible, setComponentLayout, findComponent, getComponentData</li><li>Navigation and variables, hqVisuDesigner: openPage(&quot;PageName&quot;), openScreen(&quot;SCREEN_CODE&quot;), openWebsite(url, openInNewWindow), writeVariable(name, value), and refreshView()</li> </ul> <pre class="docs-code-block"><code>// Page Script: initialize when the page is ready

window.hqVisuDesignerPageReady = function (ctx) {

// Read bit 0 from an integer tag (bracket syntax, no spaces)

const pumpRun = ReadTagBoolean(&quot;PLC_LINE01.PUMP01.STATUS[0]&quot;, false);

hqVisuDesigner.setComponentText(&quot;Title 1&quot;, pumpRun ? &quot;RUN&quot; : &quot;STOP&quot;);

hqVisuDesigner.setComponentFill(&quot;Lamp 1&quot;, pumpRun ? &quot;#22C55E&quot; : &quot;#EF4444&quot;);

hqVisuDesigner.refreshView();

};</code></pre> </article><article id="imperative-layout-item-6" class="docs-detail-row"> <strong>Common JS snippets: date/time, status text, and safe defaults</strong> <p>Use these snippets in Page Script, Click Script, or a behavior Setup Script area. Condition / Value / Text slots should contain only the final expression that returns immediately; longer checks and formatting belong in Setup Script or a script body.</p> <ul> <li>Ternary expression: condition ? trueValue : falseValue, useful for converting a boolean to text, color, or a numeric value.</li><li>Safe defaults: the second argument of ReadTagBoolean / ReadTagDouble and similar helpers is the fallback when the tag cannot be read.</li><li>Date/time text: use GetCurrentDate() for the current date, GetCurrentDateTime() for the current date-time, and FormatDateTime(...) for display formatting.</li><li>Multiple conditions: use a ternary for simple cases; use if / else to prepare variables before writing to a component or returning a behavior value.</li> </ul> <pre class="docs-code-block"><code>// date / time

const today = GetCurrentDate(); // yyyy-MM-dd

const nowText = GetCurrentDateTime(); // yyyy-MM-dd HH:mm:ss

const displayTime = FormatDateTime(nowText, &quot;yyyy/MM/dd HH:mm:ss&quot;);

// Boolean status to text

const currentValue = ReadTagBoolean(&quot;PLC_LINE01.PUMP01.READY&quot;, false);

let text = currentValue ? &quot;OK&quot; : &quot;Fault&quot;;

// Numeric banding

const speed = ReadTagDouble(&quot;PLC_LINE01.MOTOR01.SPEED&quot;, 0);

const levelText = speed &gt;= 80 ? &quot;High&quot; : (speed &gt;= 40 ? &quot;Medium&quot; : &quot;Low&quot;);

// Quality guard: show communication fault first when quality is bad

if (!ReadTagQualityGood(&quot;PLC_LINE01.MOTOR01.SPEED&quot;)) {

text = &quot;Communication fault&quot;;

}

hqVisuDesigner.setComponentText(&quot;StatusText&quot;, `${text} / ${displayTime}`);

hqVisuDesigner.setComponentText(&quot;LevelText&quot;, levelText);</code></pre> </article><article id="imperative-layout-item-7" class="docs-detail-row"> <strong>Common JS syntax: string concatenation, number formatting, arrays, and objects</strong> <p>Format Tag values with strings, numbers, arrays and objects in Setup Script or Page Script, then return the result to a behavior or write it to a component.</p> <ul> <li>String concatenation: use &#39;Speed: &#39; + speed for simple text; use template strings like `Speed: ${speed}` when several values are involved.</li><li>Number formatting: use Number(value).toFixed(1) to control decimal places.</li><li>Arrays: keep status lists, alarm lists, or multiple component names in arrays, then loop through them.</li><li>Objects: keep lookup tables such as state code to text, color, and priority.</li> </ul> <pre class="docs-code-block"><code>// String concatenation and template strings

const speed = ReadTagDouble(&#39;PLC_LINE01.MOTOR01.SPEED&#39;, 0);

const unit = &#39; rpm&#39;;

const speedText = `Speed: ${Number(speed).toFixed(1)}${unit}`;

const timeText = `Updated: ${GetCurrentDateTime()}`;

// Object map: state code to text and color

const state = ReadTagInteger(&#39;PLC_LINE01.MOTOR01.STATE&#39;, 0);

const stateMap = {

0: { text: &#39;Stopped&#39;, color: &#39;#94A3B8&#39; },

1: { text: &#39;Running&#39;, color: &#39;#22C55E&#39; },

2: { text: &#39;Fault&#39;, color: &#39;#EF4444&#39; }

};

const stateInfo = stateMap[state] ?? { text: &#39;Unknown&#39;, color: &#39;#F59E0B&#39; };

// Arrays: update several components

const targetNames = [&#39;SpeedText&#39;, &#39;SpeedTextCopy&#39;];

targetNames.forEach((name) =&gt; hqVisuDesigner.setComponentText(name, speedText));

hqVisuDesigner.setComponentText(&#39;StateText&#39;, `${stateInfo.text} / ${timeText}`);

hqVisuDesigner.setComponentFill(&#39;StateLamp&#39;, stateInfo.color);</code></pre> </article><article id="imperative-layout-item-8" class="docs-detail-row"> <strong>When to use it</strong> <p>Put shared page functions, constants and Tag prefixes at Page Script top level; put initialization in hqVisuDesignerPageReady. For advanced cross-page reuse, use the host runtime, custom SDK or templates. Use bracket bit reads to drive displays from an integer Tag’s Boolean bit.</p> <ul> <li>Put same-page helpers, constants, and Tag prefixes in the current page&#39;s Page Script</li><li>Use hqVisuDesigner.openPage(...) for same-package pages and hqVisuDesigner.openScreen(...) across packages; do not write disk-relative paths like ../../other-screen/index.html</li> </ul> </article><article id="imperative-layout-item-9" class="docs-detail-row"> <strong>Limitations and troubleshooting</strong> <p>Configuration requirements: (1) Bit-read must use exact &quot;TAGNAME[bit]&quot; syntax with no spaces, and bit numbers are 0-31. Bit writes use the parent integer Tag plus BitIndex; never write TAGNAME[3] as an ordinary Tag. (2) WriteTag is allowed during real user click, press or release actions and is still subject to host permission, confirmation, reason capture, and asynchronous outcome. (3) Async APIs belong only in script-body fields; await must be inside an async function and top-level await is unsupported. (4) import/export are module syntax and are not supported by page documents or animation expressions; advanced modules belong in the custom SDK.</p> </article> </div> <div class="docs-note-grid"> <figure id="imperative-layout-image-1" class="docs-note-card manual-doc-image-card"> <img src="/WEB_img/HQPPT/current/scripts/workspace.png" alt="Mingcedar Studio Script Workspace" loading="lazy" decoding="async"> <figcaption> <strong>Script Workspace</strong> <p>Edit JavaScript documents for the current page; at runtime use ReadTag and hqVisuDesigner to drive the screen.</p> </figcaption> </figure><figure id="imperative-layout-image-2" class="docs-note-card manual-doc-image-card"> <img src="/WEB_img/HQPPT/current-20261021/quick-methods.png" alt="Quick Methods library showing categories, methods, code example, and parameter details" loading="lazy" decoding="async"> <figcaption> <strong>Quick Methods library</strong> <p>Browse or search for a method, review its example and parameters, then click Insert. The visible count belongs to this plugin version.</p> </figcaption> </figure> </div> </section>