All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
The API is unstable, and Semantic Versioning does not yet apply.
Changes in master that are not yet released. Click to see more.
- Fixed restoring from minimized state with
win.restore(), when a taskbar. (The minimize button was not broken, as it usedminimize()to restore the window, which currently toggles the minimized state.)
- Accessing jQuery methods/properties on
$Windowinstances is deprecated. Use theelementproperty to access the underlying DOM element, and wrap it in a jQuery object if you wish to use jQuery methods.- A deprecation notice will be logged each time a jQuery method or property is accessed on a
$Windowinstance, with a stack trace. In some cases, it will recommend a specific alternative. - In TypeScript definitions, the jQuery methods and properties are mapped to
never, with some common methods/properties given special deprecation notices.
- A deprecation notice will be logged each time a jQuery method or property is accessed on a
- jQuery events on
$Windowinstances are deprecated. Use theonBeforeCloseandonClosedmethods to add event listeners.- A deprecation notice will be logged when a listener is added using jQuery's
.on()method, along with a stack trace, and the appropriate method to use instead.
- A deprecation notice will be logged when a listener is added using jQuery's
$Windowfunction now returns aProxyobject, to aid with the transition away from jQuery.- The API is the same, but I've begun to separate the jQuery out from the
OSGUIWindowinterface internally, by overlaying the methods/properties of a jQuery object onto an object satisfying theOSGUIWindowinterface. - Eventually,
OSGUIWindowwill become a class, and$Windowwill be deprecated/removed.
- The API is the same, but I've begun to separate the jQuery out from the
$Windowpropertyelementsfor accessing the different parts of the window, without jQuery.content: The window's content area.titlebar: The window's titlebar, including the title, window buttons, and possibly an icon.title: The window's title.closeButton: The window's close button.minimizeButton: The window's minimize button.maximizeButton: The window's maximize button.
- A simplified event system for
$Windowinstances, independent of jQuery. Each of these methods returns a function that removes the listener.$WindowmethodonFocus(listener)$WindowmethodonBlur(listener)$WindowmethodonIconChange(listener)$WindowmethodonTitleChange(listener)$WindowmethodonClosed(listener)$WindowmethodonBeforeClose(listener)- The listener is passed an object with
preventDefaultwhich can stop the window from closing.
- The listener is passed an object with
$WindowmethodonBeforeDrag(listener)- The listener is passed an object with
preventDefaultwhich can prevent the drag.
- The listener is passed an object with
- A window element will have a CSS class
minimizedwhen minimized, ifsetMinimizeTargetwas called before minimizing.
0.7.3 - 2024-06-15
- Fixed positioning of windows when minimized without a taskbar.
- Fixed menu bar visibility when window is minimized without a taskbar. (It was typically offscreen, but you could reveal it by dragging the window.)
- Closing a window now frees up its minimize slot at the bottom of the screen (if there's no taskbar). Previously only unminimizing did this.
0.7.2 - 2024-05-29
- Marked
options.elementandoptionsas optional inapplyCSSPropertiestype declarations. - Added missing
forceparameter to$Window'sclosemethod in type declarations and documentation. - Changed
getIconAtSizereturn type toNode | null(fromHTMLElement) in type declarations, and mentioned that it can returnnullin the documentation. - (Also changed type of
private $icontoJQuery<Node>) - (Added
dockmethod requirement to deprecated$componentoption of$Windowconstructor, in type declarations.) - (Removed weird
$G.off("scroll", onscroll);for non-existentonscrollin$Window.js. This didn't cause an error, sinceonscrollis a global event, but it shouldn't have been there.)
0.7.1 - 2024-05-24
- Fixed an assertion error that was thrown when navigating menus with the keyboard, due to an overly broad condition. (I asserted that the type was HTMLElement, but needed to assert that it was either null or an HTMLElement. The assertion was just for type narrowing.)
0.7.0 - 2024-05-23
- Deprecate
itemin favor oflabelfor menu item labels- This is just a clearer name for the property.
- Deprecate
shortcutin favor ofshortcutLabelandariaKeyShortcutsaria-keyshortcutsneeds "Control" spelled out, and for macOS "Meta" for the command key, unlike the traditional visual representations. Hence the separation of concerns.
AccessKeysAPI for parsing and rendering labels with access keys (syntax:&defines the following character as the access key,&&inserts one literal ampersand)AccessKeys.escape(label)escapes ampersands by doubling themAccessKeys.unescape(label)unescapes ampersands by removing one of each pairAccessKeys.has(label)returns whether the label has an access keyAccessKeys.get(label)returns the access key character, ornullif there isn't oneAccessKeys.remove(label)returns plain text without access key indicator, likeAccessKeys.toText()but with a special case to remove parentheticals such as " (&N)" rather than just the ampersandAccessKeys.toText(label)returns plain text without access key syntaxAccessKeys.toHTML(label)returns HTML with<span class="menu-hotkey">around the access key (usesAccessKeys.toFragmentfor security)AccessKeys.toFragment(label)returns aDocumentFragmentwith<span class="menu-hotkey">wrapping the access key character- private
AccessKeys.indexOf(label)(don't use this) - (In the future, the CSS class "menu-hotkey" may be renamed to "access-key", perhaps with a prefix.)
- Radio menu item support
- TypeScript types for the whole library
- Type declarations are included as part of the
os-guipackage, inos-gui.d.ts - You may need to reference the declarations file explicitly in your
tsconfig.json'sincludeorfilesarray, or use a/// <reference path="node_modules/os-gui/os-gui.d.ts" />directive. I'm not sure how exactly this is supposed to work.
- Type declarations are included as part of the
$Windowmethods:- experimental
onFocus,onBlur, andonClosedAPI for events (looking to remove dependency on jQuery) - private
addChildWindow($window)(don't use this) - private
unminimize()(don't use this)
- experimental
$Windowproperties:closed: Whether the window has been closed.icons: The icons of the window at different sizes, as set byoptions.iconsorsetIcons().$minimize: the minimize button$maximize: the maximize button- private
$title_area(don't use this) - private
$icon(don't use this)
$Windowpropertyelement(already mentioned but now has a section like other properties)- Menu item specification properties:
shortcutLabelfor defining the label of the shortcut key combination separately from theariaKeyShortcutsproperty; this replaces the oldshortcutpropertyariaKeyShortcutsfor defining the access key combination for the menu item. Must follow aria-keyshortcuts syntax.labelfor defining the label of the menu item; this replaces the olditempropertyvalue(only for radio items) for defining a radio option value
- Docs for positioning windows
- Handle synthetic events, including when pointerId is not given
- This is for jspaint, which triggers pointerup when pressing both mouse buttons to cancel a drawing gesture, and on blur.
- Make menu bars wrap to multiple rows when needed
- Close menus if focus leaves menu popups and menu bar
- If you click on the empty space on the menu bar, it should close menus, not just unhighlight.
- This also seems to fix the case where a window is closed while menus are open (you can test this with the Trigger Station in test.html)
- Improve menu bar code and some behavior
- Prevent some unnecessary DOM updates with highlighting and opening/closing.
- Check for specific menu bar instance when testing focus
- Make menu bar only ever close its own menu popups
- Reduce redundancy in menu closing code
- Fix cycling behavior with Up key: pressing up in a menu opened by clicking (such that the first item isn't automatically highlighted) now goes to the bottom item, instead of the top item (or the second-to-bottom item if you had hovered a menu item within and then moved the mouse out). It still focuses the top item if you open the menu via up/down arrow as this matches the Windows 98 behavior for using the keyboard.
- This commit might actually break closing menu popups in the case that the menu bar is removed from the DOM, because it relies on sending events...
- (I'm not sure if I followed up on this.)
- Use event.key instead of event.keyCode
- Prevent entering disabled submenus [with the keyboard?]
- Don't dispatch update events when hovering menu items
- This only affects the Schrödinger's Checkbox as far as I know, and arguably makes it more thematic, since it only changes when "observing" it.
- (Should it be called Schrödinger's Tick, btw? haha, gross.)
- Make menu popups inherit the theme from the menu bar
- Patch drag handling for Eye Gaze Mode in JS Paint
- Fix menu button border offset on press, and oscillating menu opening when hovering between two menu buttons
- Fix: keep menu button highlighted if clicked to close
- Highlight/open menus when moving mouse at all while over menu button
- Fix: don't trigger menu items if holding Ctrl
- For example, in Paint, with the Help menu open, Ctrl+A shouldn't open About Paint, it should Select All, using the app-global keyboard shortcut.
- SVG icons for checkbox/radio/submenu icons are now defined in CSS using
mask-image - Fix subpixel issues with menu button borders, and margin-bottom (and greatly simplify, by adding a wrapper span)
- Refocus last focused control outside menus on close to support copy/paste
- This generalizes refocusing the last focused control within the window to also work for controls outside the window, I think?
- Fix setting window title to empty string
- Previously, it returned the current window title instead of clearing it, due to incorrect handling of falsy values when differentiating between getter/setter method signatures.
MenuBarmenu item propertydescriptionis now optional.
see Changed
0.6.0 - 2021-11-01
$window.taskway of interfacing with a taskbar. Use$window.setMinimizeTarget(taskbarButtonElement)instead, and eventsicon-changeandtitle-changeto update the button.
MenuBarmethodcloseMenus()to close any open menus.MenuBarmethodsetKeyboardScope(...elements)to control hotkey handling$WindowmethodsetMenuBar(menuBar)to set the menu bar, and set up the keyboard scope.$WindowmethodsetMinimizeTarget(taskbarButtonElement)to set the element representing the window when minimized, which will be used when animating.$Windowpropertyelementto get the DOM element.element.$windowto get the$Windowinstance from the DOM element.$Windoweventsicon-changeandtitle-change- Top level menus support access keys without holding Alt, if the menu bar is focused. (You can not yet tap Alt to focus the menu bar, so you're probably still going to need to hold Alt in practice for now.)
makeBlackToInsetFilter()inparse-theme.jsto initialize an SVG filter for disabled button icons
- If you close a menu by clicking the menu button, the containing window will now be re-focused.
- Menus no longer close when encountering a synthetic
blurevent, to facilitate a hack in Pinball, where abluris triggered to trick the game into pausing. - Windows that are not
resizablecan no longer be maximized. The maximize button will be grayed out.
- Fixed error when pressing arbitrary (unhandled) keys with menu bar focused
- Menus now ignore Alt+(hotkey) if the event is already handled. (For instance, on the demo page there's a menu bar without a window which has global hotkeys, as well as menu bars with identical hotkeys in windows. Hotkeys will now affect the appropriate menu bar depending on whether a window is focused.)
- Window titlebar buttons now use
ButtonTexttheme color instead of always black.
0.5.0 - 2021-10-29
$Window's terribleoptions.iconAPI. Use the new, versatileoptions.iconsinstead. No more ugly globals you have to define! Example:new $Window({icons: {16: 'app-16x16.png', any: 'app-icon.svg'}})setIconByID(), usesetIcons(icons)instead (with same format asoptions.icons)getIconName(), use$window.iconsinstead perhaps, or avoid it entirely
applyCSSPropertiesnow takes an options object instead of an element as the second argument. Useoptions.elementto specify the root element. Default isdocument.documentElement(i.e.<html>,:root).applyCSSPropertiesnow accepts aCSSStyleDeclarationinterchangeably with a plain object of CSS properties, same asrenderThemeGraphicsdoes. I don't know if this is useful, but it's good to be consistent, and this doesn't cost much.- Page scrolling is prevented when the window is re-focused. (Browsers by default scroll controls into view, and re-focusing the window focuses the last focused control.)
touch-action: noneis now applied to the menu bar, so the page doesn't scroll if you're trying to access the menus.- Menus now close on pointer down, not pointer up, for menu buttons.
- When windows are minimized without a taskbar, the minimize button now shows a restore icon.
- Taskbar height calculation now includes padding/border (of
.taskbarelement) - When a menu item is clicked and the menu closes, the containing window is re-focused.
$Window'sclosedevent wasn't fired because the element was removed from the DOM.- A non-
toolWindowwindow withparentWindowdefined now shows as focused. aria-ownsattribute now correctly uses element IDs (not stringified elements like[object HTMLDivElement])- Super minor: if a menu bar is contained in a selection, it will no longer show access key underlines as white. This bothered me. What can I say, I'm a compulsive highlighter.
- Handle older jQuery for
pointerId((e.pointerId ?? e.originalEvent.pointerId)); affects the cursor during window resizing (which usessetPointerCaptureto keep a consistent cursor). - Fix restore from minimize (to taskbar) going to top left corner of screen (if the window had previously been dragged). (This does not apply to taskbarless minimization, which seems to be fine.)
- Word wrap is now prevented in flying titlebar text.
- Menu bar behavior with touch (menus not opening, dialogs blurring after opening via menu, etc.)
- Prevented showing multiple menu buttons as hovered (e.g. if you press Esc and left/right and then hover a different item with the mouse)
- Prevented focus ring showing on menu items when clicking and then using the keyboard, or when using touch. (Menu item highlight effect is separate from focus ring.)
- Prevented resizing window while minimized to bottom of screen (in the case that there's no taskbar).
- Prevented titlebar from shrinking and disappearing (especially when minimized without taskbar), for some window layouts.
- Fixed animation of window restoring if window was minimized without taskbar and then dragged.
- Fixed titlebar button active state not working in Chrome 95.
- Don't show padding around window when window is maximized.
- Windows are now shown as focused when focus is within an iframe, even for nested iframes! Unfortunately this can't work for cross-origin iframes in all cases. (For 98.js.org this was a regression in v0.4.0 due to focus handling changes, but now it's handled in the library)
- Focus can now be restored to the last focused control within (same-origin) iframes, even nested iframes! (when refocusing windows, e.g. clicking on the titlebar)
options.iframes.ignoreCrossOriginto silence warnings about cross-origin iframes (which can't be seamlessly integrated).applyCSSPropertiesnow supportsoptions.recurseIntoIframes(defaults tofalse).$Windowmethodsmaximize(),minimize(), andrestore()$Windowoptioniconswhich can specify icons of different sizes. Pass an object with keys that are sizes in pixels (or "any"), and values that are the URL of an image, or an object withsrcsetif you want support different pixel densities, or a DOM node if you want full control (e.g. to use an<svg>or a font icon or an emoji text node).$WindowmethodsetTitlebarIconSizeto set the icon size, picking the nearest size fromicons.$WindowmethodgetTitlebarIconSizeto get the current icon size.$WindowmethodgetIconAtSizeto pick an icon for the given size, for use in a taskbar. Returns an element ornull.$Windownow exposesiconsproperty based on theoptions.iconsoption..pressingclass to show buttons as pressed (when triggering via the keyboard for example).
0.4.1 - 2021-10-20
- Ability to use
MenuBarwithout$Window.js(TypeError: Assignment to constant variable.) - Handle
document.bodynot existing if you create aMenuBarbeforeDOMContentLoaded - Compatibility with older jQuery
- Removed some redundant event listeners
- More elements are considered tabbable (
object,embed,video,audio,iframe,[contenteditable]) - Greatly improved performance while hovering menu items! Focus is now only set on the menu popup, not the menu item.
- Menu item height no longer changes based on checkbox state
- Menu items that have a submenu open are now highlighted unless another item is hovered at that level.
- If you hover to open a submenu, and then press right (in LTR layout, or left in RTL), it will no longer go to the next top level menu. The submenu is already focused, so you can use up/down to navigate it.
- SVG is now used for checkbox menu items, instead of text.
- SVG for submenu arrow is now more accurate to Windows 98.
- Menu item and divider height is now accurate to Windows 98.
- Menu bars are now screen-reader-friendly!
infoevents (for status bar updates) are now sent when using the arrow keys to navigate.- If a submenu is empty, it is shown with "(Empty)", grayed out.
0.4.0 - 2021-10-15
minWidthoption; useminOuterWidthinstead.minHeightoption; useminOuterHeightinstead.- global
window.focusedWindow(not part of API)
$MenuBar.js; useMenuBar.jsinstead. jQuery is no longer used by the menu bar module.$MenuBar(menus); usenew MenuBar(menus).elementinstead.- The extra parameter to menu bar's
infoevent; useevent.detail?.descriptioninstead.
parseThemeFileStringcan now returnundefinedif the theme file is not valid.- HTML
dirattribute / CSSdirectionproperty is now respected at the level of the window/menu bar, rather than just the document body, so you can have individual windows with different directions. - Menu bar's buttons and top level menus are no longer contained in a
<div class="menu-container">element. Top level menus are now children of<body>, as submenus already were. - Clicking on window will now focus not just the last focused element, but if there wasn't one, it will focus a control with
class="default", and if that doesn't exist, the first control, and if there's no controls, the window itself (specifically$window.$content) or a tool window's parent window. $window.focus()now actually focuses something, rather than just bringing the window to the top and making it appear active. It will focus the last focused control within the window, or else a control withclass="default", or else, if it's a tool window, the parent window, and otherwise the window itself (specifically$window.$content).$window.blur()now removes focus from any focused control within the window. If focus is outside the window, it's not changed.- Windows can now be positioned freely when the
<body>element is smaller than the viewport. The boundary is considered to be the maximum of the document's scrollable area and the viewport. - Window focus is now based around DOM focus. Focusing a control within the window will automatically focus the window. Special logic for preventing blur for taskbars is removed. To prevent blur you must now listen for
mousedownorpointerdownon your element and callevent.preventDefault(), the standard way to prevent blur. - Tool windows that have no parent window are now shown as focused as long as the browser window is focused. This is useful for web applications where the browser window takes the place of the parent application window.
- Window method
setDimensions({ innerWidth, innerHeight, outerWidth, outerHeight })to set the size of the window. - Window options
innerWidth,innerHeight,outerWidth,outerHeightto set the initial size of the window. - Window options
minInnerWidth,minInnerHeight,minOuterWidth,minOuterHeightto set the minimum size of the window. - Windows can now be minimized without a taskbar.
- Menu bar's
infoevent now works with submenus as well. (Previously items that contain submenus were assumed to not have descriptions, simply because Paint's one submenu does not a have a description. But for instance Explorer has descriptions for all of its menus (except Favorites, which is a bit special, what with drag and drop and context menus and all.)) - Greatly improved menu navigation:
- Menus can now be opened with Enter and exited with Escape.
- Menus can now be navigated with access keys, and the first letters of items without access keys defined.
- Pressing Escape an extra time will unfocus the menu bar, focusing the last focused control within the window.
- Submenus can now be navigated with the arrow keys.
- Submenus stay open more easily. It's a little buggy still, but they're not constantly trying to close themselves on you.
- Menus wrap around when navigating up and down or left and right.
- The default action of scrolling the page with arrow keys is now prevented when menus are focused.
- Improved accuracy of the titlebar styles, especially for tool windows.
- Fixed active state of the titlebar buttons in Firefox.
- Disabled buttons no longer show active state if you try to click on them.
- In demo: When loading a theme file, do not apply any styles if it is not a valid theme file.
- For right-to-left languages, submenus are now opened with the left arrow key, matching the arrow direction shown, and menus are navigated with left/right arrow keys spatially (before it was swapped because the order of elements was reversed but the key bindings were not).
- Titlebar gradient is flipped for RTL languages.
- Submenus have correct RTL layout. (Top level menus were previously descendants of the window (so I didn't notice the problem), but now all menus are children of the document body, and
dirattribute is propagated from the menu bar element'sdirectionCSS property to the floating menus.) - Focused disabled menu items are distinguished from enabled menu items.
0.3.0 - 2021-09-04
- Added window options
toolWindow,parentWindow,maximizeButton,minimizeButton,closeButton,resizable,minWidth,minHeight, andconstrainRect(rect, x_axis, y_axis). - Added window method
bringTitleBarInBounds(). - Added window event
closed, which should be used instead ofclosefor detecting when the window is closed. Usecloseonly for preventing the window from closing. - Added window event
window-drag-start. - Focus wrapping now works with Shift+Tab in addition to Tab, and handles more types of focusable elements.
- Focus is now restored to the last focused element within the window when the window is focused again.
- Focus is now given to the next-topmost window when the window is closed.
- Loosened constraints on windows when releasing a drag. You can now drag a window out of the screen, except the titlebar is kept in bounds. (This still doesn't match the behavior of Windows, but in Windows you can recover a window from offscreen with Alt+Space or the taskbar context menu.)
- Increased thickness of the window frame to match the look of Windows 98.
- Window overflow is now hidden by default, with
contain: layout paint;on.window-contentin the layout CSS. - Window content now flexes to fill the window, with
flex: 1;in the layout CSS. The$contentelement still uses the default box model (i.e.display: block), but is stretched within its parent which usesdisplay: flex;.
- Use standard
touch-actionCSS property instead of obsolete PEP polyfill's attribute. The PEP library was never included or documented as a dependency. - Keyboard shortcuts using the meta key are no longer swallowed by the window.
- Allow setting title to empty string. Not very useful.
0.2.2 - 2020-04-30
- Added a Blue color scheme for use in JS Paint for the Winter theme.
- The menu bar is now a fixed height, which should help with automated visual regression testing in JS Paint.
- Submenu popups are now offset correctly on scrollable pages (such as the demo)
- Windows are now clamped to the bounds of a scrollable page instead of an area the size of the view at the top of the page
- Windows are now centered correctly in view when the page is scrolled
- Windows are now dragged correctly while scrolling the page
- Unwanted globals
$GandEare no longer exported
- Windows are bounded to the screen at the end of a drag operation. This doesn't match behavior of windows in Windows 98, but in lieu of OS features for getting windows back on screen like Alt+Space, I think this makes sense for now.
- Dragging over iframes is fixed
- Some layout-important CSS is moved to
layout.css - Some titlebar-related styles are scoped in to
.os-window *to fix conflicts in jspaint, where I'm trying to use a separate window class temporarily for tool windows. - Colors:
- Menu bar dividers now correctly use the theme colors
- Disabled buttons now correctly use the theme colors
- Disabled menu items now correctly use the theme colors except that sometimes it should just show GrayText and not a 3D effect
- Menu bar button text uses the correct colors now
0.2.0 - 2020-03-12
- Rewrote using PostCSS
- Everything is now themeable, by dragging and dropping
.themeand.themepackfiles - Maximize and Minimize, with flying titlebar effect
- Default buttons
- Toggle buttons
- Button borders are now based on SVG
border-image, instead of using pseudo elements,borderandbox-shadow.- Metrics for buttons are changed, they're simpler now, because it's not extending visibly outside the border-box.
- (
::afteris now free to use for other things, altho::beforeis still used for showing focus.)
- Window component is now an app window instead of a tool window, to aid reintegration with 98.js.org; jspaint will come later.
- Window component is styled with
.os-windownow, altho it includes both classesos-windowandwindow.