refactored settings menu extension
This commit is contained in:
parent
60616deec0
commit
408b190bb0
3 changed files with 440 additions and 327 deletions
272
lib/ace/ext/menu_tools/generate_settings_menu.js
Normal file
272
lib/ace/ext/menu_tools/generate_settings_menu.js
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributed to Ajax.org under the BSD license.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*jslint
|
||||
indent: 4,
|
||||
maxerr: 50,
|
||||
white: true,
|
||||
browser: true,
|
||||
vars: true
|
||||
*/
|
||||
/*global
|
||||
define
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates the settings menu
|
||||
* @fileOverview Generates the settings menu.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
/**
|
||||
* Generates an interactive menu with settings useful to end users.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {ace.Editor} editor An instance of the ace editor.
|
||||
*/
|
||||
module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
|
||||
var addEditorMenuOptions = require('./add_editor_menu_options').addEditorMenuOptions;
|
||||
var getSetFunctions = require('./get_set_functions').getSetFunctions;
|
||||
/**
|
||||
* container for dom elements that will go in the menu.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var elements = [];
|
||||
/**
|
||||
* Sorts the menu entries (elements var) so they'll appear in alphabetical order
|
||||
* the sort is performed based on the value of the contains property
|
||||
* of each element. Since this is an `array.sort` the array is sorted
|
||||
* in place.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
function cleanupElementsList() {
|
||||
elements.sort(function (a, b) {
|
||||
var x = a.getAttribute('contains');
|
||||
var y = b.getAttribute('contains');
|
||||
return x.localeCompare(y);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Wraps all dom elements contained in the elements var with a single
|
||||
* div.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
function wrapElements() {
|
||||
var topmenu = document.createElement('div');
|
||||
topmenu.setAttribute('id', 'settingsmenu');
|
||||
elements.forEach(function (element) {
|
||||
topmenu.appendChild(element);
|
||||
});
|
||||
return topmenu;
|
||||
}
|
||||
/**
|
||||
* Creates a new menu entry.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {object} obj This is a reference to the object containing the
|
||||
* set function. It is used to set up event listeners for when the
|
||||
* menu options change.
|
||||
* @param {string} clss Maps to the class of the dom element. This is
|
||||
* the name of the object containing the set function e.g. `editor`,
|
||||
* `session`, `renderer`.
|
||||
* @param {string} item This is the set function name. It maps to the
|
||||
* id of the dom element (check, select, input) and to the "contains"
|
||||
* attribute of the div holding both the element and its label.
|
||||
* @param {mixed} val This is the value of the setting. It is mapped to
|
||||
* the dom element's value, checked, or selected option accordingly.
|
||||
*/
|
||||
function createNewEntry(obj, clss, item, val) {
|
||||
var egen = require('./element_generator');
|
||||
var el;
|
||||
var div = document.createElement('div');
|
||||
div.setAttribute('contains', item);
|
||||
div.setAttribute('class', 'menuEntry');
|
||||
div.setAttribute('style', 'clear: both;');
|
||||
|
||||
div.appendChild(egen.createLabel(
|
||||
item.replace(
|
||||
/^set/, ''
|
||||
).replace(
|
||||
/([A-Z])/g, ' $1'
|
||||
).trim(),
|
||||
item
|
||||
));
|
||||
|
||||
if(Array.isArray(val)) {
|
||||
el = egen.createSelection(item, val, clss);
|
||||
el.addEventListener('change', function (e) {
|
||||
try{
|
||||
editor.menuOptions[e.target.id].forEach(function (x) {
|
||||
if(x.textContent !== e.target.textContent) {
|
||||
delete x.selected;
|
||||
}
|
||||
});
|
||||
// editor.session['setMode']('ace/mode/javascript')
|
||||
obj[e.target.id](e.target.value);
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
} else if(typeof val === 'boolean') {
|
||||
el = egen.createCheckbox(item, val, clss);
|
||||
el.addEventListener('change', function (e) {
|
||||
try{
|
||||
// renderer['setHighlightGutterLine'](true);
|
||||
obj[e.target.id](!!e.target.checked);
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// this aids in giving the ability to specify settings through
|
||||
// post and get requests.
|
||||
// /ace_editor.html?setMode=ace/mode/html&setOverwrite=true
|
||||
el = egen.createInput(item, val, clss);
|
||||
el.addEventListener('blur', function (e) {
|
||||
try{
|
||||
if(e.target.value === 'true') {
|
||||
obj[e.target.id](true);
|
||||
} else if(e.target.value === 'false') {
|
||||
obj[e.target.id](false);
|
||||
} else {
|
||||
obj[e.target.id](e.target.value);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
el.style.cssText = 'float:right;';
|
||||
div.appendChild(el);
|
||||
return div;
|
||||
}
|
||||
/**
|
||||
* Generates selection fields for the menu and populates their options
|
||||
* using information from `editor.menuOptions`
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {string} item The set function name.
|
||||
* @param {object} esr A reference to the object having the set function.
|
||||
* @param {string} clss The name of the object containing the set function.
|
||||
* @param {string} fn The matching get function's function name.
|
||||
* @returns {DOMElement} Returns a dom element containing a selection
|
||||
* element populated with options. The option whose value matches that
|
||||
* returned from `esr[fn]()` will be selected.
|
||||
*/
|
||||
function makeDropdown(item, esr, clss, fn) {
|
||||
var val = editor.menuOptions[item];
|
||||
val = val.map(function (valuex) {
|
||||
if(valuex.value === esr[fn]()) {
|
||||
valuex.selected = 'selected';
|
||||
} else if(valuex.value === esr.$modeId) {
|
||||
// is mode
|
||||
valuex.selected = 'selected';
|
||||
}
|
||||
return valuex;
|
||||
});
|
||||
return createNewEntry(esr, clss, item, val);
|
||||
}
|
||||
/**
|
||||
* Processes the set functions returned from `getSetFunctions`. First it
|
||||
* checks for menu options defined in `editor.menuOptions`. If no
|
||||
* options are specified then it checks whether there is a get function
|
||||
* (replace set with get) for the setting. When either of those
|
||||
* conditions are met it will attempt to create a new entry for the
|
||||
* settings menu and push it into the elements array defined above.
|
||||
* It can only do so for get functions which return
|
||||
* strings, numbers, and booleans. A special case is written in for
|
||||
* `getMode` where it looks at the returned objects `$id` property and
|
||||
* forwards that through instead. Other special cases could be written
|
||||
* in but that would get a bit ridiculous.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {object} setObj An item from the array returned by
|
||||
* `getSetFunctions`.
|
||||
*/
|
||||
function handleSet (setObj) {
|
||||
var item = setObj.functionName;
|
||||
var esr = setObj.parentObj;
|
||||
var clss = setObj.parentName;
|
||||
var val;
|
||||
var fn = item.replace(/^set/, 'get');
|
||||
if(editor.menuOptions[item] !== undefined) {
|
||||
// has options for select element
|
||||
elements.push(makeDropdown(item, esr, clss, fn));
|
||||
} else if(typeof esr[fn] === 'function') {
|
||||
// has get function
|
||||
try {
|
||||
val = esr[fn]();
|
||||
if(typeof val === 'object') {
|
||||
// setMode takes a string, getMode returns an object
|
||||
// the $id property of that object is the string
|
||||
// which may be given to setMode...
|
||||
val = val.$id;
|
||||
}
|
||||
// the rest of the get functions return strings,
|
||||
// booleans, or numbers.
|
||||
elements.push(
|
||||
createNewEntry(esr, clss, item, val)
|
||||
);
|
||||
} catch (e) {
|
||||
// if there are errors it is because the element
|
||||
// does not belong in the settings menu
|
||||
}
|
||||
}
|
||||
}
|
||||
addEditorMenuOptions(editor);
|
||||
// gather the set functions
|
||||
getSetFunctions(editor).forEach(function (setObj) {
|
||||
// populate the elements array with good stuff.
|
||||
handleSet(setObj);
|
||||
});
|
||||
// sort the menu entries in the elements list so people can find
|
||||
// the settings in alphabetical order.
|
||||
cleanupElementsList();
|
||||
// dump the entries from the elements list and wrap them up in a div
|
||||
return wrapElements();
|
||||
};
|
||||
|
||||
});
|
||||
155
lib/ace/ext/menu_tools/get_set_functions.js
Normal file
155
lib/ace/ext/menu_tools/get_set_functions.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributed to Ajax.org under the BSD license.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*jslint
|
||||
indent: 4,
|
||||
maxerr: 50,
|
||||
white: true,
|
||||
browser: true,
|
||||
vars: true
|
||||
*/
|
||||
/*global
|
||||
define
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get Set Functions
|
||||
* @fileOverview Get Set Functions <br />
|
||||
* Gets various functions for setting settings.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
/**
|
||||
* Generates a list of set functions for the settings menu.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {object} editor The editor instance
|
||||
* @return {array} Returns an array of objects. Each object contains the
|
||||
* following properties: functionName, parentObj, and parentName. The
|
||||
* function name will be the name of a method beginning with the string
|
||||
* `set` which was found. The parent object will be a reference to the
|
||||
* object having the method matching the function name. The parent name
|
||||
* will be a string representing the identifier of the parent object e.g.
|
||||
* `editor`, `session`, or `renderer`.
|
||||
*/
|
||||
module.exports.getSetFunctions = function getSetFunctions (editor) {
|
||||
/**
|
||||
* Output array. Will hold the objects described above.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var out = [];
|
||||
/**
|
||||
* This object provides a map between the objects which will be
|
||||
* traversed and the parent name which will appear in the output.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var my = {
|
||||
'editor' : editor,
|
||||
'session' : editor.session,
|
||||
'renderer' : editor.renderer
|
||||
};
|
||||
/**
|
||||
* This array will hold the set function names which have already been
|
||||
* found so that they are not added to the output multiple times.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var opts = [];
|
||||
/**
|
||||
* This is a list of set functions which will not appear in the settings
|
||||
* menu. I don't know what to do with setKeyboardHandler. When I tried
|
||||
* to use it, it didn't appear to be working. Someone who knows better
|
||||
* could remove it from this list and add it's options to
|
||||
* add_editor_menu_options.js
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var skip = [
|
||||
'setOption',
|
||||
'setUndoManager',
|
||||
'setDocument',
|
||||
'setValue',
|
||||
'setBreakpoints',
|
||||
'setScrollTop',
|
||||
'setScrollLeft',
|
||||
'setSelectionStyle',
|
||||
'setWrapLimitRange',
|
||||
'setKeyboardHandler'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* This will search the objects mapped to the `my` variable above. When
|
||||
* it finds a set function in the object that is not listed in the
|
||||
* `skip` list or the `opts` list it will push a new object to the
|
||||
* output array.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
[
|
||||
'renderer',
|
||||
'session',
|
||||
'editor'
|
||||
].forEach(function (esra) {
|
||||
var fn;
|
||||
var esr = my[esra];
|
||||
var clss = esra;
|
||||
for(fn in esr) {
|
||||
if(skip.indexOf(fn) === -1) {
|
||||
if(/^set/.test(fn) && opts.indexOf(fn) === -1) {
|
||||
// found set function
|
||||
opts.push(fn);
|
||||
out.push({
|
||||
'functionName' : fn,
|
||||
'parentObj' : esr,
|
||||
'parentName' : clss
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return out;
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -55,344 +55,30 @@
|
|||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
var Editor = require("ace/editor").Editor;
|
||||
var overlayPage = require('./menu_tools/overlay_page').overlayPage;
|
||||
var addEditorMenuOptions = require('./menu_tools/add_editor_menu_options').addEditorMenuOptions;
|
||||
|
||||
/**
|
||||
* Generates a list of set functions for the settings menu.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {object} editor The editor instance
|
||||
* @return {array} Returns an array of objects. Each object contains the
|
||||
* following properties: functionName, parentObj, and parentName. The
|
||||
* function name will be the name of a method beginning with the string
|
||||
* `set` which was found. The parent object will be a reference to the
|
||||
* object having the method matching the function name. The parent name
|
||||
* will be a string representing the identifier of the parent object e.g.
|
||||
* `editor`, `session`, or `renderer`.
|
||||
*/
|
||||
function getSetFunctions (editor) {
|
||||
/**
|
||||
* Output array. Will hold the objects described above.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var out = [];
|
||||
/**
|
||||
* This object provides a map between the objects which will be
|
||||
* traversed and the parent name which will appear in the output.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var my = {
|
||||
'editor' : editor,
|
||||
'session' : editor.session,
|
||||
'renderer' : editor.renderer
|
||||
};
|
||||
/**
|
||||
* This array will hold the set function names which have already been
|
||||
* found so that they are not added to the output multiple times.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var opts = [];
|
||||
/**
|
||||
* This is a list of set functions which will not appear in the settings
|
||||
* menu. I don't know what to do with setKeyboardHandler. When I tried
|
||||
* to use it, it didn't appear to be working. Someone who knows better
|
||||
* could remove it from this list and add it's options to
|
||||
* add_editor_menu_options.js
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var skip = [
|
||||
'setOption',
|
||||
'setUndoManager',
|
||||
'setDocument',
|
||||
'setValue',
|
||||
'setBreakpoints',
|
||||
'setScrollTop',
|
||||
'setScrollLeft',
|
||||
'setSelectionStyle',
|
||||
'setWrapLimitRange',
|
||||
'setKeyboardHandler'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* This will search the objects mapped to the `my` variable above. When
|
||||
* it finds a set function in the object that is not listed in the
|
||||
* `skip` list or the `opts` list it will push a new object to the
|
||||
* output array.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
[
|
||||
'renderer',
|
||||
'session',
|
||||
'editor'
|
||||
].forEach(function (esra) {
|
||||
var fn;
|
||||
var esr = my[esra];
|
||||
var clss = esra;
|
||||
for(fn in esr) {
|
||||
if(skip.indexOf(fn) === -1) {
|
||||
if(/^set/.test(fn) && opts.indexOf(fn) === -1) {
|
||||
// found set function
|
||||
opts.push(fn);
|
||||
out.push({
|
||||
'functionName' : fn,
|
||||
'parentObj' : esr,
|
||||
'parentName' : clss
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
/**
|
||||
* Generates an interactive menu with settings useful to end users.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {ace.Editor} editor An instance of the ace editor.
|
||||
*/
|
||||
function generateMenu (editor) {
|
||||
/**
|
||||
* container for dom elements that will go in the menu.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
var elements = [];
|
||||
/**
|
||||
* Sorts the menu entries (elements var) so they'll appear in alphabetical order
|
||||
* the sort is performed based on the value of the contains property
|
||||
* of each element. Since this is an `array.sort` the array is sorted
|
||||
* in place.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
function cleanupElementsList() {
|
||||
elements.sort(function (a, b) {
|
||||
var x = a.getAttribute('contains');
|
||||
var y = b.getAttribute('contains');
|
||||
return x.localeCompare(y);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Wraps all dom elements contained in the elements var with a single
|
||||
* div.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
*/
|
||||
function wrapElements() {
|
||||
var topmenu = document.createElement('div');
|
||||
topmenu.setAttribute('id', 'settingsmenu');
|
||||
elements.forEach(function (element) {
|
||||
topmenu.appendChild(element);
|
||||
});
|
||||
return topmenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new menu entry.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {object} obj This is a reference to the object containing the
|
||||
* set function. It is used to set up event listeners for when the
|
||||
* menu options change.
|
||||
* @param {string} clss Maps to the class of the dom element. This is
|
||||
* the name of the object containing the set function e.g. `editor`,
|
||||
* `session`, `renderer`.
|
||||
* @param {string} item This is the set function name. It maps to the
|
||||
* id of the dom element (check, select, input) and to the "contains"
|
||||
* attribute of the div holding both the element and its label.
|
||||
* @param {mixed} val This is the value of the setting. It is mapped to
|
||||
* the dom element's value, checked, or selected option accordingly.
|
||||
*/
|
||||
function createNewEntry(obj, clss, item, val) {
|
||||
var egen = require('./menu_tools/element_generator');
|
||||
var el;
|
||||
var div = document.createElement('div');
|
||||
div.setAttribute('contains', item);
|
||||
div.setAttribute('class', 'menuEntry');
|
||||
div.setAttribute('style', 'clear: both;');
|
||||
|
||||
div.appendChild(egen.createLabel(
|
||||
item.replace(
|
||||
/^set/, ''
|
||||
).replace(
|
||||
/([A-Z])/g, ' $1'
|
||||
).trim(),
|
||||
item
|
||||
));
|
||||
|
||||
if(Array.isArray(val)) {
|
||||
el = egen.createSelection(item, val, clss);
|
||||
el.addEventListener('change', function (e) {
|
||||
try{
|
||||
editor.menuOptions[e.target.id].forEach(function (x) {
|
||||
if(x.textContent !== e.target.textContent) {
|
||||
delete x.selected;
|
||||
}
|
||||
});
|
||||
// editor.session['setMode']('ace/mode/javascript')
|
||||
obj[e.target.id](e.target.value);
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
} else if(typeof val === 'boolean') {
|
||||
el = egen.createCheckbox(item, val, clss);
|
||||
el.addEventListener('change', function (e) {
|
||||
try{
|
||||
// renderer['setHighlightGutterLine'](true);
|
||||
obj[e.target.id](!!e.target.checked);
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// this aids in giving the ability to specify settings through
|
||||
// post and get requests.
|
||||
// /ace_editor.html?setMode=ace/mode/html&setOverwrite=true
|
||||
el = egen.createInput(item, val, clss);
|
||||
el.addEventListener('blur', function (e) {
|
||||
try{
|
||||
if(e.target.value === 'true') {
|
||||
obj[e.target.id](true);
|
||||
} else if(e.target.value === 'false') {
|
||||
obj[e.target.id](false);
|
||||
} else {
|
||||
obj[e.target.id](e.target.value);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
el.style.cssText = 'float:right;';
|
||||
div.appendChild(el);
|
||||
return div;
|
||||
}
|
||||
/**
|
||||
* Generates selection fields for the menu and populates their options
|
||||
* using information from `editor.menuOptions`
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {string} item The set function name.
|
||||
* @param {object} esr A reference to the object having the set function.
|
||||
* @param {string} clss The name of the object containing the set function.
|
||||
* @param {string} fn The matching get function's function name.
|
||||
* @returns {DOMElement} Returns a dom element containing a selection
|
||||
* element populated with options. The option whose value matches that
|
||||
* returned from `esr[fn]()` will be selected.
|
||||
*/
|
||||
function makeDropdown(item, esr, clss, fn) {
|
||||
var val = editor.menuOptions[item];
|
||||
val = val.map(function (valuex) {
|
||||
if(valuex.value === esr[fn]()) {
|
||||
valuex.selected = 'selected';
|
||||
} else if(valuex.value === esr.$modeId) {
|
||||
// is mode
|
||||
valuex.selected = 'selected';
|
||||
}
|
||||
return valuex;
|
||||
});
|
||||
return createNewEntry(esr, clss, item, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the set functions returned from `getSetFunctions`. First it
|
||||
* checks for menu options defined in `editor.menuOptons`. If no
|
||||
* options are specified then it checks whether there is a get function
|
||||
* (replace set with get) for the setting. When either of those
|
||||
* conditions are met it will attempt to create a new entry for the
|
||||
* settings menu and push it into the elements array defined above.
|
||||
* It can only do so for get functions which return
|
||||
* strings, numbers, and booleans. A special case is written in for
|
||||
* `getMode` where it looks at the returned objects `$id` property and
|
||||
* forwards that through instead. Other special cases could be written
|
||||
* in but that would get a bit ridiculous.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {object} setObj An item from the array returned by
|
||||
* `getSetFunctions`.
|
||||
*/
|
||||
function handleSet (setObj) {
|
||||
var item = setObj.functionName;
|
||||
var esr = setObj.parentObj;
|
||||
var clss = setObj.parentName;
|
||||
var val;
|
||||
var fn = item.replace(/^set/, 'get');
|
||||
if(editor.menuOptions[item] !== undefined) {
|
||||
// has options for select element
|
||||
elements.push(makeDropdown(item, esr, clss, fn));
|
||||
} else if(typeof esr[fn] === 'function') {
|
||||
// has get function
|
||||
try {
|
||||
val = esr[fn]();
|
||||
if(typeof val === 'object') {
|
||||
// setMode takes a string, getMode returns an object
|
||||
// the $id property of that object is the string
|
||||
// which may be given to setMode...
|
||||
val = val.$id;
|
||||
}
|
||||
// the rest of the get functions return strings,
|
||||
// booleans, or numbers.
|
||||
elements.push(
|
||||
createNewEntry(esr, clss, item, val)
|
||||
);
|
||||
} catch (e) {
|
||||
// if there are errors it is because the element
|
||||
// does not belong in the settings menu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gather the set functions
|
||||
getSetFunctions(editor).forEach(function (setObj) {
|
||||
// populate the elements array with good stuff.
|
||||
handleSet(setObj);
|
||||
});
|
||||
// sort the menu entries in the elements list so people can find
|
||||
// the settings in alphabetical order.
|
||||
cleanupElementsList();
|
||||
// dump the entries from the elements list and wrap them up in a div
|
||||
// then put the div into the generic menu and show it.
|
||||
overlayPage(editor, wrapElements(), '0', '0', '0');
|
||||
}
|
||||
/**
|
||||
* This builds the settings menu and selects
|
||||
* all the options currently in effect.
|
||||
* This displays the settings menu if it is not already being shown.
|
||||
* @author <a href="mailto:matthewkastor@gmail.com">
|
||||
* Matthew Christopher Kastor-Inare III </a><br />
|
||||
* ☭ Hial Atropa!! ☭
|
||||
* @param {ace.Editor} editor An instance of the ace editor.
|
||||
*/
|
||||
function showSettingsMenu (editor) {
|
||||
var overlayPage = require('./menu_tools/overlay_page').overlayPage;
|
||||
var generateSettingsMenu = require(
|
||||
'./menu_tools/generate_settings_menu').generateSettingsMenu;
|
||||
// make sure the menu isn't open already.
|
||||
if(!document.getElementById('settingsmenu')) {
|
||||
addEditorMenuOptions(editor);
|
||||
generateMenu(editor);
|
||||
overlayPage(editor, generateSettingsMenu(editor), '0', '0', '0');
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* Initializes the settings menu extension. It adds the showSettingsMenu
|
||||
* method to the given editor object and adds the showSettingsMenu command
|
||||
* to the editor with appropriate keyboard shortcuts.
|
||||
* @param {ace.Editor} editor An instance of the Editor.
|
||||
*/
|
||||
module.exports.init = function (editor) {
|
||||
var Editor = require("ace/editor").Editor;
|
||||
Editor.prototype.showSettingsMenu = function () {
|
||||
showSettingsMenu(this);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue