Brazen Framework - View Layer

View layer for the Brazen userscripts framework

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.sleazyfork.org/scripts/416104/1847306/Brazen%20Framework%20-%20View%20Layer.js

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

作者
brazenvoid
版本
3.1.1
建立日期
2020-11-14
更新日期
2026-06-09
尺寸
26.5 KB
授權條款
GPL-3.0-only

Brazen Framework — View Layer (developer guide)

Shared settings panel UI: #bv-ui, tabs, form controls, modals, bookmarks panel, compliance statistics widgets, and tag-sidebar enhancements.

Greasy Fork: View Layer · Requires: Utilities · Used by: Configuration Manager, Framework core

Styles ship inlined at runtime via GM_addStyle when this module loads. Requires @grant GM_addStyle on this script or the app.


Constructor

const uiGen = new BrazenViewLayer(scriptPrefix)

scriptPrefix feeds SelectorGenerator for stat label element ids.


Panel lifecycle

Factory / method Role
createSettingsSection() Root #bv-ui section (hidden by default); includes #bv-resizer
createSettingsShowButton(caption, settingsSection) Left-edge .bv-show-settings strip; slideDown(300) on click
createSettingsHideButton() << Hide — sets panel display: none
getSelectedSection() Returns the container from createContainer() / createSettingsSection()
isSettingsPaneBeingResized() true while #bv-resizer drag is active
createResizer() Width drag handle (min width 150px)

Framework _embedUI:

  • Appends panel + show strip to body.
  • mouseleave on panel slides up unless resizing or Always Show Settings Pane is on.
  • When always-show is enabled, panel is shown immediately.

userScript on #bv-ui: Tab buttons call root.userScript._configurationManager.updateInterface(). Set getSelectedSection()[0].userScript = this in _onAfterUIBuild so custom widgets can reach the app instance.


Layout factories

Method Returns Notes
appendToBody(nodes) Static. Appends jQuery nodes to body
createContainer() JQuery <section class="bv-section bv-font-primary">
createBottomSection(children) JQuery .bv-bottom-section footer column
createTitle(title) JQuery .bv-title label
createSeparator() JQuery <hr/>
createBreakSeparator() JQuery <br class="bv-break"/>
createFormSection(title) JQuery Titled block with inner .bv-title

Form building blocks

Method Returns Notes
createFormGroup() JQuery .bv-group row
createFormGroupLabel(label, inputType?) JQuery .bv-label; adds : for text/number
createFormGroupInput(type) JQuery .bv-input; adds .bv-text or .bv-checkbox-radio
createFormInputGroup(label, type, hoverHelp?) JQuery Label + single input
createFormRangeInputGroup(label, type, min, max, help?) JQuery .bv-range-group with two inputs (min/max)
createFormTextAreaGroup(label, rows, help?) JQuery .bv-textarea-group
createFormCheckBoxesGroupSection(label, pairs, help?) JQuery .bv-checkboxes-group; data-value on each input
createFormRadiosGroupSection(label, pairs, help?) JQuery .bv-radios-group; mutual exclusive on change
createFormGroupDropdown(id, pairs) JQuery <select class="bv-input"> — use directly if needed
createFormButton(caption, hoverHelp, onClick) JQuery .bv-button
createFormActions(children, wrapperClasses?) JQuery .bv-actions button row

Configuration Manager uses these factories via each field's createElement binding.


Tabs

Method Notes
createTabsSection(tabNames[], tabPanels[]) .bv-tabs-section with nav + panels
createTabButton(tabName, isFirst) .bv-tab-button; first tab gets .bv-active
createTabPanel(tabName, isFirst?) .bv-tab-panel; id = Utilities.toKebabCase(tabName)

Critical: Tab button label text must kebab-case to the panel id. Example: button "My Filters" → panel id="my-filters". Active panel gets .bv-active (display: flex).

On tab click: deactivates other buttons/panels, activates matching #kebab-tab-name, calls updateInterface() on linked userScript.


Statistics widgets

Method Notes
createFormGroupStatLabel(statisticType) <label class="bv-stat-label"> with id from SelectorGenerator.getStatLabelSelector
createStatisticsFormGroup(statisticType, label?) .bv-stat-group; label defaults to {type} Filter
createStatisticsTotalsGroup() Total row wired to Total stat key

Pair statisticType with framework filter config keys passed to StatisticsRecorder.record.


Modals

let modal = this._uiGen.createModal('Title', bodyNodes)  // bodyNodes: JQuery | JQuery[]
this._uiGen.showModal(modal)
this._uiGen.hideModal(modal)
Behaviour Detail
Overlay .bv-modal-overlay; click outside closes
Close control .bv-modal-close button
Escape keydown.bvModal on document
Compliance lists .bv-compliance-rule-list, .bv-compliance-rule-row, .bv-compliance-rule-label, .bv-compliance-rule-remove

createModal builds .bv-modal-dialog > header (.bv-modal-title) + .bv-modal-body.


Bookmarks panel

createBookmarksPanel(options?)BrazenBookmarksPanel

Options (BrazenBookmarksPanelOptions)

Option Default Role
showAddButton true Show add button above list
addCaption 'Add Bookmark' Add button text
addHelpText '' Add button tooltip
searchPlaceholder 'Search bookmarks…' Filter input placeholder
searchHelpText Filter tooltip
sortHelpText Sort tooltip
emptyMessage 'No bookmarks yet.' No bookmarks state
noMatchMessage 'No matching bookmarks.' Filter miss state
onAdd / onSort / onRemove(id) / onNavigate(url) callbacks onNavigate defaults to location.href = url
pageMatch optional Current-page bookmark detection (below)

pageMatch (BrazenBookmarksPageMatchOptions)

Option Role
getCurrentUrl() URL to compare (default location.href)
normalizeUrl(url) Trim/normalize before compare
onMatchChange(isBookmarked) Called when match state changes
watchSelectors[] Re-check on input events
isActive() If returns false, forces onMatchChange(false)

Panel API (BrazenBookmarksPanel)

Method Role
element Root .bv-bookmarks-group jQuery node
render(bookmarks[]) BrazenBookmarkEntry[]{ id, label, tags, url }
getFilterQuery() Current search string
isCurrentPageBookmarked(url?) Compare normalized URL to list
checkPageMatch() Refresh pageMatch state

Wired by Configuration Manager addBookmarksField (typically persist: false; app stores via GM_setValue).


Tag sidebar enhancement

enhanceTagSidebarCounts(options?) — wraps tag count spans with hover-reveal action slots.

Option Default
sidebarSelector '#tag-sidebar'
rowSelector 'li[class*="tag-type-"]'
countSelector 'span.tag-count'
hideDelayMs 2000 (0 if prefers-reduced-motion)
extractTag(row) () => ({ name: '' })
renderActions(row, tag, actionsEl, ctx) ctx.isBookmarked from isBookmarked(tagName)
isBookmarked(name) () => false

DOM: .bv-tag-actions-slot wraps count; .bv-tag-actions shown on pointer enter; count hidden while actions visible; .bv-tag-row-active on row.


CSS class vocabulary

Class / id Role
#bv-ui Main settings panel
#bv-resizer, #bv-resizer-icon Width handle
.bv-show-settings / .show-settings Left reveal strip
.bv-section, .bv-bg-colour, .bv-font-primary Panel chrome
.bv-tab-button, .bv-tab-panel, .bv-tabs-nav, .bv-tabs-section Tabs
.bv-active Active tab button or panel
.bv-group, .bv-label, .bv-input, .bv-button, .bv-actions Form
.bv-checkboxes-group, .bv-radios-group, .bv-range-group, .bv-textarea-group Group layouts
.bv-stat-group, .bv-stat-label Statistics
.bv-bookmarks-group, .bv-bookmark-* Bookmarks UI
.bv-modal-overlay, .bv-modal-dialog, .bv-modal-* Modals
.bv-compliance-rule-* Compliance rule modal rows
.bv-tag-actions-slot, .bv-tag-actions, .bv-tag-row-active Sidebar tag actions

Typical composition

this._userInterface = [
  this._uiGen.createTabsSection(['Filters', 'Options'], [
    this._uiGen.createTabPanel('Filters', true).append([
      this._configurationManager.createElement('Tag Blacklist'),
    ]),
    this._uiGen.createTabPanel('Options').append([/* ... */]),
  ]),
  this._uiGen.createBottomSection([
    this._uiGen.createStatisticsTotalsGroup(),
    this._uiGen.createSettingsFormActions(), // from framework helper
  ]),
]

Next in stack: Configuration Manager