Convert generic <select> elements to select2(), with new class helpers (#8053)

* feat: convert generic <select> elements to select2, with new class helpers

Replaces the jQuery UI selectmenu() catch-all in setSelectMenus() with select2,
applied uniformly to single and multi selects. Fewer than 10 options disables
the search box (minimumResultsForSearch: Infinity); 10 or more enables it -
same threshold now applied to the existing select2/select2-multi classes.

New layout.js class helper: select2-multi-count, a multi-select whose
selection summary reads "N Selected"/"All Selected" instead of one chip per
option (generic multiSelectAllText/multiSelectCountText strings in html.php,
overridable per-field via data-select-all-text/data-select-count-text/
data-select-all-value). graph_template_id (html_graph.php x2, html_tree.php)
now uses it in place of the jquery.multiselect-based .graph-multiselect,
preserving the existing "All Graph Templates"/"N Templates Selected" wording
and the -1 "all" sentinel behavior (reimplemented via select2:select/unselect
events in setSelectMenus()). The old .graph-multiselect jquery.multiselect
init block is left in place (now unreachable for core's own markup) in case
a plugin/theme still emits that class itself.

select2-callback is reworked from its previously-unused static-URL contract
into an ajax-backed replacement for the legacy .drop-callback/makeCallbacks()
autocomplete widget: data-action + data-variables build the query the same
way makeCallbacks() already did (pageName + action + live values of other
named fields + search term), and data-callback still names a JS function to
invoke on selection, matching form_callback()'s existing $on_change/$class
contract. form_callback() only renders the new <select> markup when its
$class parameter contains select2-callback (opt-in); every existing caller
that doesn't request it keeps the exact legacy output. html_graph.php's
host_id filter (both places) opts in. form_multi_dropdown() gained optional
$select_all_text/$select_count_text/$select_all_value parameters (all
additive/backward compatible) to plumb the graph_template_id wording through.

Compatibility: an org-wide code search found no plugin depending on the
.select2-callback/.graph-multiselect/.drop-callback/makeCallbacks() internals
being changed here (form_callback()'s default output is unchanged; the
.graph-multiselect jquery.multiselect init stays available). Everywhere else
in core that assumed the old jQuery UI selectmenu widget on elements now
covered by the broadened catch-all (disableField()/enableField(), the SNMP
security-level/protocol refresh logic, realtime.js's ds_step/graph_start/size
refresh, api_aggregate.php's field enable/disable, and html_reports.php's
branch_id/site_id/host_template_id handling) now branches on
.select2-hidden-accessible and uses select2's own refresh mechanism
(.trigger('change.select2')) instead, alongside the untouched legacy
selectmenu branch. #user_language and #i18n_default_language (which get
their own bespoke flag-icon languageselect widget) are excluded from the
catch-all, same as before.

The install wizard (install/install.js) has its own independent selectmenu
initialization and is intentionally left untouched.

* fix: use json_encode for select2 multi-select JS translation strings

* fix: make select2 initializers idempotent to stop duplicate widgets

applySkin() (which calls setSelectMenus(), where every select2/select2-multi/
select2-multi-count/select2-callback/catch-all initializer lives) runs more
than once per page view - once from cactiReady() on initial load, and again
from the generic AJAX-completion handler after any loadUrl()/postUrl() call,
which most list/filter pages already trigger during their own initial load.

Since calling .select2() a second time on an element that already has it
initialized creates a second, independent .select2-container next to the
first (select2 does not no-op or tear down the previous instance), every
affected <select> ended up rendering twice. Guard every initializer (plus
the graph_template_id -1 sentinel's event bindings, now namespaced and
unbound first) so a second setSelectMenus() pass skips elements already
marked .select2-hidden-accessible.

* fix: match select2 dropdown styling to the dark theme's real button look

border-radius was 4px (should be 6px, matching .ui-corner-all used
everywhere else); the selection box and dropdown panel were flat black
instead of this theme's actual .ui-button/.ui-widget-content backgrounds
(a subtle gradient-highlight image and a repeating texture image,
respectively). Also add a min-width and force the selected text/dropdown
option list to a single line instead of wrapping.

* fix: match select2 dropdown styling to each theme's real button look

Same fix as the earlier dark theme commit, applied to the remaining themes.
Every theme's select2 override previously used generic placeholder colors
(border-radius: 4px, background: #ffffff/#222222) that did not match that
theme's actual .ui-state-default/.ui-button/.ui-widget-content styling:

- cacti, carrot, hollyberry, raspberry, modern, paw: selection box now uses
  the real button gradient-image background instead of flat white; dropdown
  panel background already matched and is unchanged.
- sunrise: selection box background corrected to transparent (matching its
  real button style) and the dropdown panel to its real black background,
  instead of flat white for both.
- paper-plane: selection box background corrected to this theme's real
  near-black button color instead of flat white.
- midwinter: switched from hardcoded generic colors to this theme's own
  CSS custom properties (var(--border-color), var(--background-content),
  var(--text-color-lighter), etc.), matching jquery-ui.midwinter.css.

border-radius is now 6px everywhere, matching .ui-corner-all. All themes
also gained a min-width and forced the selected text/dropdown option list
onto a single line instead of wrapping.

* fix: default select2's dropdownAutoWidth to true

The legacy jQuery UI selectmenu widget always sized its open dropdown to fit
the widest option, regardless of how narrow the closed control itself was.
Select2 defaults to matching the dropdown's width to the control's, so wide
option text was wrapping/truncating inside a narrow panel. Set this as a
global default once instead of touching every individual select2() call.

fix: destroy any existing select2 widget before re-initializing

applySkin() runs more than once per page view. The existing
:not(.select2-hidden-accessible) guards were meant to make re-running the
select2 initializers a no-op, but duplicate widgets were still being
reported. Explicitly tear down any select2 instance still attached right
before the initializers run again, so a widget can never end up duplicated
regardless of why applySkin() re-ran.

fix: don't select2-ify a select a plugin already widget-ified with selectmenu

Symmetric to the above: if a plugin's own script already deliberately
applied jQuery UI selectmenu to one of its selects (a few do, for their own
dynamically-created fields), skip converting it to select2 too.

* fix: convert the Device filter's legacy drop-callback widget to select2-callback

html_host_filter()'s autocomplete-enabled branch never got the select2
treatment applied to every other filter field - it still built its own
<input class='drop-callback'> wired up by the older makeCallbacks()/jQuery UI
autocomplete widget (styled with the legacy ui-selectmenu-button markup),
instead of opting into form_callback()'s newer select2-callback rendering like
everything else. Left side-by-side with now-modernized neighboring filters,
this old widget stood out as a leftover "old select". Switch it to the same
select2-callback select markup (data-action='ajax_hosts',
data-variables='site_id') the 1.2.x branch already uses, reusing the existing
ajax_hosts handlers and get_allowed_ajax_hosts()'s id/label response shape.

* fix: restore select2's gradient after closing without selecting, shrink its height, and drop the now-unneeded min-width

Every theme's active/open select2 style also matched .select2-container--focus,
but select2 leaves that class on the container after the dropdown closes (it
only drops --open), so the flat "active" background stuck around until the
next selection instead of the gradient returning right away. Scope the active
look to --open only.

Also shrink the single-select control from select2's stock 28px down to 24px
(and its arrow/rendered text to match) so it sits closer to the jQuery UI
button height it's replacing, and drop the min-width: 160px placeholder added
earlier to keep wide option text from being clipped - dropdownAutoWidth now
sizes the open dropdown to its content regardless of the closed control's
width, so the constraint is no longer needed.

* feat: add configurable select2 search threshold; drop autocomplete_enabled on develop

Add the same Select Search Minimum Rows setting added on 1.2.x, wiring it
through as the select2SearchRows JS global (include/global_session.php) and
replacing the hardcoded 10-option cutoff in every select2 initializer in
layout.js.

Remove Autocomplete Enabled entirely on develop: it only ever existed to let
the Classic theme opt out of the ajax-backed callback widgets, and Classic
doesn't exist as a develop theme. html_host_filter() and the Graph Items data
source field now always use the ajax-backed rendering (select2-callback /
drop_callback) unconditionally instead of branching on the removed setting.

* fix: keep the first 20 select2 results visible before scrolling

Select2's stock results list only guaranteed ~7-8 rows (200px) before
scrolling. Pin each result row to a consistent 24px (matching the shrunk
control height) and size the list's max-height to fit 20 of them before the
scrollbar kicks in.

* fix: repair layout.js corruption from the select2SearchRows commit, and exclude .multiselect from the catch-all

A faulty automated edit in 3cbc5a75 (feat: add configurable select2 search
threshold) matched the wrong text in 4 places and clobbered unrelated code
instead of the intended minimumResultsForSearch lines:
 - deleted the fa-remove icon-class swap and mangled the `if (!theme)` check
 - deleted setupPageTimeout()/CsrfMagic.end()
 - left a stray bare `select2SearchRows` statement before the themeReady() call
 - deleted the #password/#password_confirm delayKeyup wiring and broke the
   showPage deferred's closing brace

Restored all four to their pre-corruption behavior and applied the intended
select2SearchRows threshold to the actual 4 select2 init blocks this time
(select2, select2-multi, select2-multi-count, and the generic catch-all).

While in there: the catch-all's '.multi-select'/'.graph-multiselect'
exclusions never matched anything real - form_multi_dropdown() always tags
its <select multiple> with plain 'multiselect', so every field using the
older jquery.multiselect plugin (Automation's day/month pickers, Consolidation
Functions, Selective Debug, etc.) was getting select2-ified on top of its own
dedicated multiselect() init. Exclude '.multiselect' instead.

* feat: checkbox-styled option rows for select2-multi-count dropdowns

Gets closer to the old jquery-multiselect look the count-style multi-selects
(Graph Templates, etc.) replaced: each option row in the open dropdown now
shows a checkbox-style indicator instead of plain text, driven by
[aria-selected] via CSS so it stays in sync with select2's own selection
state without any extra JS bookkeeping. closeOnSelect stays off so multiple
options can still be picked without the dropdown closing between clicks; the
closed control still shows the "N Selected"/"All Selected" summary text.

* fix: match multi-select control height to single-selects and add its missing dropdown arrow

select2's stock multi-select box only had a min-height with no matching
override, so it stayed taller than every single-select control next to it;
select2-multi-count fields never actually show real per-option chips (the
rendered area always gets replaced with "N Selected"/"All Selected" text),
so it's safe to tighten this to match.

select2 also only renders a .select2-selection__arrow element for
single-selects - multi-selects (Templates, Days of Week, etc.) got none by
default, so they looked handle-less next to every single-select control. Add
a matching CSS-only arrow via ::after (flips on select2-container--open,
same as the single-select's).

* fix: stop select2's multi-select inline search box from collapsing to near-zero width

Select2 sizes the inline search input it embeds in .select2-selection__rendered
by measuring the box's natural layout; my earlier height-matching CSS
(zeroed padding, a fixed line-height, and extending the single-select's
overflow:hidden/text-overflow:ellipsis truncation to multi-selects too) broke
that measurement, so the search field rendered as a barely-visible sliver
sitting inline next to the "N Selected" text instead of expanding to a usable
width.

Back off to a lighter touch: only nudge min-height down a little (no padding/
line-height overrides), and keep the overflow/ellipsis truncation scoped to
single-selects, which is where it was actually needed (short "N Selected"/
"All Selected" labels on multi-selects don't need it and it wasn't there
before this session's changes).

* fix: hide the inline search box on select2-multi-count controls

Reducing padding/line-height (previous attempt) didn't stop the box from
showing - select2's inline search-while-typing input for multi-selects still
rendered as a tiny stray rectangle next to the "N Selected" text and kept
inflating the control's height, since that input's own margin/height are
part of the rendered area's natural content flow regardless of the parent's
box model.

select2-multi-count fields always replace the rendered area with summary
text and rely on checkboxes in the open dropdown for picking options, so the
inline search box serves no purpose here - hide it outright via the adjacent-
sibling selector (select.select2-multi-count + .select2-container), which
also lets the control's height settle back down to match single-selects
without needing to fight select2's own sizing math.

* fix: let select2-multi-count's search box work again once opened; fix vertical alignment

Hiding the inline search box outright also removed the only way to search a
multi-select's open dropdown (multi-select mode has no separate dropdown-only
search box - the inline one filters the open list too). Scope the hide to
:not(.select2-container--open) instead, so it stays out of the way while
closed but reappears once the dropdown is open.

Also wrap the "N Selected"/"All Selected" label in its own span
(select2-count-label) instead of writing bare text into
.select2-selection__rendered, so its line-height/truncation can be
controlled independently of whatever else (the search box) shares that
container - this was causing the text to sit off-center vertically.

* fix: keep the multi-select control's height fixed when its search box opens

Even scoped to select2-container--open, the inline search <li> was still
sitting inside .select2-selection__rendered as a normal block-level sibling
of the "N Selected" label span, so it pushed the label onto its own line and
grew/shifted the whole control upward whenever the dropdown opened - visible
proof the search box was structurally part of the "selection" element, not
just visually overlapping it.

Take it fully out of flow with position: absolute (sized to the control via
top/left/right/height: 100%, overriding select2's own inline width/height on
the actual <input>), so it can never affect the parent's layout regardless of
when it's shown. Also switch the control to flexbox with align-items: center
for reliable vertical centering of the label instead of a guessed
line-height, and give it the same 8px left inset the single-select's text
already has.

* fix: stop the multi-select's overlaid search field from painting over the label

The generic .select2-search--inline .select2-search__field rule gives search
boxes a solid background (matching the dropdown panel's search box, where
that's correct) - but once resized to fill the whole control via absolute
positioning, that same solid background completely hid the "N Selected"
label behind it while the dropdown was open. Make it transparent/borderless
instead, and hide the label (visibility, not display, so layout doesn't
shift) while open so there's no overlapping text underneath the cursor.

* fix: put the multi-select's search box on its own row instead of overlapping the selection

Overlaying it via position: absolute solved the layout-corruption bug but
traded it for a worse one - it now hid the "N Selected" label completely.
Let it flow normally below the label instead (its own full-width block, small
top margin for separation), matching how a search box should actually behave
- visible on its own line, not fighting the label for the same space. The
container only grows taller while the dropdown is actually open, since the
search row is hidden entirely while closed.

Also reset the stray margin select2 puts on #select2-<id>-container (the
same element as .select2-selection__rendered) - it was inflating the closed
control's height too.

* fix: multi-select search box wraps below label; vertically center label text

The row-direction flex box for select2-selection--multiple had no
flex-wrap, so once the search field was added as a second full-width flex
item its own line-item competed with the label item in the same row -
squeezing/overlapping both instead of the intended label-then-search
stacked layout. flex-wrap: wrap lets the label take row 1 and the
full-width search field naturally wrap to row 2, only while open.

Also give the label an explicit line-height matching the control's height
(same technique already used for the single-select boxes) - flex centering
alone left the text sitting a few pixels high due to the font's default
line-height metrics.

* fix: search select2-multi-count from the dropdown, not an inline box in the control

Root cause of the open-state height jump: select2 gives every multiple-select
a type-to-filter <input> INSIDE the selection control (its SelectionSearch
adapter). When the dropdown opens that input appears, growing the control and
pushing the surrounding filter rows down. No amount of CSS on an in-flow child
of the control avoids that - the search genuinely lives inside the control's
box.

Single-selects don't have this problem because their search lives in the
floating dropdown panel (DropdownSearch adapter), which is body-attached and
never affects page layout. So give the multi-count controls the same wiring:
a custom dropdownAdapter (Dropdown + DropdownSearch + MinimumResultsForSearch
+ AttachBody) that searches from the panel, and a selectionAdapter of just
MultipleSelection + EventRelay with no inline search box at all.

The control now keeps a fixed height whether open or closed, and the surrounding
form no longer shifts. Guarded so it falls back to default behavior if the
select2 AMD modules aren't reachable.

* fix: show 15 select2 dropdown rows before scrolling instead of 20

* fix: actually apply the multi-count dropdown-search adapters + trim control padding

Two bugs behind the "search still looks attached to the (green) control and the
control grows when open" report:

1. The adapters were required with the ARRAY form of select2's amd.require(),
   which almond defers via setTimeout - so multiCountDropdownAdapter/
   multiCountSelectionAdapter were still undefined when the init loop ran, and
   select2 silently fell back to its default inline search box inside the
   control. Fetch each module with the synchronous string form instead so the
   adapters are actually in place at init time. The search now lives in the
   floating dropdown (black), not inline in the green open-state control.

2. Vendor select2.css's .select2-container--default .select2-selection--multiple
   adds padding-bottom:5px (equal specificity, so it wasn't being reset), which
   left the count label sitting against the top of the control with a gap below.
   Set explicit padding: 0 20px 0 0 so the flex-centered label is truly centered
   and the closed control matches the single-select height.

* fix: size select2-multi-count control/dropdown to content, not the native listbox width

* fix: reload graphs after the Template select2 fully closes, not mid-teardown

* docs: track pending select2 upstream dropdown-search PR for future cleanup

* docs: link the actual select2 upstream PR (#6462)

* fix: sync checkbox visuals for graph_template_id's -1/others exclusivity; skip reload if nothing changed

Two bugs in the "All Templates" (-1) mutual-exclusivity sentinel:

1. Selecting -1 didn't visually uncheck the other checkboxes, and vice versa.
   The old code flipped the underlying <option>.selected directly and fired a
   plain 'change' event - but select2's own 'change' listener only refreshes
   the "N Selected" summary label, not the open dropdown's rendered results
   list. The checkbox marks are drawn from aria-selected on those already-
   rendered <li> elements, which never got touched. Fixed by routing through
   select2's own internal event bus (available via $el.data('select2')) with
   'select'/'unselect' triggers instead - the exact same path a real click
   takes, which also runs Results.setClasses() to redraw the checkboxes.

2. Opening the dropdown and closing it again without changing anything used
   to still reload the graphs. Now the selected value is snapshotted on open
   and compared on close; the reload only fires if it actually changed.

* fix: force checkbox refresh in graph_template_id sentinel to fix off-by-one visual lag

Reported symptom: click template T1 while "All Graphs & Templates" is
checked - the "All" box unchecks correctly, but T1 does not visually check.
Click T2 next - T1 (not T2) now shows checked. Click T3 - T2 shows checked.
The checkbox visual was always exactly one click behind the actual selection.

Rather than keep chasing the precise internal event-ordering that causes
this (select2's DataAdapter/Results adapters both listen to the same
internal 'select'/'unselect' events our sentinel re-triggers), force a
direct, unconditional call to the Results adapter's own setClasses() method
(exposed publicly as $el.data('select2').results) immediately after our
selection changes. This guarantees the open dropdown's checkboxes reflect
the current underlying <option> selected state before the handler returns,
independent of dispatch ordering.

* debug: temporary console diagnostics for graphTemplateSentinel checkbox lag

* fix: checkbox checkmark keys off --selected class, not aria-selected (hover was stealing it)

Root cause of the "checkbox always one click behind" bug, finally confirmed
via console diagnostics: our checkbox checkmark CSS keyed off the
aria-selected attribute, but select2's own results.js reuses that exact same
attribute for a second, unrelated purpose - tracking which row is currently
mouse-hovered/keyboard-highlighted (a legitimate ARIA listbox pattern). Every
time the mouse moves onto a new row, select2 clears aria-selected on whatever
row was previously "highlighted" and sets it on the newly-hovered row,
completely independent of actual selection state.

Since a user naturally moves the mouse toward the next item immediately after
clicking the current one, this hover-tracking code was stealing
aria-selected="true" away from the just-selected row and handing it to
whatever's now under the cursor - producing exactly the observed "previous
box shows checked, current one doesn't" pattern. Confirmed via console
logging: aria-selected was momentarily correct right after each click (when
our own forced setClasses() call ran), then immediately got reassigned by the
very next mouseenter as the user moved toward their next target.

Fix: key the checkmark off the select2-results__option--selected CSS class
instead. That class is exclusively added/removed by setClasses() based on the
real underlying <option>.selected state, and is never touched by the
mouseenter/highlight-tracking code - so it can't be hijacked by hovering.

Also removes the temporary console.log diagnostics added while tracking this
down; the forced setClasses() calls in the sentinel are kept as harmless extra
insurance.

* chore: apply php-cs-fixer alignment fixes

CI's php-cs-fixer dry-run flagged 4 files for pure whitespace/alignment
drift introduced by the select2 conversion: array `=>` operators and a
docblock's @param columns need to align to the widest key/name in their
respective blocks, and two inline PHP print tags were missing the space
before `?>`. No behavioral change.

* fix: address Copilot review findings on select2 conversion (develop)

- lib/html_form.php: form_callback()'s select2-callback opt-in path used
  htmle() (double_encode=false) for the select's id/name/class, its
  data-action/data-variables/data-callback attributes, and the
  pre-selected option's value attribute. A pre-encoded entity in any of
  these caller-supplied values would survive into the attribute and be
  decoded back into markup/quotes by the browser. Use html_escape_attr()
  (double_encode=true) for all of these attribute contexts; the option's
  text content stays on htmle() since that's body text, not an
  attribute. Same fix for form_multi_dropdown()'s three
  data-select-all-text/data-select-count-text/data-select-all-value
  attributes.
- lib/html_reports.php: changeTree()'s replaceWith(data) on #branch_id
  only swaps the <select> element itself, leaving a live Select2
  instance's sibling .select2-container orphaned in the DOM. Destroy the
  existing Select2 instance first so the re-initialization a few lines
  down doesn't produce a duplicate branch control.

include/layout.js's select2-callback CSRF finding: verified this is not
an actual bug. select2 4.0.13's AjaxAdapter.query() calls
options.data.call(...) and hands the result straight to $.ajax() via the
default transport; for type: 'post' with a plain-object `data` and no
processData:false/contentType override, jQuery serializes it as the POST
body via $.param(), and Cacti's csrf_check() reads the token via
filter_input(INPUT_POST, ...). The __csrf_magic data() callback already
present here (since the PR's first commit) does get sent correctly. No
global $.fn.select2.defaults override clobbers it. Replied with this
analysis rather than changing working code.

Verified: php -l on both changed PHP files; brace-balance check on
lib/html_reports.php (295 open / 295 close).

* fix: address remaining Copilot review findings on select2 conversion (develop)

- include/layout.js: move the select2-hidden-accessible teardown in
  applySkin() to run before setSelectMenus() instead of after it, so the
  catch-all initializer still re-enhances plain <select> elements that the
  teardown just destroyed (previously they stayed native after any
  post-initial-load applySkin() re-run).
- include/layout.js: namespace the select2-callback widget's
  select2:select listener and unbind it before rebinding, since destroying
  and recreating the Select2 instance on every AJAX filter reload does not
  remove a plain jQuery listener bound to the underlying <select>, which
  was accumulating duplicate invocations of the configured callback.
- include/layout.js, lib/auth.php, lib/html.php: thread $noany/$nonone
  from html_host_filter() through to its ajax-backed select2-callback
  widget (as data-noany/data-nonone attributes forwarded as request vars),
  and have get_allowed_ajax_hosts() honor them. $sql_where is intentionally
  left unapplied over the ajax path and documented as such: passing
  caller-supplied raw SQL across the client/server boundary would be a new
  SQL injection vector, unlike the boolean any/none toggles.
- lib/html.php: use html_escape_attr() instead of htmle() for the two
  attribute contexts in html_host_filter()'s markup (data-callback and the
  option value), since htmle()/html_escape() disables double_encode and so
  a pre-encoded quote entity in the input could survive and be decoded
  back into a live quote by the browser, breaking out of the attribute.
  htmle() is kept for the visible option text.
- lib/html.php: use cacti_js_encode() instead of plain json_encode() for
  the two new multi-select translation strings emitted into the inline
  <script> block, since json_encode() alone does not hex-escape </script>
  sequences.
- lib/html_reports.php: use the global select2SearchRows setting instead
  of a hard-coded 10-row threshold when reinitializing the branch_id
  Select2 control after an AJAX tree change, so the configured
  "Select Search Minimum Rows" setting (including "Always") is respected.
- include/themes/paper-plane/main.css, include/themes/sunrise/main.css:
  fix unreadable dark-on-dark Select2 control text (both the base control
  and its rendered value) by using each theme's existing light foreground
  convention instead of the near-black color left over from the plain
  jQuery UI selectmenu styling.

Verified: tests/Unit/InlineScriptDataEncodingTest,
tests/Unit/Security/Xss/HtmlEscapeTest, and reports/host/graph-filter
related Unit tests all pass; php -l and node --check clean on touched
files; empirically reproduced (jsdom + real select2 4.1.0 + jQuery 4.0)
that the select2-multi-count adapter combination does not create a
duplicate inline search box, contrary to one review comment - no code
change made for that finding, replied with the reproduction instead.
This commit is contained in:
TheWitness authored and GitHub committed 2026-09-23 11:58:48 -04:00
1 parent 1e5329dd89
commit f956ea5a5c
23 files changed
+2325 -713

No files matched your search

+25
View File
@@ -136,3 +136,28 @@
- After moving a test between folders, update every path in it, and check each one individually. Setting them all to the repo-root depth silently breaks the `tests/`-internal ones. A `require` that resolves to a missing file is fatal during bootstrap and stops the whole suite rather than failing one test.
- Verify a move by running the suite, not by reading the diff.
## Pending upstream dependency: select2 multi-select dropdown search
- `include/layout.js` (`select2-multi-count` init, both this branch and `feature/select2-select-conversion-1.2.x`)
works around select2 4.1.0 not natively supporting "search from the dropdown
panel instead of an inline box" for multi-selects. It manually builds custom
`dropdownAdapter`/`selectionAdapter` combinations via
`$.fn.select2.amd.require('select2/...')` (synchronous string-form require -
see the comment at that call site for why array-form must not be used).
- TheWitness has an upstream pull request open against `select2/select2`
proposing this behavior as a first-class option:
`https://github.com/select2/select2/pull/6462`
- **Action item for any future Copilot session working in this repo:** when
starting work here, check whether a select2 release has shipped that
includes that PR (check `select2/select2` releases/CHANGELOG for a
first-class dropdown-search-for-multiple-selects option). If it has:
1. Bump the vendored `include/js/select2.js` to that release.
2. Replace the manual adapter-composition workaround in `include/layout.js`
with the new native option on both `feature/select2-select-conversion`
(develop) and `feature/select2-select-conversion-1.2.x` (1.2.x), or their
successor branches/develop/1.2.x if already merged.
3. Remove the now-unnecessary `multiCountDropdownAdapter`/
`multiCountSelectionAdapter` wiring and related comments once the native
option covers it.
4. Open a Cacti PR for this cleanup as a matter of course - don't wait to be
asked.
+19 -25
View File
@@ -1073,29 +1073,27 @@ function item_edit() : void {
$value = '';
}
if (read_config_option('autocomplete_enabled') > 0) {
$action = 'ajax_graph_items';
$action = 'ajax_graph_items';
if (grv('host_id') > 0) {
$action .= '&host_id=' . gfrv('host_id');
}
if (grv('data_template_id') > 0) {
$action .= '&data_template_id=' . gfrv('data_template_id');
}
$struct_graph_item['task_item_id'] = [
'method' => 'drop_callback',
'friendly_name' => __('Data Source'),
'description' => __('Choose the Data Source to associate with this Graph Item.'),
'sql' => '',
'action' => $action,
'none_value' => __('None'),
'id' => $task_item_id,
'value' => $value
];
if (grv('host_id') > 0) {
$action .= '&host_id=' . gfrv('host_id');
}
if (grv('data_template_id') > 0) {
$action .= '&data_template_id=' . gfrv('data_template_id');
}
$struct_graph_item['task_item_id'] = [
'method' => 'drop_callback',
'friendly_name' => __('Data Source'),
'description' => __('Choose the Data Source to associate with this Graph Item.'),
'sql' => '',
'action' => $action,
'none_value' => __('None'),
'id' => $task_item_id,
'value' => $value
];
// modifications to the default graph items array
$struct_graph_item['task_item_id']['sql'] = "SELECT
CONCAT_WS('', dtd.name_cache,' (', dtr.data_source_name, ')') as name, dtr.id
@@ -1124,11 +1122,7 @@ function item_edit() : void {
foreach ($struct_graph_item as $field_name => $field_array) {
$form_array += [$field_name => $struct_graph_item[$field_name]];
if (read_config_option('autocomplete_enabled')) {
if ($field_name != 'task_item_id') {
$form_array[$field_name]['value'] = (isset($template_item[$field_name]) ? $template_item[$field_name] : '');
}
} else {
if ($field_name != 'task_item_id') {
$form_array[$field_name]['value'] = (isset($template_item[$field_name]) ? $template_item[$field_name] : '');
}
+1
View File
@@ -135,4 +135,5 @@ if ($graphs) {
var sessionNotices=<?php print display_output_messages(); ?>;
var sessionMessage={};
var csrfMagicToken='<?php print csrf_get_tokens(); ?>';
var select2SearchRows=<?php print intval(read_config_option('select2_search_rows')); ?>;
</script>
+10 -6
View File
@@ -1299,14 +1299,18 @@ $settings['visual'] = [
'default' => '30',
'array' => $item_rows
],
'autocomplete_enabled' => [
'friendly_name' => __('Autocomplete Enabled'),
'description' => __('In very large systems, select lists can slow the user interface significantly. If this option is enabled, Cacti will use autocomplete callbacks to populate the select list systematically. Note: autocomplete is forcibly disabled on the Classic theme.'),
'select2_search_rows' => [
'friendly_name' => __('Select Search Minimum Rows'),
'description' => __('The minimum number of options a dropdown must have before Cacti shows a search box inside it. Choose \'Always\' to show the search box regardless of the number of options.'),
'method' => 'drop_array',
'default' => '1',
'default' => '10',
'array' => [
1 => __('Yes'),
0 => __('No')
'0' => __('Always'),
'5' => '5',
'10' => '10',
'15' => '15',
'20' => '20',
'25' => '25'
]
],
'autocomplete_rows' => [
+278 -72
View File
@@ -104,6 +104,11 @@ let select2Setup = {
displayDefaultLabel : false,
}
/* size the open dropdown to fit its options instead of the (possibly narrower) control */
if (typeof $ !== 'undefined' && $.fn.select2) {
$.fn.select2.defaults.set('dropdownAutoWidth', true);
}
window.paceOptions = {
ajax: true,
document: true,
@@ -997,6 +1002,19 @@ function applySkin() {
});
}
/* applySkin() runs more than once per page view (initial load, then again
* after every AJAX load/filter apply); tear down any select2 widget still
* attached before setSelectMenus()/the blocks below re-initialize, instead
* of relying only on the :not(.select2-hidden-accessible) guards to skip
* them, so a widget can never end up duplicated. Must run before
* setSelectMenus() so its catch-all init below still re-enhances plain
* <select> elements that this teardown just destroyed. */
$('.select2-hidden-accessible').each(function() {
if ($(this).data('select2')) {
$(this).select2('destroy');
}
});
setSelectMenus();
setGraphTabs();
@@ -1164,19 +1182,19 @@ function applySkin() {
renderLanguages();
$('select.select2').each(function() {
if ($(this).closest('.ui-dialog').length) {
var dropdownParent = $(this).closest('.ui-dialog');
$('select.select2:not(.select2-hidden-accessible)').each(function() {
var options = {
minimumResultsForSearch: select2SearchRows
};
$(this).select2({
dropdownParent: dropdownParent
});
} else {
$(this).select2({});
if ($(this).closest('.ui-dialog').length) {
options.dropdownParent = $(this).closest('.ui-dialog');
}
$(this).select2(options);
});
$('select.select2-nosearch').each(function() {
$('select.select2-nosearch:not(.select2-hidden-accessible)').each(function() {
if ($(this).closest('.ui-dialog').length) {
var dropdownParent = $(this).closest('.ui-dialog');
@@ -1191,7 +1209,7 @@ function applySkin() {
}
});
$('select.select2-tags').each(function() {
$('select.select2-tags:not(.select2-hidden-accessible)').each(function() {
if ($(this).closest('.ui-dialog').length) {
var dropdownParent = $(this).closest('.ui-dialog');
@@ -1206,48 +1224,165 @@ function applySkin() {
}
});
$('select.select2-multi').each(function() {
if ($(this).closest('.ui-dialog').length) {
var dropdownParent = $(this).closest('.ui-dialog');
$(this).select2({
dropdownParent: dropdownParent
});
} else {
$(this).select2({});
}
});
$('select.select2-multi-tags').each(function() {
if ($(this).closest('.ui-dialog').length) {
var dropdownParent = $(this).closest('.ui-dialog');
$(this).select2({
tags: true,
dropdownParent: dropdownParent
});
} else {
$(this).select2({
tags: true
});
}
});
$('select.select2-callback').each(function() {
var callbackUrl = $(this).data('callback');
$('select.select2-multi:not(.select2-hidden-accessible)').each(function() {
var options = {
dropdownParent: $(this).closest('.ui-dialog').length ? $(this).closest('.ui-dialog') : document.body,
minimumResultsForSearch: select2SearchRows
};
if ($(this).closest('.ui-dialog').length) {
options.dropdownParent = $(this).closest('.ui-dialog');
}
$(this).select2(options);
});
/* multi-select that reports "N selected"/"All selected" instead of one chip per option */
/* select2 normally puts a multi-select's type-to-filter box inside the control itself,
* which grows its height and shoves the surrounding form down when opened. Build adapters
* that instead search from the floating dropdown panel (how single-selects behave) and
* drop the inline box entirely, so the control stays a fixed height whether open or closed */
var multiCountDropdownAdapter, multiCountSelectionAdapter;
if ($.fn.select2 && $.fn.select2.amd) {
/* string-form require() resolves synchronously; the array form defers via
* setTimeout, which would leave these undefined when the init loop below runs */
var s2amd = $.fn.select2.amd;
var Utils = s2amd.require('select2/utils');
var Dropdown = s2amd.require('select2/dropdown');
var DropdownSearch = s2amd.require('select2/dropdown/search');
var MinResults = s2amd.require('select2/dropdown/minimumResultsForSearch');
var AttachBody = s2amd.require('select2/dropdown/attachBody');
var MultipleSelection = s2amd.require('select2/selection/multiple');
var EventRelay = s2amd.require('select2/selection/eventRelay');
multiCountDropdownAdapter = Utils.Decorate(
Utils.Decorate(
Utils.Decorate(Dropdown, DropdownSearch),
MinResults
),
AttachBody
);
multiCountSelectionAdapter = Utils.Decorate(MultipleSelection, EventRelay);
}
$('select.select2-multi-count:not(.select2-hidden-accessible)').each(function() {
var $select = $(this);
var allText = $select.data('select-all-text') || multiSelectAllText;
var countText = $select.data('select-count-text') || multiSelectCountText;
var allValue = $select.data('select-all-value');
var options = {
/* without this select2 defaults width to 'resolve', which sizes the control
* (and thus the body-attached dropdown) to the native multi-select's wide
* content box instead of the rendered summary label */
width: 'auto',
minimumResultsForSearch: select2SearchRows,
closeOnSelect: false,
/* checkbox-styled option rows, closer to the old jquery-multiselect look;
* the checked mark itself is drawn from [aria-selected] via CSS */
templateResult: function(state) {
if (!state.id) {
return state.text;
}
return $('<span class="select2-checkbox-option">').text(state.text);
}
};
if (multiCountDropdownAdapter && multiCountSelectionAdapter) {
options.dropdownAdapter = multiCountDropdownAdapter;
options.selectionAdapter = multiCountSelectionAdapter;
}
if ($select.closest('.ui-dialog').length) {
options.dropdownParent = $select.closest('.ui-dialog');
}
$select.select2(options);
function updateSelect2CountLabel() {
var selected = $select.val() || [];
var rendered = $select.next('.select2-container').find('.select2-selection__rendered');
/* own span instead of bare text, so it can be centered independently of
* whatever else (e.g. select2's inline search box) shares this container */
var label = $('<span class="select2-count-label">');
if (selected.length == 0 || (allValue !== undefined && $.inArray(String(allValue), selected) > -1)) {
label.text(allText);
} else {
label.text(selected.length + ' ' + countText);
}
rendered.empty().append(label);
}
$select.on('select2:select select2:unselect change', updateSelect2CountLabel);
updateSelect2CountLabel();
});
$('select.select2-multi-tags:not(.select2-hidden-accessible)').each(function() {
if ($(this).closest('.ui-dialog').length) {
var dropdownParent = $(this).closest('.ui-dialog');
$(this).select2({
tags: true,
dropdownParent: dropdownParent
});
} else {
$(this).select2({
tags: true
});
}
});
/* ajax-backed lookup select: replaces the legacy .drop-callback/makeCallbacks() autocomplete
* widget for filter fields opted into it (see form_callback()'s $class parameter) */
$('select.select2-callback:not(.select2-hidden-accessible)').each(function() {
var $select = $(this);
var action = $select.data('action');
var requestVars = $select.data('variables');
var changeFunc = $select.data('callback');
var noAny = $select.data('noany');
var noNone = $select.data('nonone');
var options = {
dropdownParent: $select.closest('.ui-dialog').length ? $select.closest('.ui-dialog') : document.body,
minimumInputLength: 0,
ajax: {
type: 'post',
dataType: 'json',
delay: 250,
cache: false,
url: function(params) {
if (params.term !== undefined && params.term != '') {
return callbackUrl + '&search=' + encodeURIComponent(params.term) + '&page=' + (encodeURIComponent(params.page || 1));
} else {
return callbackUrl + '&page=' + (encodeURIComponent(params.page || 1));
var url = pageName + '?action=' + encodeURIComponent(action);
if (requestVars) {
$.each(requestVars.split(','), function(index, field) {
if ($('#' + field).length) {
url += '&' + encodeURIComponent(field) + '=' + encodeURIComponent($('#' + field).val());
}
});
}
if (noAny == 1 || noAny === '1') {
url += '&noany=1';
}
if (noNone == 1 || noNone === '1') {
url += '&nonone=1';
}
if (params.term !== undefined && params.term != '') {
url += '&term=' + encodeURIComponent(params.term);
}
return url + '&page=' + encodeURIComponent(params.page || 1);
},
data: function() {
/* these callback actions are regular POST endpoints guarded by the
* same CSRF check as any other form submission */
return { __csrf_magic: csrfMagicToken };
},
processResults: function(data) {
return {
@@ -1259,7 +1394,17 @@ function applySkin() {
}
};
$(this).select2(options);
$select.select2(options);
if (changeFunc) {
/* namespaced + unbound-before-rebound: applySkin() destroys/recreates this
* select2 widget on every AJAX filter reload, but that destroy doesn't remove
* a plain jQuery listener bound to the underlying <select> itself, so without
* this the handler would accumulate and fire the callback multiple times */
$select.off('select2:select.select2Callback').on('select2:select.select2Callback', function() {
executeFunctionByName(changeFunc.replace('(', '').replace(')', ''), window);
});
}
});
}
@@ -3855,41 +4000,87 @@ function setSelectMenus() {
$('select.colordropdown').dropcolor();
$('select').not('.colordropdown').not('.drop-icon').not('.multi-select').not('.graph-multiselect').not('#user_language')
.not('.select2').not('.select2-nosearch').not('.select2-tags').not('.select2-multi').not('.select2-multi-tags').not('.select2-callback')
$('select').not('.colordropdown').not('.drop-icon').not('.multiselect').not('#user_language').not('#i18n_default_language')
.not('.select2').not('.select2-nosearch').not('.select2-tags').not('.select2-multi').not('.select2-multi-tags').not('.select2-multi-count').not('.select2-callback')
.not('.select2-hidden-accessible')
.each(function() {
if ($(this).prop('multiple') != true) {
$(this).each(function() {
let id = $(this).attr('id');
let text = 'hello';
var $this = $(this);
$(this).selectmenu({
open: function(event, ui) {
let instance = $(this).selectmenu('instance');
/* a plugin may have already deliberately widget-ified this element with
* jQuery UI selectmenu itself; don't layer select2 on top of that too */
if ($this.selectmenu('instance')) {
return;
}
instance.menuInstance.focus(null, instance._getSelectedItem());
var options = {
width: 'auto',
minimumResultsForSearch: select2SearchRows
};
let search = instance.menuWrap.find('input');
if ($this.closest('.ui-dialog').length) {
options.dropdownParent = $this.closest('.ui-dialog');
}
if (search.length > 0) {
search.trigger('focus');
}
},
change: function(event, ui) {
$(this).val(ui.item.value).trigger('change');
},
position: {
my: 'left top',
at: 'left bottom',
collision: 'flip'
},
width: 'auto'
});
$this.select2(options);
});
$('#'+id+'-menu').css('max-height', '250px');
/* graph_template_id's '-1' option means "All Templates"; picking it clears every
* other selection and picking anything else clears '-1', mirroring the old
* jquery.multiselect uncheckAll/click handlers this replaces */
var graphTemplateValueAtOpen = null;
$('#graph_template_id.select2-multi-count').off('select2:select.graphTemplateSentinel select2:unselect.graphTemplateSentinel select2:open.graphTemplateSentinel select2:close.graphTemplateSentinel')
.on('select2:open.graphTemplateSentinel', function(event) {
graphTemplateValueAtOpen = ($(this).val() || []).join(',');
}).on('select2:select.graphTemplateSentinel', function(event) {
var $this = $(this);
var instance = $this.data('select2');
if (!instance) {
return;
}
/* unselect through select2's own event bus (not just the underlying <option>s)
* so the open dropdown's checkboxes redraw along with the selection - a plain
* .prop('selected', ...) + change only updates the "N Selected" summary label */
if (event.params.data.id == '-1') {
$this.find('option:selected').not('[value="-1"]').each(function() {
instance.trigger('unselect', { data: { id: this.value, text: this.text, element: this } });
});
} else {
$(this).addClass('ui-state-default ui-corner-all');
var $allOption = $this.find('option[value="-1"]:selected');
if ($allOption.length) {
instance.trigger('unselect', { data: { id: '-1', text: $allOption.text(), element: $allOption[0] } });
}
}
/* belt-and-suspenders: force the open dropdown's checkboxes to match the
* current selection right now, rather than trusting internal event-ordering
* between the data and results adapters to have already redrawn them */
if (instance.results && instance.results.setClasses) {
instance.results.setClasses();
}
}).on('select2:unselect.graphTemplateSentinel', function(event) {
var $this = $(this);
var instance = $this.data('select2');
var $allOption = $this.find('option[value="-1"]');
if (instance && $allOption.length && $this.find('option:selected').length == 0) {
instance.trigger('select', { data: { id: '-1', text: $allOption.text(), element: $allOption[0] } });
}
if (instance && instance.results && instance.results.setClasses) {
instance.results.setClasses();
}
}).on('select2:close.graphTemplateSentinel', function(event) {
var currentValue = ($(this).val() || []).join(',');
/* only reload if the selection actually changed while open - just opening
* and closing without picking anything shouldn't refresh the page */
if (currentValue !== graphTemplateValueAtOpen) {
/* defer past select2's own close teardown so the reload isn't torn down with it */
setTimeout(applyGraphFilter, 0);
}
});
@@ -3905,6 +4096,9 @@ function setSelectMenus() {
/* shrink down */
msWidth -= 20;
/* legacy jquery.multiselect widget, preserved for any plugin/theme still emitting its
* own class='graph-multiselect' element; core's own #graph_template_id now uses
* select2-multi-count (see above) and no longer matches this selector */
$('#graph_template_id.graph-multiselect').hide().multiselect({
menuHeight: $(window).height()*.7,
menuWidth: 'auto',
@@ -3975,6 +4169,8 @@ function setupObjectChange() {
$('#' + id).button('disable');
} else if ($('#' + id).selectmenu('instance')) {
$('#' + id).selectmenu('disable');
} else if ($('#' + id).hasClass('select2-hidden-accessible')) {
$('#' + id).trigger('change.select2');
}
}
@@ -3989,6 +4185,8 @@ function setupObjectChange() {
$('#' + id).button('enable');
} else if ($('#' + id).selectmenu('instance')) {
$('#' + id).selectmenu('enable');
} else if ($('#' + id).hasClass('select2-hidden-accessible')) {
$('#' + id).trigger('change.select2');
}
}
@@ -5511,6 +5709,8 @@ function setSNMPSecurity() {
var selectmenu = ($('#snmp_security_level').selectmenu('instance') !== undefined);
if (selectmenu) {
$('#snmp_security_level').selectmenu('refresh');
} else if ($('#snmp_security_level').hasClass('select2-hidden-accessible')) {
$('#snmp_security_level').trigger('change.select2');
}
$('#snmp_password').delayKeyup(function () {
@@ -5662,6 +5862,12 @@ function setSNMP() {
$('#snmp_auth_protocol').selectmenu('refresh');
$('#snmp_priv_protocol').selectmenu('refresh');
}
if ($('#snmp_security_level').hasClass('select2-hidden-accessible')) {
$('#snmp_security_level').trigger('change.select2');
$('#snmp_auth_protocol').trigger('change.select2');
$('#snmp_priv_protocol').trigger('change.select2');
}
}
function checkSNMPPassphrase(type) {
+6
View File
@@ -103,6 +103,8 @@ function imageOptionsChanged(action) {
$('#ds_step').val(data.ds_step);
if ($('#ds_step').selectmenu('instance') !== undefined) {
$('#ds_step').selectmenu('refresh');
} else if ($('#ds_step').hasClass('select2-hidden-accessible')) {
$('#ds_step').trigger('change.select2');
}
}
@@ -112,6 +114,8 @@ function imageOptionsChanged(action) {
$('#graph_start').val(Math.abs(data.graph_start));
if ($('#graph_start').selectmenu('instance') !== undefined) {
$('#graph_start').selectmenu('refresh');
} else if ($('#graph_start').hasClass('select2-hidden-accessible')) {
$('#graph_start').trigger('change.select2');
}
}
@@ -119,6 +123,8 @@ function imageOptionsChanged(action) {
$('#size').val(data.size);
if ($('#size').selectmenu('instance') !== undefined) {
$('#size').selectmenu('refresh');
} else if ($('#size').hasClass('select2-hidden-accessible')) {
$('#size').trigger('change.select2');
}
}
+192 -62
View File
@@ -2570,66 +2570,196 @@ td.center > table {
color:#ffb7a5 !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(0,119,0,0.9);
color: white;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 6px;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
color: #222222;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(0,119,0,0.9);
color: white;
}
+192 -62
View File
@@ -2575,66 +2575,196 @@ td.center > table {
color:#ffb7a5 !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(255,150,98,0.9);
color: white;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 6px;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
color: #222222;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(255,150,98,0.9);
color: white;
}
+192 -62
View File
@@ -3059,66 +3059,196 @@ circle {
color:#9BB7D4 !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #555555;
border-radius: 4px;
background: #000000;
color: #ffffff;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #ffffff;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #155413;
background: #155413;
color: #ffffff;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #ffffff;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #155413;
border: 1px solid #555555;
color: #ffffff;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #ffffff;
}
.select2-dropdown {
border: 1px solid #555555;
background: #000000;
color: #ffffff;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #555555;
background: #000000;
color: #ffffff;
}
.select2-container--default .select2-results__option--selected {
background: #155413;
color: #ffffff;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: #31442b;
color: #ffffff;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #555555;
border-radius: 6px;
background: #222222 url("images/ui-bg_highlight-soft_35_222222_1x100.png") 50% 50% repeat-x;
color: #ffffff;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #ffffff;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #155413;
background: #155413;
color: #ffffff;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #ffffff;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #155413;
border: 1px solid #555555;
color: #ffffff;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #ffffff;
}
.select2-dropdown {
border: 1px solid #555555;
background: #000000 url("images/ui-bg_loop_25_000000_21x21.png") 50% 50% repeat;
color: #ffffff;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #555555;
background: #000000;
color: #ffffff;
}
.select2-container--default .select2-results__option--selected {
background: #155413;
color: #ffffff;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: #31442b;
color: #ffffff;
}
+192 -62
View File
@@ -2648,66 +2648,196 @@ td.center > table {
color:#56C6A9 !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(0, 161, 11,0.9);
color: white;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 6px;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
color: #222222;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(0, 161, 11,0.9);
color: white;
}
+202 -72
View File
@@ -1,50 +1,50 @@
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/
/* prerequisites */
@import 'css/pre/fonts.css?a23648e6dc13c913f9ae2e993735631b';
@import 'css/pre/colors.css?6a3d4dc1567013fda818848070dd9939';
@import 'css/pre/keyframes.css?6d1d6a79b3c3bf783d25ff4a0cb83d59';
@import 'css/pre/helper.css?6d1d6a79b3c3bf783d25ff4a0cb83d59';
@import 'css/pre/reset.css?6d1d6a79b3c3bf783d25ff4a0cb83d59';
/* Cacti core */
@import 'css/media/hint.css';
@import 'css/media/core.css?ad4ed321bb6b1a387743e4af1388207f' all;
@import 'css/media/print.css?f8c80271650344f45629199331592924' print;
/* compact mode */
@import 'css/media/compact.css?0bda9f47e7be64d1c2709f24cd70ba00' screen;
@import 'css/media/compact-landscape.css?ce95d6c0a3041f8db65365a6d0dad1ca' screen;
/* extensions & addons */
@import 'billboard.midwinter.css?e442c55720734e56c33de67e26a596de';
@import 'jquery-ui.midwinter.css?7c0c69ff83d0a0d9fc7d54b737c7f9d3';
@import 'css/media/daterangepicker.css';
@import 'jquery.contextMenu.css?7c0c69ff83d0a0d9fc7d54b737c7f9d3';
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/
/* prerequisites */
@import 'css/pre/fonts.css?a23648e6dc13c913f9ae2e993735631b';
@import 'css/pre/colors.css?6a3d4dc1567013fda818848070dd9939';
@import 'css/pre/keyframes.css?6d1d6a79b3c3bf783d25ff4a0cb83d59';
@import 'css/pre/helper.css?6d1d6a79b3c3bf783d25ff4a0cb83d59';
@import 'css/pre/reset.css?6d1d6a79b3c3bf783d25ff4a0cb83d59';
/* Cacti core */
@import 'css/media/hint.css';
@import 'css/media/core.css?ad4ed321bb6b1a387743e4af1388207f' all;
@import 'css/media/print.css?f8c80271650344f45629199331592924' print;
/* compact mode */
@import 'css/media/compact.css?0bda9f47e7be64d1c2709f24cd70ba00' screen;
@import 'css/media/compact-landscape.css?ce95d6c0a3041f8db65365a6d0dad1ca' screen;
/* extensions & addons */
@import 'billboard.midwinter.css?e442c55720734e56c33de67e26a596de';
@import 'jquery-ui.midwinter.css?7c0c69ff83d0a0d9fc7d54b737c7f9d3';
@import 'css/media/daterangepicker.css';
@import 'jquery.contextMenu.css?7c0c69ff83d0a0d9fc7d54b737c7f9d3';
/* End of file */
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
@@ -52,59 +52,189 @@
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
border: 1px solid var(--border-color);
border-radius: 6px;
background: transparent;
color: var(--text-color-normal);
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
color: var(--text-color-normal);
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
border-color: var(--border-color);
background: var(--background-lowlight);
color: var(--text-color-highlight-a);
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
border-top-color: var(--text-color-normal);
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
background: var(--background-lowlight);
border: 1px solid var(--border-color-superlowlight);
color: var(--text-color-lighter);
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
color: var(--text-color-lighter);
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
border: 1px solid var(--border-color-superlowlight);
background: var(--background-content);
color: var(--text-color-lighter);
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
border: 1px solid var(--border-color-superlowlight);
background: var(--background-content);
color: var(--text-color-lighter);
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
background: var(--background-lowlight);
color: var(--text-color-highlight-a);
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: #dadada;
color: #212121;
background: var(--background-lowlight);
color: var(--text-color-highlight-a);
}
+192 -62
View File
@@ -2964,66 +2964,196 @@ td.center > table {
.cactiFilterState {
color:snow !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(98,125,77,1);
color: white;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 6px;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
color: #222222;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(98,125,77,1);
color: white;
}
+137 -7
View File
@@ -3070,19 +3070,149 @@ circle {
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
border: 1px solid #d3d3d3;
border-radius: 6px;
background: #111111;
color: #cccccc;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
color: #cccccc;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
+192 -62
View File
@@ -2643,66 +2643,196 @@ td.center > table {
color:#9BB7D4 !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(0,0,0,0.9);
color: white;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 6px;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
color: #222222;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(0,0,0,0.9);
color: white;
}
+192 -62
View File
@@ -2573,66 +2573,196 @@ td.center > table {
color:#56C6A9 !important;
}
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(119,119,0,119.9);
color: white;
/* Select2 - adapt to look like a native Cacti/jQuery UI control.
Select2 4.x ships no jQuery UI theme, so these overrides reuse this
theme's own jquery-ui.css/main.css colors (see .ui-widget-content /
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 6px;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
color: #222222;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
}
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
background: #dadada;
color: #212121;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-top-color: #222222;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background: #dadada;
border: 1px solid #aaaaaa;
color: #212121;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #212121;
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
.select2-container--default .select2-search--inline .select2-search__field {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.select2-container--default .select2-results__option--selected {
background: #dadada;
color: #212121;
}
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable {
background: rgba(119,119,0,119.9);
color: white;
}
+140 -10
View File
@@ -3260,19 +3260,149 @@ circle {
.ui-state-hover / .ui-state-active) to match its look and feel. */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
border: 1px solid #aaaaaa;
border-radius: 4px;
background: #ffffff;
color: #222222;
border: 1px solid rgba(255,255,255,0.2);
border-radius: 6px;
background: transparent;
color: #ffffff;
}
/* match jQuery UI's shorter button height */
.select2-container--default .select2-selection--single {
height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 24px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 22px;
}
/* match the multi-select (e.g. Templates) control to the single-select height;
flexbox centers content vertically regardless of font metrics */
.select2-container--default .select2-selection--multiple {
min-height: 24px;
padding: 0 20px 0 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
display: block;
flex: 1;
margin: 0;
padding-left: 8px;
overflow: hidden;
line-height: 24px;
}
/* select2-multi-count always replaces the rendered area with "N Selected" text;
only hide the inline search-while-typing box while closed (it doesn't fit
that display and was inflating the control's height) - let it reappear once
the dropdown opens, since that's the only place multi-selects can search from */
select.select2-multi-count.select2-hidden-accessible + .select2-container:not(.select2-container--open) .select2-search--inline {
display: none;
}
.select2-selection--multiple .select2-count-label {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* once open, let the search box sit on its own row below the current
selection instead of overlapping it */
.select2-container--default .select2-selection--multiple .select2-search--inline {
display: block;
width: 100%;
margin: 4px 0 0;
}
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
width: 100% !important;
box-sizing: border-box;
margin: 0 !important;
}
/* select2 doesn't draw a dropdown arrow for multi-selects by default; add one to match */
.select2-container--default .select2-selection--multiple::after {
content: '';
position: absolute;
top: 50%;
right: 8px;
margin-top: -2px;
border-color: currentColor transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
width: 0;
pointer-events: none;
}
.select2-container--default.select2-container--open .select2-selection--multiple::after {
border-color: transparent transparent currentColor transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.select2-results__option {
white-space: nowrap;
min-height: 24px;
box-sizing: border-box;
}
/* keep the first 15 results visible before the list needs to scroll */
.select2-container--default .select2-results > .select2-results__options {
max-height: 360px;
}
/* checkbox-style indicator for select2-multi-count option rows */
.select2-results__option .select2-checkbox-option {
position: relative;
display: block;
padding-left: 20px;
}
.select2-results__option .select2-checkbox-option::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 13px;
height: 13px;
margin-top: -7px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
}
/* select2 also (re)uses aria-selected for mouse-hover/keyboard highlight
* tracking, unrelated to actual selection - key off the --selected class
* instead, which setClasses() only ever sets from the real selected data */
.select2-results__option.select2-results__option--selected .select2-checkbox-option::after {
content: '\2713';
position: absolute;
left: 2px;
top: 50%;
margin-top: -7px;
font-size: 11px;
line-height: 13px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #222222;
color: #ffffff;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
/* select2 keeps --focus set after the dropdown closes; only --open should get the active look */
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
border-color: #999999;
@@ -3295,9 +3425,9 @@ circle {
}
.select2-dropdown {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
border: 1px solid rgba(255,255,255,0.2);
background: #000000;
color: #969BA3;
}
.select2-container--default .select2-search--dropdown .select2-search__field,
+6
View File
@@ -2103,6 +2103,8 @@ function draw_aggregate_template_graph_config(int $aggregate_template_id, int $g
if ($('#'+fieldId).selectmenu('instance')) {
$('#'+fieldId).selectmenu('disable');
} else if ($('#'+fieldId).hasClass('select2-hidden-accessible')) {
$('#'+fieldId).trigger('change.select2');
}
}
});
@@ -2117,12 +2119,16 @@ function draw_aggregate_template_graph_config(int $aggregate_template_id, int $g
if ($('#'+fieldId).selectmenu('instance')) {
$('#'+fieldId).selectmenu('enable');
} else if ($('#'+fieldId).hasClass('select2-hidden-accessible')) {
$('#'+fieldId).trigger('change.select2');
}
} else {
$('#'+fieldId).prop('disabled', true).addClass('ui-state-disabled');
if ($('#'+fieldId).selectmenu('instance')) {
$('#'+fieldId).selectmenu('disable');
} else if ($('#'+fieldId).hasClass('select2-hidden-accessible')) {
$('#'+fieldId).trigger('change.select2');
}
}
}
+13
View File
@@ -3372,6 +3372,8 @@ function get_host_array() : array {
/**
* Returns a list of hosts in a way that can be easily read through
* a callback, in JSON. The 'term' request variable will include an optional search term.
* The 'noany'/'nonone' request vars, if present, override $include_any/$include_none
* respectively (used by html_host_filter()'s ajax-backed select2-callback widget).
*
* @param bool $include_any Whether to include an "Any" option in the results.
* @param bool $include_none Whether to include a "None" option in the results.
@@ -3386,6 +3388,17 @@ function get_allowed_ajax_hosts(bool $include_any = true, bool $include_none = t
return [];
}
// html_host_filter()'s select2-callback widget forwards the caller's $noany/$nonone
// choice as request vars, since it's not the same page context that originally
// rendered the filter form; only override the defaults when explicitly present.
if (isrv('noany')) {
$include_any = !gfrv('noany', FILTER_VALIDATE_BOOLEAN);
}
if (isrv('nonone')) {
$include_none = !gfrv('nonone', FILTER_VALIDATE_BOOLEAN);
}
$return = [];
$term = gfrv('term', FILTER_CALLBACK, ['options' => 'sanitize_search_string']);
+26 -44
View File
@@ -2782,15 +2782,17 @@ function html_business_hours_filter(string $callBack = 'applyGraphFilter') : str
*
* @param mixed $host_id - The ID of the host to be selected by default. Defaults to '-1'.
* @param string $call_back - The JavaScript function to call when the selection changes. Defaults to 'applyFilter'.
* @param string $sql_where - Additional SQL WHERE clause to filter the devices. Defaults to an empty string.
* @param string $sql_where - Not applied: the option list is populated via the shared
* 'ajax_hosts' action, which is not safe to pass caller-supplied
* raw SQL to over the client/server boundary. Callers that need to
* constrain the device list must add their own SQL-safe filtering
* (e.g. by request var) inside their page's own 'ajax_hosts' handler.
* @param bool $noany - Whether to exclude the 'Any' option from the dropdown. Defaults to false.
* @param bool $nonone - Whether to exclude the 'None' option from the dropdown. Defaults to false.
*
* @return void
*/
function html_host_filter(mixed $host_id = -1, string $call_back = 'applyFilter', string $sql_where = '', bool $noany = false, bool $nonone = false) : void {
$theme = get_selected_theme();
if (!str_contains($call_back, '()')) {
$call_back .= '()';
}
@@ -2799,49 +2801,27 @@ function html_host_filter(mixed $host_id = -1, string $call_back = 'applyFilter'
$host_id = gfrv('host_id');
}
if (!read_config_option('autocomplete_enabled')) {
?>
<td>
<?php print __('Device'); ?>
</td>
<td>
<select id='host_id' name='host_id' onChange='<?php print $call_back; ?>' data-defaultLabel='<?php print __('Device'); ?>'>
<?php if (!$noany) {?><option value='-1'<?php if ($host_id == '-1') {?> selected<?php }?>><?php print __('Any'); ?></option><?php }?>
<?php if (!$nonone) {?><option value='0'<?php if ($host_id == '0') {?> selected<?php }?>><?php print __('None'); ?></option><?php }?>
<?php
$devices = get_allowed_devices($sql_where);
if (cacti_sizeof($devices)) {
foreach ($devices as $device) {
print "<option value='{$device['id']}'" . ($host_id == $device['id'] ? ' selected' : '') . '>' . htmle(strip_domain($device['description'])) . '</option>';
}
}
?>
</select>
</td>
<?php
if ($host_id > 0) {
$hostname = db_fetch_cell_prepared('SELECT description
FROM host
WHERE id = ?',
[$host_id]);
} elseif ($host_id == 0) {
$hostname = __('None');
} else {
if ($host_id > 0) {
$hostname = db_fetch_cell_prepared('SELECT description
FROM host
WHERE id = ?',
[$host_id]);
} elseif ($host_id == 0) {
$hostname = __('None');
} else {
$hostname = __('Any');
}
?>
<td>
<?php print __('Device'); ?>
</td>
<td>
<?php print "<input id='host_id' name='host_id' type='text' class='drop-callback ui-state-default ui-corner-all' data-action='ajax_hosts' data-callback='$call_back' data-callback-id='host_id' data-value='" . htmle($hostname) . "' value='" . htmle($host_id) . "'>"; ?>
</td>
<?php
$hostname = __('Any');
}
?>
<td>
<?php print __('Device'); ?>
</td>
<td>
<select id='host_id' name='host_id' class='select2-callback' data-action='ajax_hosts' data-variables='site_id' data-noany='<?php print $noany ? '1' : '0'; ?>' data-nonone='<?php print $nonone ? '1' : '0'; ?>' data-callback='<?php print html_escape_attr($call_back); ?>'>
<option value='<?php print html_escape_attr($host_id); ?>' selected><?php print htmle($hostname); ?></option>
</select>
</td>
<?php
}
/**
@@ -3383,6 +3363,8 @@ function html_common_header(string $title, string $selectedTheme = '') : void {
var allSelectedText = '<?php print __('All Graph Templates'); ?>';
var templatesSelected = '<?php print __esc('Templates Selected'); ?>';
var notTemplated = '<?php print __esc('Not Templated'); ?>';
var multiSelectAllText = <?php print cacti_js_encode(__('All Selected')); ?>;
var multiSelectCountText = <?php print cacti_js_encode(__('Selected')); ?>;
var allText = '<?php __esc('All'); ?>';
var noneText = '<?php print __esc('None'); ?>';
var zoom_i18n_3rd_button = '<?php print __esc('3rd Mouse Button'); ?>';
+59 -13
View File
@@ -387,7 +387,10 @@ function draw_edit_control(string $field_name, array &$field_array) : void {
(isset($field_array['sql']) ? db_fetch_assoc($field_array['sql']) : $field_array['value']),
'id',
($field_array['class'] ?? ''),
($field_array['on_change'] ?? '')
($field_array['on_change'] ?? ''),
($field_array['select_all_text'] ?? ''),
($field_array['select_count_text'] ?? ''),
($field_array['select_all_value'] ?? '')
);
break;
@@ -1051,6 +1054,28 @@ function form_callback(string $form_name, string $classic_sql, string $column_di
}
}
/* opt-in via $class: preserves the legacy .drop-callback/makeCallbacks() autocomplete
* widget below for every existing caller (including plugins) that does not explicitly
* request the newer ajax-backed select2-callback rendering. */
if (preg_match('/(^|\s)select2-callback(\s|$)/', $class)) {
if (empty($previous_id) && $prev_val == '') {
$prev_val = $none_entry;
}
print "<select id='" . html_escape_attr($form_name) . "' name='" . html_escape_attr($form_name) . "' class='" . html_escape_attr($class) . "'"
. " data-action='" . html_escape_attr($action) . "' data-variables='" . html_escape_attr($request_vars) . "' data-callback='" . html_escape_attr($on_change) . "'>";
if ($previous_id != '' && $prev_val != '') {
print "<option value='" . html_escape_attr($previous_id) . "' selected>" . htmle($prev_val) . '</option>';
} elseif (!empty($none_entry)) {
print "<option value='0' selected>" . htmle($none_entry) . '</option>';
}
print '</select>';
return;
}
if ($class != '') {
$class = " class='$class' ";
}
@@ -1232,21 +1257,28 @@ function form_text_area(string $form_name, mixed $prev_val, int $form_rows, int
/**
* Draws a standard html multiple select dropdown
*
* @param string $form_name - the name of this form element
* @param array $array_display - an array containing display values for this dropdown. it must
* be formatted like:
* $array[id] = display;
* @param mixed $prev_vals - an array containing keys that should be marked as selected.
* it must be formatted like:
* $array[0][$column_id] = key
* @param string $column_id - the name of the key used to reference the keys above
* @param string $class - Optional. Additional CSS classes to apply to the select element.
* @param string $on_change - Optional. JavaScript code to execute when the selection changes.
* @param string $form_name - the name of this form element
* @param array $array_display - an array containing display values for this dropdown. it must
* be formatted like:
* $array[id] = display;
* @param mixed $prev_vals - an array containing keys that should be marked as selected.
* it must be formatted like:
* $array[0][$column_id] = key
* @param string $column_id - the name of the key used to reference the keys above
* @param string $class - Optional. Additional CSS classes to apply to the select element.
* @param string $on_change - Optional. JavaScript code to execute when the selection changes.
* @param string $select_all_text - Optional. For class 'select2-multi-count', the summary text shown
* when $select_all_value is selected (or nothing is selected).
* @param string $select_count_text - Optional. For class 'select2-multi-count', the suffix appended
* after the selected count (e.g. '3 <suffix>').
* @param string $select_all_value - Optional. For class 'select2-multi-count', the option value that
* represents "all" and takes priority over showing a count.
*
* @return void
*/
function form_multi_dropdown(string $form_name, array $array_display, mixed $prev_vals,
string $column_id, string $class = '', string $on_change = '') : void {
string $column_id, string $class = '', string $on_change = '', string $select_all_text = '',
string $select_count_text = '', string $select_all_value = '') : void {
if (!is_array($prev_vals) && $prev_vals != '') {
$values = explode(',', $prev_vals);
$prev_vals = [];
@@ -1283,7 +1315,21 @@ function form_multi_dropdown(string $form_name, array $array_display, mixed $pre
$on_change = " onChange='$on_change' ";
}
print "<select style='height:20px;' size='1' class='$class' id='$form_name' name='$form_name" . "[]' multiple>";
$select2Attrs = '';
if ($select_all_text != '') {
$select2Attrs .= " data-select-all-text='" . html_escape_attr($select_all_text) . "'";
}
if ($select_count_text != '') {
$select2Attrs .= " data-select-count-text='" . html_escape_attr($select_count_text) . "'";
}
if ($select_all_value != '') {
$select2Attrs .= " data-select-all-value='" . html_escape_attr($select_all_value) . "'";
}
print "<select style='height:20px;' size='1' class='$class'$select2Attrs id='$form_name' name='$form_name" . "[]' multiple>";
foreach (array_keys($array_display) as $id) {
print "<option value='" . $id . "'";
+28 -20
View File
@@ -298,6 +298,7 @@ function create_graphs_preview_filter(string $session_var) : array {
'friendly_name' => __('Device'),
'filter' => FILTER_VALIDATE_INT,
'default' => '-1',
'class' => 'select2-callback',
'pageset' => true,
'request_vars' => 'location,site_id',
'sql' => 'SELECT DISTINCT id, description AS name FROM host ORDER BY description',
@@ -309,16 +310,19 @@ function create_graphs_preview_filter(string $session_var) : array {
],
[
'graph_template_id' => [
'method' => 'drop_multi',
'friendly_name' => __('Template'),
'filter' => FILTER_VALIDATE_REGEXP,
'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)$/']],
'default' => '-1',
'dynamic' => false,
'class' => 'graph-multiselect',
'pageset' => true,
'array' => $normalized_templates,
'value' => gnrv('graph_template_id')
'method' => 'drop_multi',
'friendly_name' => __('Template'),
'filter' => FILTER_VALIDATE_REGEXP,
'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)$/']],
'default' => '-1',
'dynamic' => false,
'class' => 'select2-multi-count',
'select_all_text' => __('All Graph Templates'),
'select_count_text' => __('Templates Selected'),
'select_all_value' => '-1',
'pageset' => true,
'array' => $normalized_templates,
'value' => gnrv('graph_template_id')
],
],
[
@@ -1120,6 +1124,7 @@ function create_listview_filter(string $session_var) : array {
'friendly_name' => __('Device'),
'filter' => FILTER_VALIDATE_INT,
'default' => '-1',
'class' => 'select2-callback',
'pageset' => true,
'request_vars' => 'location,site_id',
'sql' => 'SELECT DISTINCT id, description AS name FROM host ORDER BY description',
@@ -1142,16 +1147,19 @@ function create_listview_filter(string $session_var) : array {
'value' => ''
],
'graph_template_id' => [
'method' => 'drop_multi',
'friendly_name' => __('Template'),
'filter' => FILTER_VALIDATE_REGEXP,
'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)$/']],
'default' => '-1',
'dynamic' => false,
'class' => 'graph-multiselect',
'pageset' => true,
'array' => $normalized_templates,
'value' => gnrv('graph_template_id')
'method' => 'drop_multi',
'friendly_name' => __('Template'),
'filter' => FILTER_VALIDATE_REGEXP,
'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)$/']],
'default' => '-1',
'dynamic' => false,
'class' => 'select2-multi-count',
'select_all_text' => __('All Graph Templates'),
'select_count_text' => __('Templates Selected'),
'select_all_value' => '-1',
'pageset' => true,
'array' => $normalized_templates,
'value' => gnrv('graph_template_id')
],
'graphs' => [
'method' => 'drop_array',
+18
View File
@@ -1461,11 +1461,23 @@ function reports_item_edit() : void {
$.getJSON(strURL, function(data) {
$.get('?action=ajax_get_branches&tree_id=' + $('#tree_id').val(), function(data) {
var selectmenu = $('#branch_id').selectmenu('instance');
var select2 = $('#branch_id').hasClass('select2-hidden-accessible');
/* replaceWith() only swaps the <select> itself; a live Select2 instance's
* sibling .select2-container is left orphaned in the DOM unless torn down
* first, which would leave a duplicate control once re-initialized below */
if (select2) {
$('#branch_id').select2('destroy');
}
$('#branch_id').replaceWith(data);
if (selectmenu) {
$('#branch_id').selectmenu();
} else if (select2) {
$('#branch_id').select2({
minimumResultsForSearch: select2SearchRows
});
}
});
});
@@ -1500,15 +1512,21 @@ function reports_item_edit() : void {
function resetSelects(data) {
if (data.site_id) {
$('#site_id').val('-1');
if ($('#site_id').selectmenu('instance')) {
$('#site_id').selectmenu('refresh');
} else if ($('#site_id').hasClass('select2-hidden-accessible')) {
$('#site_id').trigger('change.select2');
}
}
if (data.host_template_id) {
$('#host_template_id').val('-1');
if ($('#host_template_id').selectmenu('instance')) {
$('#host_template_id').selectmenu('refresh');
} else if ($('#host_template_id').hasClass('select2-hidden-accessible')) {
$('#host_template_id').trigger('change.select2');
}
}
+13 -10
View File
@@ -1014,16 +1014,19 @@ function create_tree_filter() : array {
],
[
'graph_template_id' => [
'method' => 'drop_multi',
'friendly_name' => __('Template'),
'filter' => FILTER_VALIDATE_REGEXP,
'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)(,(cg_[0-9]+|dq_[0-9]+|-?[0-9]+))*$/']],
'default' => '-1',
'dynamic' => false,
'class' => 'graph-multiselect',
'pageset' => true,
'array' => $normalized_templates,
'value' => gnrv('graph_template_id')
'method' => 'drop_multi',
'friendly_name' => __('Template'),
'filter' => FILTER_VALIDATE_REGEXP,
'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)(,(cg_[0-9]+|dq_[0-9]+|-?[0-9]+))*$/']],
'default' => '-1',
'dynamic' => false,
'class' => 'select2-multi-count',
'select_all_text' => __('All Graph Templates'),
'select_count_text' => __('Templates Selected'),
'select_all_value' => '-1',
'pageset' => true,
'array' => $normalized_templates,
'value' => gnrv('graph_template_id')
],
],
[