View layer for the Brazen userscripts framework
This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.sleazyfork.org/scripts/416104/1847306/Brazen%20Framework%20-%20View%20Layer.js
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.
const uiGen = new BrazenViewLayer(scriptPrefix)
scriptPrefix feeds SelectorGenerator for stat label element ids.
| 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:
body.mouseleave on panel slides up unless resizing or Always Show Settings Pane is on.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.
| 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 |
| 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.
| 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.
| 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.
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.
createBookmarksPanel(options?) → BrazenBookmarksPanel
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) |
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).
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.
| 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 |
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