diff --git a/doc/api/embed_parameters.md b/doc/api/embed_parameters.md index d6f27af05..9ca0d429a 100644 --- a/doc/api/embed_parameters.md +++ b/doc/api/embed_parameters.md @@ -73,3 +73,11 @@ Default: 0 Focuses pad at specific line number and places caret at beginning of this line Special note: Is not a URL parameter but instead of a Hash value +## focusOnEditor + * Boolean + +Default: true + +If true, focus on the editor upon initial page load. Set this to false if the +pad is embedded in an iframe adjacent to other editable content that should +retain focus. diff --git a/src/static/js/pad.js b/src/static/js/pad.js index ccf29cc57..eb392b0cb 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -49,6 +49,7 @@ const socketio = require('./socketio'); const hooks = require('./pluginfw/hooks'); let receivedClientVars = false; +let focusOnEditor = true; // This array represents all GET-parameters which can be used to change a setting. // name: the parameter-name, eg `?noColors=true` => `noColors` @@ -146,13 +147,17 @@ const getParameters = [ Cookies.set('language', val); }, }, + { + name: 'focusOnEditor', + callback: (val) => focusOnEditor = val !== 'false', + }, ]; const getParams = () => { // Tries server enforced options first.. for (const setting of getParameters) { const value = clientVars.padOptions[setting.name]; - if (value.toString() === setting.checkVal) { + if (value != null && value.toString() === setting.checkVal) { setting.callback(value); } } @@ -463,9 +468,7 @@ const pad = { const postAceInit = () => { padeditbar.init(); - setTimeout(() => { - padeditor.ace.focus(); - }, 0); + if (focusOnEditor) setTimeout(() => padeditor.ace.focus(), 0); // if we have a cookie for always showing chat then show it if (padcookie.getPref('chatAlwaysVisible')) { chat.stickToScreen(true); // stick it to the screen diff --git a/src/static/js/pad_editbar.js b/src/static/js/pad_editbar.js index 9d006d2c7..87baf45d3 100644 --- a/src/static/js/pad_editbar.js +++ b/src/static/js/pad_editbar.js @@ -262,7 +262,7 @@ exports.padeditbar = new class { } setEmbedLinks() { const padUrl = window.location.href.split('?')[0]; - const params = '?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false'; + const params = '?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false&focusOnEditor=false'; const props = 'width="100%" height="600" frameborder="0"'; if ($('#readonlyinput').is(':checked')) { diff --git a/src/tests/frontend/specs/embed_value.js b/src/tests/frontend/specs/embed_value.js index e92d070a7..30c03deff 100644 --- a/src/tests/frontend/specs/embed_value.js +++ b/src/tests/frontend/specs/embed_value.js @@ -35,6 +35,7 @@ describe('embed links', function () { showChat: 'true', showLineNumbers: 'true', useMonospaceFont: 'false', + focusOnEditor: 'false', }; // check the url diff --git a/src/tests/frontend/specs/focus.js b/src/tests/frontend/specs/focus.js new file mode 100644 index 000000000..f401dda85 --- /dev/null +++ b/src/tests/frontend/specs/focus.js @@ -0,0 +1,27 @@ +'use strict'; + +describe('caret focus', function () { + for (const params of [{}, {focusOnEditor: 'true'}, {focusOnEditor: 'false'}]) { + const wantFocus = params.focusOnEditor !== 'false'; + + describe(`focusOnEditor=${params.focusOnEditor}`, function () { + before(async function () { + await helper.aNewPad({params}); + }); + + it(`does${wantFocus ? '' : ' not'} focus`, async function () { + if (wantFocus) { + expect(helper.padChrome$.document.activeElement) + .to.be(helper.padChrome$.document.querySelector('iframe[name="ace_outer"]')); + expect(helper.padOuter$.document.activeElement) + .to.be(helper.padOuter$.document.querySelector('iframe[name="ace_inner"]')); + expect(helper.padInner$.document.activeElement) + .to.be(helper.padInner$.document.body); + } else { + expect(helper.padChrome$.document.activeElement) + .to.not.be(helper.padChrome$.document.querySelector('iframe[name="ace_outer"]')); + } + }); + }); + } +});