diff --git a/README.md b/README.md index ae34fba..1b1a043 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,15 @@ Journey.js [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Journey.js%2C%20a%20free%20JavaScript%journey%builder&url=https://github.com/williamtroup/Journey.js&hashtags=javascript,html,journey,guide) -[![npm](https://img.shields.io/badge/npmjs-v0.2.1-blue)](https://www.npmjs.com/package/jjourney.js) -[![nuget](https://img.shields.io/badge/nuget-v0.2.1-purple)](https://www.nuget.org/packages/jJourney.js/) +[![npm](https://img.shields.io/badge/npmjs-v0.3.0-blue)](https://www.npmjs.com/package/jjourney.js) +[![nuget](https://img.shields.io/badge/nuget-v0.3.0-purple)](https://www.nuget.org/packages/jJourney.js/) [![license](https://img.shields.io/badge/license-MIT-green)](https://github.com/williamtroup/Journey.js/blob/main/LICENSE.txt) [![discussions Welcome](https://img.shields.io/badge/discussions-Welcome-red)](https://github.com/williamtroup/Journey.js/discussions) [![coded by William Troup](https://img.shields.io/badge/coded_by-William_Troup-yellow)](https://github.com/williamtroup) >

🚶 A lightweight, and easy-to-use, JavaScript library for building a website walk-through guide!

->

v0.2.1

+>

v0.3.0


![Journey.js](docs/images/main.png) @@ -24,6 +24,7 @@ Journey.js - Fully styled in CSS/SASS and compatible with the Bootstrap library. - Full CSS theme support (using :root variables, with a default dark-mode theme). - Custom triggers for actions (when the dialog is shown for an element, or hidden, etc). +- Shortcut keys (click [here](docs/SHORTCUT_KEYS.md) to see the full list).

diff --git a/README_NUGET.md b/README_NUGET.md index 410f977..ca64f2d 100644 --- a/README_NUGET.md +++ b/README_NUGET.md @@ -1,8 +1,8 @@ -# Journey.js v0.2.1 +# Journey.js v0.3.0 [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Journey.js%2C%20a%20free%20JavaScript%journey%builder&url=https://github.com/williamtroup/Journey.js&hashtags=javascript,html,journey,guide) -[![npm](https://img.shields.io/badge/npmjs-v0.2.1-blue)](https://www.npmjs.com/package/jjourney.js) -[![nuget](https://img.shields.io/badge/nuget-v0.2.1-purple)](https://www.nuget.org/packages/jJourney.js/) +[![npm](https://img.shields.io/badge/npmjs-v0.3.0-blue)](https://www.npmjs.com/package/jjourney.js) +[![nuget](https://img.shields.io/badge/nuget-v0.3.0-purple)](https://www.nuget.org/packages/jJourney.js/) [![license](https://img.shields.io/badge/license-MIT-green)](https://github.com/williamtroup/Journey.js/blob/main/LICENSE.txt) [![discussions Welcome](https://img.shields.io/badge/discussions-Welcome-red)](https://github.com/williamtroup/Journey.js/discussions) [![coded by William Troup](https://img.shields.io/badge/coded_by-William_Troup-yellow)](https://github.com/williamtroup) @@ -17,6 +17,7 @@ - Fully styled in CSS/SASS and compatible with the Bootstrap library. - Full CSS theme support (using :root variables, with a default dark-mode theme). - Custom triggers for actions (when the dialog is shown for an element, or hidden, etc). +- Shortcut keys (click [here](https://github.com/williamtroup/Journey.js/blob/main/docs/SHORTCUT_KEYS.md) to see the full list). ## What browsers are supported? diff --git a/dist/journey.js b/dist/journey.js index 7b13dde..e37ce30 100644 --- a/dist/journey.js +++ b/dist/journey.js @@ -1,4 +1,4 @@ -/*! Journey.js v0.2.1 | (c) Bunoon | MIT License */ +/*! Journey.js v0.3.0 | (c) Bunoon | MIT License */ (function() { function renderDisabledBackground() { _element_Disabled_Background = createElement("div", "journey-js-disabled-background"); @@ -39,12 +39,11 @@ _element_Dialog.style.display = "none"; } function onDialogPrevious() { - removeFocusClassFromLastElement(); - _elements_Attributes_Position--; - if (_elements_Attributes_Position < 0) { - _elements_Attributes_Position = _elements_Attributes_Keys.length - 1; + if (_elements_Attributes_Position > 0) { + removeFocusClassFromLastElement(); + _elements_Attributes_Position--; + showDialogAndSetPosition(); } - showDialogAndSetPosition(); } function onDialogNext() { if (_elements_Attributes_Position === _elements_Attributes_Keys.length - 1) { @@ -141,6 +140,7 @@ if (isDefinedNumber(bindingOptions.order) && (isDefinedString(bindingOptions.title) || isDefinedString(bindingOptions.description))) { _elements_Attributes_Json[bindingOptions.order] = bindingOptions; _elements_Attributes_Keys.push(bindingOptions.order); + element.removeAttribute(_attribute_Name_Journey); } } else { if (!_configuration.safeMode) { @@ -157,6 +157,27 @@ } return result; } + function buildDocumentEvents(addEvents) { + addEvents = isDefined(addEvents) ? addEvents : true; + var documentFunc = addEvents ? _parameter_Document.addEventListener : _parameter_Document.removeEventListener; + if (_configuration.shortcutKeysEnabled) { + documentFunc("keydown", onWindowKeyDown); + } + } + function onWindowKeyDown(e) { + if (_this.isOpen()) { + if (e.keyCode === _enum_KeyCodes.escape) { + e.preventDefault(); + onDialogClose(); + } else if (e.keyCode === _enum_KeyCodes.left) { + e.preventDefault(); + onDialogPrevious(); + } else if (e.keyCode === _enum_KeyCodes.right) { + e.preventDefault(); + onDialogNext(); + } + } + } function buildAttributeOptions(newOptions) { var options = !isDefinedObject(newOptions) ? {} : newOptions; options.order = getDefaultNumber(options.order, 0); @@ -312,11 +333,13 @@ _configuration.nextButtonText = getDefaultString(_configuration.nextButtonText, "Next"); _configuration.finishButtonText = getDefaultString(_configuration.finishButtonText, "Finish"); _configuration.showCloseButton = getDefaultBoolean(_configuration.showCloseButton, true); + _configuration.shortcutKeysEnabled = getDefaultBoolean(_configuration.shortcutKeysEnabled, true); } var _this = this; var _parameter_Document = null; var _parameter_Window = null; var _configuration = {}; + var _enum_KeyCodes = {escape:27, left:37, right:39}; var _string = {empty:"", space:" "}; var _elements_Type = {}; var _elements_Attributes_Json = {}; @@ -356,7 +379,7 @@ return _elements_Attributes_Position >= _elements_Attributes_Keys.length - 1; }; this.getVersion = function() { - return "0.2.1"; + return "0.3.0"; }; (function(documentObject, windowObject) { _parameter_Document = documentObject; @@ -366,6 +389,7 @@ renderDisabledBackground(); renderDialog(); getElements(); + buildDocumentEvents(); }); if (!isDefined(_parameter_Window.$journey)) { _parameter_Window.$journey = this; diff --git a/dist/journey.js.css b/dist/journey.js.css index dc377ab..65f69b7 100644 --- a/dist/journey.js.css +++ b/dist/journey.js.css @@ -1,5 +1,5 @@ /* - * Journey.js Library v0.2.1 + * Journey.js Library v0.3.0 * * Copyright 2023 Bunoon * Released under the MIT License @@ -22,10 +22,14 @@ --dialog-button-hover-background-color: #007FFF; --dialog-button-hover-border-color: var(--dialog-button-border-color); --dialog-button-hover-text-color: var(--dialog-button-text-color); - --dialog-button-disabled-background-color: #002244; - --dialog-close-button-color: var(--color-white); - --dialog-close-button-hover-color: var(--dialog-button-hover-background-color); + --dialog-button-disabled-background-color: var(--dialog-background-color); + --dialog-close-button-background-color: var(--dialog-button-background-color); + --dialog-close-button-border-color: #3457D5; --dialog-close-button-size: 1.1rem; + --dialog-close-button-x-color: var(--color-white); + --dialog-close-button-hover-background-color: #007FFF; + --dialog-close-button-hover-x-color: var(--dialog-close-button-x-color); + --dialog-close-button-hover-border-color: var(--dialog-close-button-border-color); --border-radius: 0.5rem; --border-size: 0.5px; --spacing: 10px; @@ -62,14 +66,14 @@ div.journey-js-dialog button.close { height: var(--dialog-close-button-size); border-radius: 0.25rem; padding: 0; - background-color: transparent; - border: var(--border-size) solid var(--dialog-close-button-color); + background-color: var(--dialog-close-button-background-color); + border: var(--border-size) solid var(--dialog-close-button-border-color); } div.journey-js-dialog button.close::before, div.journey-js-dialog button.close::after { content: ""; width: 1px; height: 100%; - background: var(--dialog-close-button-color); + background: var(--dialog-close-button-x-color); display: block; transform: rotate(45deg) translateX(0px); position: absolute; @@ -81,11 +85,12 @@ div.journey-js-dialog button.close::after { } div.journey-js-dialog button.close:hover { cursor: pointer; - border: var(--border-size) solid var(--dialog-close-button-hover-color); + border: var(--border-size) solid var(--dialog-close-button-hover-border-color); transition: var(--transition); + background-color: var(--dialog-close-button-hover-background-color); } div.journey-js-dialog button.close:hover::before, div.journey-js-dialog button.close:hover::after { - background: var(--dialog-close-button-hover-color); + background: var(--dialog-close-button-hover-x-color); transition: var(--transition); } div.journey-js-dialog div:first-of-type { diff --git a/dist/journey.js.css.map b/dist/journey.js.css.map index 0765ee3..5597cc3 100644 --- a/dist/journey.js.css.map +++ b/dist/journey.js.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../src/journey.js.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;AAAA;AAAA;AAAA;AAAA;AAMA;EAEI;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EACA;EAGA;EAGA;EACA;EACA;EAGA;EACA;EAGA;EAGA;;;AAIJ;AAAA;AAAA;AAAA;AAAA;AAMA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAEA;EAEI;EACA;;AAMR;EACI;;AAIR;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACI;EACA;EACA;EACA;EACA;;AAGJ;AAAA;EACI;EACA;;AAIR;EACI;;;AAMZ;AAAA;AAAA;AAAA;AAAA;AAMA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI","file":"journey.js.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../src/journey.js.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;AAAA;AAAA;AAAA;AAAA;AAMA;EAEI;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EACA;EAGA;EAGA;EACA;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EAGA;EAGA;;;AAIJ;AAAA;AAAA;AAAA;AAAA;AAMA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EAEI;EACA;;AAMR;EACI;;AAIR;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACI;EACA;EACA;EACA;EACA;;AAGJ;AAAA;EACI;EACA;;AAIR;EACI;;;AAMZ;AAAA;AAAA;AAAA;AAAA;AAMA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI","file":"journey.js.css"} \ No newline at end of file diff --git a/dist/journey.js.min.css b/dist/journey.js.min.css index 5f4e7db..61a3002 100644 --- a/dist/journey.js.min.css +++ b/dist/journey.js.min.css @@ -1,2 +1,2 @@ -/*! Journey.js v0.2.1 | (c) Bunoon | MIT License */ -:root{--color-black:#3b3a3a;--color-white:#F5F5F5;--color-gray:#AAA;--dialog-background-color:#024;--dialog-text-color:var(--color-white);--dialog-border-color:#72A0C1;--dialog-button-background-color:#002D62;--dialog-button-border-color:#3457D5;--dialog-button-text-color:var(--color-white);--dialog-button-hover-background-color:#007FFF;--dialog-button-hover-border-color:var(--dialog-button-border-color);--dialog-button-hover-text-color:var(--dialog-button-text-color);--dialog-button-disabled-background-color:#024;--dialog-close-button-color:var(--color-white);--dialog-close-button-hover-color:var(--dialog-button-hover-background-color);--dialog-close-button-size:1.1rem;--border-radius:.5rem;--border-size:.5px;--spacing:10px;--transition:all .3s}div.journey-js-dialog{position:absolute;display:none;border-radius:var(--border-radius);background-color:var(--dialog-background-color);color:var(--dialog-text-color);border:var(--border-size) solid var(--dialog-border-color);padding:var(--spacing);font-family:"Montserrat",sans-serif;font-size:.9rem;z-index:1001;width:300px;height:auto;-webkit-user-select:none;-ms-user-select:none;user-select:none}div.journey-js-dialog button.close{position:absolute;top:var(--spacing);right:var(--spacing);width:var(--dialog-close-button-size);height:var(--dialog-close-button-size);border-radius:.25rem;padding:0;background-color:transparent;border:var(--border-size) solid var(--dialog-close-button-color)}div.journey-js-dialog button.close::before,div.journey-js-dialog button.close::after{content:"";width:1px;height:100%;background:var(--dialog-close-button-color);display:block;transform:rotate(45deg) translateX(0);position:absolute;left:50%;top:0}div.journey-js-dialog button.close::after{transform:rotate(-45deg) translateX(0)}div.journey-js-dialog button.close:hover{cursor:pointer;border:var(--border-size) solid var(--dialog-close-button-hover-color);transition:var(--transition)}div.journey-js-dialog button.close:hover::before,div.journey-js-dialog button.close:hover::after{background:var(--dialog-close-button-hover-color);transition:var(--transition)}div.journey-js-dialog div:first-of-type{padding-right:calc(var(--dialog-close-button-size) + var(--spacing))}div.journey-js-dialog div.title{font-size:large;font-weight:700}div.journey-js-dialog div.description{font-weight:100}div.journey-js-dialog div.buttons{margin-top:var(--spacing);text-align:right}div.journey-js-dialog div.buttons button.previous,div.journey-js-dialog div.buttons button.next{border-radius:var(--border-radius);background-color:var(--dialog-button-background-color);color:var(--dialog-button-text-color);border:var(--border-size) solid var(--dialog-button-border-color);min-width:100px;padding:var(--spacing)}div.journey-js-dialog div.buttons button.previous:not([disabled]):hover,div.journey-js-dialog div.buttons button.next:not([disabled]):hover{cursor:pointer;background-color:var(--dialog-button-hover-background-color);color:var(--dialog-button-hover-text-color);border:var(--border-size) solid var(--dialog-button-hover-border-color);transition:var(--transition)}div.journey-js-dialog div.buttons button.previous:disabled,div.journey-js-dialog div.buttons button.next:disabled{background-color:var(--dialog-button-disabled-background-color)!important;color:var(--color-gray)}div.journey-js-dialog div.buttons button.next{font-weight:700}div.journey-js-disabled-background{z-index:1000;position:fixed;background-color:#000;background-color:rgba(0,0,0,.5);top:0;left:0;height:100%;width:100%}.journey-js-element-focus{z-index:1001!important} \ No newline at end of file +/*! Journey.js v0.3.0 | (c) Bunoon | MIT License */ +:root{--color-black:#3b3a3a;--color-white:#F5F5F5;--color-gray:#AAA;--dialog-background-color:#024;--dialog-text-color:var(--color-white);--dialog-border-color:#72A0C1;--dialog-button-background-color:#002D62;--dialog-button-border-color:#3457D5;--dialog-button-text-color:var(--color-white);--dialog-button-hover-background-color:#007FFF;--dialog-button-hover-border-color:var(--dialog-button-border-color);--dialog-button-hover-text-color:var(--dialog-button-text-color);--dialog-button-disabled-background-color:var(--dialog-background-color);--dialog-close-button-background-color:var(--dialog-button-background-color);--dialog-close-button-border-color:#3457D5;--dialog-close-button-size:1.1rem;--dialog-close-button-x-color:var(--color-white);--dialog-close-button-hover-background-color:#007FFF;--dialog-close-button-hover-x-color:var(--dialog-close-button-x-color);--dialog-close-button-hover-border-color:var(--dialog-close-button-border-color);--border-radius:.5rem;--border-size:.5px;--spacing:10px;--transition:all .3s}div.journey-js-dialog{position:absolute;display:none;border-radius:var(--border-radius);background-color:var(--dialog-background-color);color:var(--dialog-text-color);border:var(--border-size) solid var(--dialog-border-color);padding:var(--spacing);font-family:"Montserrat",sans-serif;font-size:.9rem;z-index:1001;width:300px;height:auto;-webkit-user-select:none;-ms-user-select:none;user-select:none}div.journey-js-dialog button.close{position:absolute;top:var(--spacing);right:var(--spacing);width:var(--dialog-close-button-size);height:var(--dialog-close-button-size);border-radius:.25rem;padding:0;background-color:var(--dialog-close-button-background-color);border:var(--border-size) solid var(--dialog-close-button-border-color)}div.journey-js-dialog button.close::before,div.journey-js-dialog button.close::after{content:"";width:1px;height:100%;background:var(--dialog-close-button-x-color);display:block;transform:rotate(45deg) translateX(0);position:absolute;left:50%;top:0}div.journey-js-dialog button.close::after{transform:rotate(-45deg) translateX(0)}div.journey-js-dialog button.close:hover{cursor:pointer;border:var(--border-size) solid var(--dialog-close-button-hover-border-color);transition:var(--transition);background-color:var(--dialog-close-button-hover-background-color)}div.journey-js-dialog button.close:hover::before,div.journey-js-dialog button.close:hover::after{background:var(--dialog-close-button-hover-x-color);transition:var(--transition)}div.journey-js-dialog div:first-of-type{padding-right:calc(var(--dialog-close-button-size) + var(--spacing))}div.journey-js-dialog div.title{font-size:large;font-weight:700}div.journey-js-dialog div.description{font-weight:100}div.journey-js-dialog div.buttons{margin-top:var(--spacing);text-align:right}div.journey-js-dialog div.buttons button.previous,div.journey-js-dialog div.buttons button.next{border-radius:var(--border-radius);background-color:var(--dialog-button-background-color);color:var(--dialog-button-text-color);border:var(--border-size) solid var(--dialog-button-border-color);min-width:100px;padding:var(--spacing)}div.journey-js-dialog div.buttons button.previous:not([disabled]):hover,div.journey-js-dialog div.buttons button.next:not([disabled]):hover{cursor:pointer;background-color:var(--dialog-button-hover-background-color);color:var(--dialog-button-hover-text-color);border:var(--border-size) solid var(--dialog-button-hover-border-color);transition:var(--transition)}div.journey-js-dialog div.buttons button.previous:disabled,div.journey-js-dialog div.buttons button.next:disabled{background-color:var(--dialog-button-disabled-background-color)!important;color:var(--color-gray)}div.journey-js-dialog div.buttons button.next{font-weight:700}div.journey-js-disabled-background{z-index:1000;position:fixed;background-color:#000;background-color:rgba(0,0,0,.5);top:0;left:0;height:100%;width:100%}.journey-js-element-focus{z-index:1001!important} \ No newline at end of file diff --git a/dist/journey.min.js b/dist/journey.min.js index 37884c8..047f2f1 100644 --- a/dist/journey.min.js +++ b/dist/journey.min.js @@ -1,11 +1,12 @@ -/*! Journey.js v0.2.1 | (c) Bunoon | MIT License */ -(function(){function x(){var a=y[m[k]];l(a.element)&&G(a.onClose,a.element);H(!1);a=n.body;var c=I;try{a.contains(c)&&a.removeChild(c)}catch(b){console.warn(b.message)}g.style.display="none"}function T(){H();k--;0>k&&(k=m.length-1);J()}function U(){k===m.length-1?x():(H(),k++,J())}function J(){var a=y[m[k]];if(l(a)&&l(a.element)){var c=n.body,b=I;try{c.contains(b)||c.appendChild(b)}catch(u){console.warn(u.message)}z.style.display=f.showCloseButton?"block":"none";a.element.className+=p.space+"journey-js-element-focus"; -var e=a.element;for(b=c=0;e&&!isNaN(e.offsetLeft)&&!isNaN(e.offsetTop);)c+=e.offsetLeft-e.scrollLeft,b+=e.offsetTop-e.scrollTop,e=e.offsetParent;var h=n.documentElement;e=(q.pageXOffset||h.scrollLeft)-(h.clientLeft||0);h=(q.pageYOffset||h.scrollTop)-(h.clientTop||0);b=b-h+a.element.offsetHeight;c-=e;e=a.element;h=null;q.getComputedStyle?h=document.defaultView.getComputedStyle(e,null).getPropertyValue("position"):e.currentStyle&&(h=e.currentStyle.position);e=h;e!==p.empty&&"static"===e.toLowerCase()&& -(K=e,a.element.style.position="relative");v.innerHTML=f.previousButtonText;v.disabled=0===k;A.innerHTML=k>=m.length-1?f.finishButtonText:f.nextButtonText;r(a.title)?B.innerHTML=a.title:B.innerHTML=p.empty;r(a.description)?C.innerHTML=a.description:C.innerHTML=p.empty;g.style.display="block";c+g.offsetWidth>q.innerWidth&&(c-=g.offsetWidth+a.element.offsetWidth);b+g.offsetHeight>q.innerHeight&&(b-=g.offsetHeight+a.element.offsetHeight);g.style.top=b+"px";g.style.left=c+"px";G(a.onEnter,a.element)}} -function H(a){a=l(a)?a:!0;var c=y[m[k]];l(c.element)&&(c.element.className=c.element.className.replace(p.space+"journey-js-element-focus",p.empty),l(K)&&(c.element.style.position=K),a&&G(c.onLeave,c.element))}function l(a){return null!==a&&void 0!==a&&a!==p.empty}function D(a){return l(a)&&"object"===typeof a}function Q(a){return l(a)&&"boolean"===typeof a}function r(a){return l(a)&&"string"===typeof a}function L(a){return l(a)&&"function"===typeof a}function R(a){return l(a)&&"number"===typeof a} -function t(a,c){var b=a.toLowerCase();var e="text"===b;M.hasOwnProperty(b)||(M[b]=e?n.createTextNode(p.empty):n.createElement(b));b=M[b].cloneNode(!1);l(c)&&(b.className=c);return b}function G(a){L(a)&&a.apply(null,[].slice.call(arguments,1))}function w(a,c){return r(a)?a:c}function N(a,c){return L(a)?a:c}function V(a){var c=!0,b=null;try{r(a)&&(b=JSON.parse(a))}catch(e){try{b=eval("("+a+")"),L(b)&&(b=b())}catch(h){f.safeMode||(console.error("Errors in object: "+e.message+", "+h.message),c=!1),b= -null}}return{parsed:c,result:b}}function S(){var a=f;var c=f.safeMode;c=Q(c)?c:!0;a.safeMode=c;a=f;var b=f.domElementTypes;c=["*"];r(b)?(b=b.split(p.space),0===b.length&&(b=c)):b=D(b)&&b instanceof Array?b:c;a.domElementTypes=b;f.previousButtonText=w(f.previousButtonText,"Previous");f.nextButtonText=w(f.nextButtonText,"Next");f.finishButtonText=w(f.finishButtonText,"Finish");a=f;c=f.showCloseButton;c=Q(c)?c:!0;a.showCloseButton=c}var W=this,n=null,q=null,f={},p={empty:"",space:" "},M={},y={},m=[], -k=0,K=null,I=null,g=null,z=null,B=null,C=null,v=null,A=null;this.setConfiguration=function(a){f=D(a)?a:{};S();W.isOpen()&&(x(),k=0);return this};this.show=function(){k===m.length-1&&(k=0);J()};this.hide=function(){x()};this.isOpen=function(){return"block"===g.style.display};this.isComplete=function(){return k>=m.length-1};this.getVersion=function(){return"0.2.1"};(function(a,c){n=a;q=c;S();n.addEventListener("DOMContentLoaded",function(){I=t("div","journey-js-disabled-background");g=t("div","journey-js-dialog"); -g.style.display="none";n.body.appendChild(g);z=t("button","close");z.onclick=x;g.appendChild(z);B=t("div","title");g.appendChild(B);C=t("div","description");g.appendChild(C);var b=t("div","buttons");g.appendChild(b);v=t("button","previous");v.onclick=T;b.appendChild(v);A=t("button","next");A.onclick=U;b.appendChild(A);b=f.domElementTypes;for(var e=b.length,h=0;h=n.length-1?f.finishButtonText:f.nextButtonText;r(a.title)?C.innerHTML=a.title:C.innerHTML=p.empty;r(a.description)?D.innerHTML=a.description:D.innerHTML=p.empty;g.style.display="block";c+g.offsetWidth>q.innerWidth&&(c-=g.offsetWidth+a.element.offsetWidth);b+g.offsetHeight>q.innerHeight&&(b-=g.offsetHeight+a.element.offsetHeight);g.style.top=b+"px";g.style.left=c+"px";G(a.onEnter,a.element)}} +function H(a){a=k(a)?a:!0;var c=z[n[l]];k(c.element)&&(c.element.className=c.element.className.replace(p.space+"journey-js-element-focus",p.empty),k(K)&&(c.element.style.position=K),a&&G(c.onLeave,c.element))}function X(a){U.isOpen()&&(a.keyCode===L.escape?(a.preventDefault(),v()):a.keyCode===L.left?(a.preventDefault(),S()):a.keyCode===L.right&&(a.preventDefault(),T()))}function k(a){return null!==a&&void 0!==a&&a!==p.empty}function E(a){return k(a)&&"object"===typeof a}function r(a){return k(a)&& +"string"===typeof a}function M(a){return k(a)&&"function"===typeof a}function V(a){return k(a)&&"number"===typeof a}function t(a,c){var b=a.toLowerCase();var e="text"===b;N.hasOwnProperty(b)||(N[b]=e?m.createTextNode(p.empty):m.createElement(b));b=N[b].cloneNode(!1);k(c)&&(b.className=c);return b}function G(a){M(a)&&a.apply(null,[].slice.call(arguments,1))}function x(a,c){return r(a)?a:c}function O(a,c){return k(a)&&"boolean"===typeof a?a:c}function P(a,c){return M(a)?a:c}function Y(a){var c=!0,b= +null;try{r(a)&&(b=JSON.parse(a))}catch(e){try{b=eval("("+a+")"),M(b)&&(b=b())}catch(h){f.safeMode||(console.error("Errors in object: "+e.message+", "+h.message),c=!1),b=null}}return{parsed:c,result:b}}function W(){f.safeMode=O(f.safeMode,!0);var a=f,c=f.domElementTypes,b=["*"];r(c)?(c=c.split(p.space),0===c.length&&(c=b)):c=E(c)&&c instanceof Array?c:b;a.domElementTypes=c;f.previousButtonText=x(f.previousButtonText,"Previous");f.nextButtonText=x(f.nextButtonText,"Next");f.finishButtonText=x(f.finishButtonText, +"Finish");f.showCloseButton=O(f.showCloseButton,!0);f.shortcutKeysEnabled=O(f.shortcutKeysEnabled,!0)}var U=this,m=null,q=null,f={},L={escape:27,left:37,right:39},p={empty:"",space:" "},N={},z={},n=[],l=0,K=null,I=null,g=null,A=null,C=null,D=null,w=null,B=null;this.setConfiguration=function(a){f=E(a)?a:{};W();U.isOpen()&&(v(),l=0);return this};this.show=function(){l===n.length-1&&(l=0);J()};this.hide=function(){v()};this.isOpen=function(){return"block"===g.style.display};this.isComplete=function(){return l>= +n.length-1};this.getVersion=function(){return"0.3.0"};(function(a,c){m=a;q=c;W();m.addEventListener("DOMContentLoaded",function(){I=t("div","journey-js-disabled-background");g=t("div","journey-js-dialog");g.style.display="none";m.body.appendChild(g);A=t("button","close");A.onclick=v;g.appendChild(A);C=t("div","title");g.appendChild(C);D=t("div","description");g.appendChild(D);var b=t("div","buttons");g.appendChild(b);w=t("button","previous");w.onclick=S;b.appendChild(w);B=t("button","next");B.onclick= +T;b.appendChild(B);b=f.domElementTypes;for(var e=b.length,h=0;h | Type: | Name: | Description: | @@ -12,7 +12,7 @@ Below are all the JSON properties that can be passed in the "data-journey-option
-### Translatable String Options: +## Translatable String Options:
| Type: | Name: | Description: | diff --git a/docs/BINDING_OPTIONS_CUSTOM_TRIGGERS.md b/docs/BINDING_OPTIONS_CUSTOM_TRIGGERS.md index 8132c7d..cc85df7 100644 --- a/docs/BINDING_OPTIONS_CUSTOM_TRIGGERS.md +++ b/docs/BINDING_OPTIONS_CUSTOM_TRIGGERS.md @@ -5,7 +5,7 @@ Below is a list of all the custom triggers supported in the "data-journey-option
-

For Viewing:

+## For Viewing: ### options.onEnter( *element* ): Fires when the the dialog is shown for a specific DOM element. diff --git a/docs/CHANGE_LOG.md b/docs/CHANGE_LOG.md index 53af95c..06d012a 100644 --- a/docs/CHANGE_LOG.md +++ b/docs/CHANGE_LOG.md @@ -1,5 +1,28 @@ # Journey.js - Change Log: +## Version 0.3.0: + +#### **New Features:** +- Added shortcut keys "Left", "Right", and "Escape", which move to the previous/next element in the journey, and close the dialog. + +#### **Configuration Options:** +- Added a new configuration option "shortcutKeysEnabled" (defaults to true), which states if the shortcut keys (for navigation) are enabled. + +#### **CSS:** +- Added CSS ":root" variable "--dialog-close-button-background-color", which states the background color to use for the close button. +- Added CSS ":root" variable "--dialog-close-button-border-color", which states the border color to use for the close button. +- Added CSS ":root" variable "--dialog-close-button-hover-background-color", which states the background color to use for the close button when hovered. +- Renamed one or two of the other ":root" variables for the Close button. + +#### **General Improvements:** +- The attribute "data-journey-options" is now removed from all elements after they are processed. + +#### **Fixes:** +- Fixed the previous buttons event sometimes allowing a loop back to the end. + +
+ + ## Version 0.2.1: - Added Code of Conduct, Contributing, and Security Policy. diff --git a/docs/CONFIGURATION_OPTIONS.md b/docs/CONFIGURATION_OPTIONS.md index 23d0878..3d12e8b 100644 --- a/docs/CONFIGURATION_OPTIONS.md +++ b/docs/CONFIGURATION_OPTIONS.md @@ -1,11 +1,10 @@ # Journey.js - Configuration Options: Below are all the configuration options that can be passed to the "setConfiguration()" public function. +
+
-### Options: -
- | Type: | Name: | Description: | | --- | --- | --- | | *boolean* | safeMode | States if safe-mode is enabled (errors will be ignored and logged only (defaults to true). | @@ -13,4 +12,5 @@ Below are all the configuration options that can be passed to the "setConfigurat | *string* | previousButtonText | States the text that should be used for the Previous button (defaults to "Previous"). | | *string* | nextButtonText | States the text that should be used for the Next button (defaults to "Next"). | | *string* | finishButtonText | States the text that should be used for the Finish button (defaults to "Finish"). | -| *boolean* | showCloseButton | States if the Close button is visible on the dialog (defaults to true). | \ No newline at end of file +| *boolean* | showCloseButton | States if the Close button is visible on the dialog (defaults to true). | +| *boolean* | shortcutKeysEnabled | States if the shortcut keys are enabled (defaults to true). | \ No newline at end of file diff --git a/docs/PUBLIC_FUNCTIONS.md b/docs/PUBLIC_FUNCTIONS.md index 55e302e..0973813 100644 --- a/docs/PUBLIC_FUNCTIONS.md +++ b/docs/PUBLIC_FUNCTIONS.md @@ -5,7 +5,7 @@ Below is a list of all the public functions that can be called from the Journey.
-

Show/Hide:

+## Show/Hide: ### **show()**: Shows the Journey.js dialog for the element in the last known position (defaults to the start). @@ -26,10 +26,10 @@ Returns a flag that states if the dialog is opened. Returns a flag that states if the full journey has been completed.
***Returns***: '*boolean*' - The flag that states if the full journey has been completed. +
-
-

Configuration:

+## Configuration: ### **setConfiguration( *newOptions* )**: Sets the specific configuration options that should be used. @@ -37,10 +37,10 @@ Sets the specific configuration options that should be used. ***Parameter: newOptions***: '*Options*' - All the configuration options that should be set (refer to ["Configuration Options"](CONFIGURATION_OPTIONS.md) documentation for properties).
***Returns***: '*Object*' - The Journey.js class instance. +
-
-

Additional Data:

+## Additional Data: ### **getVersion()**: Returns the version of Journey.js. diff --git a/docs/SHORTCUT_KEYS.md b/docs/SHORTCUT_KEYS.md new file mode 100644 index 0000000..fc7698c --- /dev/null +++ b/docs/SHORTCUT_KEYS.md @@ -0,0 +1,12 @@ +# Journey.js - Shortcut Keys: + +Below is a list of all the shortcut keys supported in Journey.js. +
+
+ + +| Key: | Description: | +| --- | --- | +| *Left* | Moves to the previous element in the journey. | +| *Right* | Moves to the next element in the journey. | +| *Escape* | Close the dialog. | \ No newline at end of file diff --git a/docs/images/main.png b/docs/images/main.png index 6ee334d..78dcff8 100644 Binary files a/docs/images/main.png and b/docs/images/main.png differ diff --git a/journey.js.nuspec b/journey.js.nuspec index 9cb56fb..e002a87 100644 --- a/journey.js.nuspec +++ b/journey.js.nuspec @@ -2,7 +2,7 @@ jJourney.js - 0.2.1 + 0.3.0 Journey.js A lightweight, and easy-to-use, JavaScript library for building a website walk-through guide! William Troup diff --git a/package.json b/package.json index 6388e1c..2ad279a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "jjourney.js", "title": "Journey.js", "description": "A lightweight, and easy-to-use, JavaScript library for building a website walk-through guide!", - "version": "0.2.1", + "version": "0.3.0", "main": "dist/journey.js", "author": { "name": "Bunoon" diff --git a/src/journey.js b/src/journey.js index a9fa6ec..e88be39 100644 --- a/src/journey.js +++ b/src/journey.js @@ -4,7 +4,7 @@ * A lightweight, and easy-to-use, JavaScript library for building a website walk-through guide! * * @file journey.js - * @version v0.2.1 + * @version v0.3.0 * @author Bunoon * @license MIT License * @copyright Bunoon 2023 @@ -21,6 +21,13 @@ // Variables: Configuration _configuration = {}, + // Variables: Enums + _enum_KeyCodes = { + escape: 27, + left: 37, + right: 39 + }, + // Variables: Strings _string = { empty: "", @@ -117,15 +124,13 @@ } function onDialogPrevious() { - removeFocusClassFromLastElement(); + if ( _elements_Attributes_Position > 0 ) { + removeFocusClassFromLastElement(); - _elements_Attributes_Position--; + _elements_Attributes_Position--; - if ( _elements_Attributes_Position < 0 ) { - _elements_Attributes_Position = _elements_Attributes_Keys.length - 1; - } - - showDialogAndSetPosition(); + showDialogAndSetPosition(); + } } function onDialogNext() { @@ -259,6 +264,8 @@ if ( isDefinedNumber( bindingOptions.order ) && ( isDefinedString( bindingOptions.title ) || isDefinedString( bindingOptions.description ) ) ) { _elements_Attributes_Json[ bindingOptions.order ] = bindingOptions; _elements_Attributes_Keys.push( bindingOptions.order ); + + element.removeAttribute( _attribute_Name_Journey ); } } else { @@ -280,6 +287,40 @@ } + /* + * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Document Events + * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + + function buildDocumentEvents( addEvents ) { + addEvents = isDefined( addEvents ) ? addEvents : true; + + var documentFunc = addEvents ? _parameter_Document.addEventListener : _parameter_Document.removeEventListener; + + if ( _configuration.shortcutKeysEnabled ) { + documentFunc( "keydown", onWindowKeyDown ); + } + } + + function onWindowKeyDown( e ) { + if ( _this.isOpen() ) { + if ( e.keyCode === _enum_KeyCodes.escape ) { + e.preventDefault(); + onDialogClose(); + + } else if ( e.keyCode === _enum_KeyCodes.left ) { + e.preventDefault(); + onDialogPrevious(); + + } else if ( e.keyCode === _enum_KeyCodes.right ) { + e.preventDefault(); + onDialogNext(); + } + } + } + + /* * ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Options @@ -559,6 +600,7 @@ _configuration.nextButtonText = getDefaultString( _configuration.nextButtonText, "Next" ); _configuration.finishButtonText = getDefaultString( _configuration.finishButtonText, "Finish" ); _configuration.showCloseButton = getDefaultBoolean( _configuration.showCloseButton, true ); + _configuration.shortcutKeysEnabled = getDefaultBoolean( _configuration.shortcutKeysEnabled, true ); } @@ -637,7 +679,7 @@ * @returns {string} The version number. */ this.getVersion = function() { - return "0.2.1"; + return "0.3.0"; }; @@ -657,6 +699,7 @@ renderDisabledBackground(); renderDialog(); getElements(); + buildDocumentEvents(); } ); if ( !isDefined( _parameter_Window.$journey ) ) { diff --git a/src/journey.js.scss b/src/journey.js.scss index 0e256be..f25b686 100644 --- a/src/journey.js.scss +++ b/src/journey.js.scss @@ -1,5 +1,5 @@ /* - * Journey.js Library v0.2.1 + * Journey.js Library v0.3.0 * * Copyright 2023 Bunoon * Released under the MIT License @@ -34,13 +34,19 @@ --dialog-button-hover-text-color: var(--dialog-button-text-color); // Dialog - Buttons - Disabled - --dialog-button-disabled-background-color: #002244; + --dialog-button-disabled-background-color: var(--dialog-background-color); // Dialog - Close Button - --dialog-close-button-color: var(--color-white); - --dialog-close-button-hover-color: var(--dialog-button-hover-background-color); + --dialog-close-button-background-color: var(--dialog-button-background-color); + --dialog-close-button-border-color: #3457D5; --dialog-close-button-size: 1.1rem; - + --dialog-close-button-x-color: var(--color-white); + + // Dialog - Close Button - Hover + --dialog-close-button-hover-background-color: #007FFF; + --dialog-close-button-hover-x-color: var(--dialog-close-button-x-color); + --dialog-close-button-hover-border-color: var(--dialog-close-button-border-color); + // Borders --border-radius: 0.5rem; --border-size: 0.5px; @@ -84,15 +90,15 @@ div.journey-js-dialog { height: var(--dialog-close-button-size); border-radius: 0.25rem; padding: 0; - background-color: transparent; - border: var(--border-size) solid var(--dialog-close-button-color); + background-color: var(--dialog-close-button-background-color); + border: var(--border-size) solid var(--dialog-close-button-border-color); &::before, &::after { content: ''; width: 1px; height: 100%; - background: var(--dialog-close-button-color); + background: var(--dialog-close-button-x-color); display: block; transform: rotate(45deg) translateX(0px); position: absolute; @@ -106,12 +112,13 @@ div.journey-js-dialog { &:hover { cursor: pointer; - border: var(--border-size) solid var(--dialog-close-button-hover-color); + border: var(--border-size) solid var(--dialog-close-button-hover-border-color); transition: var(--transition); + background-color: var(--dialog-close-button-hover-background-color); &::before, &::after { - background: var(--dialog-close-button-hover-color); + background: var(--dialog-close-button-hover-x-color); transition: var(--transition); } }