Multiple Codemirror instances - javascript

I can create and display multiple dynamic codemirror instances, but I CANT reference them with the below code. Think the issue is that I need to create a dynamic function name. (Not 100% on how to do so here)
var function (somefilename, xml){
var instanceName = somefilename + 'Editor';
require([
'codemirror/lib/codemirror','codemirror/mode/xml/xml',
'codemirror/addon/search/search'
], function(CodeMirror) {
instanceName = CodeMirror.fromTextArea(document.getElementById(somefilename + 'xml'), {
lineNumbers: true,
mode: 'xml'
});
instanceName.setValue(xml);
instanceName.focus();
});
};

I actually was going about this the wrong way and should have been utilizing an object to store said multiple instances. Which of course gives me the ability to reference ANY stored records.
Hope this helps someone in the future!
//Create your object to store multiple instances of CodeMirror
var cmInstances = {}
function createInstance(someId) {
In my case I will be using requirejs to load 'on demand'
require([
'codemirror/lib/codemirror', 'codemirror/mode/xml/xml',
'codemirror/addon/search/search'
], function(CodeMirror) {
So what I'm doing below is creating a instance of the Codemirror object within my object. That essentially keys to the ID I've previously passed in the function (ie: 'someId). Also before I called the below I've had a previous function create a 'textarea' that I've injected into the page named '#someID_xml'. Hence the reference for getElementByID
cmInstances[someId] = CodeMirror.fromTextArea(document.getElementById(someId + '_xml'), {
lineNumbers: true,
mode: 'xml'
});
});
};

Related

How to get to "extended" prototype properties or function in JavaScript? Common practice in jQuery pliugins

I'm beginner with OOP in JavaScript. I've tried few things but its obvious that i don't understand code.
Here's my problem:
I have a plugin for showing calendar - glDataPicker. It is initialised on input tag like this:
$('#my_input_id').glDatePicker();//parameters may be passed
So i am assuming that after deploying script to my site glDatePicker.min.js inputs in DOM got new method glDatePicker? Am i right here?
Then it has hide and show methods defined:
// Public methods
glDatePicker.prototype =
{
show: function() {
// Hide others and show this calendar
$.each($('.gldp-el').not(this.el), function(i, o) {
if(o.length) { o.options.onHide(o.calendar) ; }
});
// Show this calendar
this.options.onShow(this.calendar);
},
hide: function() {
if(this.options && !this.options.showAlways) {
this.options.onHide(this.calendar);
}
},
So my question is how can I call method `hide' from outside the plugin code?
I've tried:
$('#my_input_id').glDatePicker().calendar.hide()
-> Cannot read property 'hide' of undefined(…)
and so on but i can't hide the calendar. How can i get to this method from global context?
Try this :
$('[gldp-el='+ $('#my_input_id').attr('gldp-id') +']').hide()
$('[gldp-el='+ $('#my_input_id').attr('gldp-id') +']').show()
ok, I have found, what I need:
// Doing it in a single pass
var myDatePicker = $('#example1').glDatePicker(
{
showAlways: true,
selectableDOW: [0, 2, 3]
}).glDatePicker(true);
// Or you can do it with multiple calls
$('example1').glDatePicker(
{
showAlways: true,
selectableDOW: [0, 2, 3]
});
var myDatePicker = $('example1').glDatePicker(true);
now I can:
myDatePicker.hide();
so that menas that first glDatePicker doesn't reutrn object.

dynamic call to a function jQuery

I am trying to build a lib and I need to call functions dynamically depending on the variables I have in parameter like this
strategies = min
function dispatchRuleToStrategy(strategies)
{
$.each(strategies, function(index, value) {
strategy = "strategy_" + value;
});
}
function strategy_min()
{
// do something
}
How can I call the function strategy_min() from dispatchRuleToStrategy()?
I've been trying a couple of things none of which are working.
Thanks for your help
Use an Object to create a dictionary of your functions e.g. lib
var lib = {
'strategy_min': strategy_min
};
then you can invoke via the key in this dictionary Object
lib['strategy_min']();
If you've named all your functions and you don't want to re-type the names over and over, you could
var lib = {};
function addToLib(fn) {
lib[fn.name] = fn;
}
// then
addToLib(strategy_min);
// or
[strategy_min].forEach(addToLib);
Put them in an object and use the property name:
var strategy_table = {
min: function() {
// do something
},
max: function() {
// do something else
},
...
};
Then you can access them as strategy_table[value]:
$.each(strategies, function(index, value) {
strategy_table[value]();
});
Others have already suggested to create a wrapper object for the functions, however, if your strategy_min() function is in the global scope, you can access it directly:
window['strategy_' + value]();
window in browsers refers to the global object. The bracket notation is used to access properties whose keys are dynamically generated. This way you are accessing the function, which is a property of the global object, i.e. window, and calling it using the parentheses.
Finally I found the real problem. I was in a jquery document ready which is a closure. I did not knew what closures were before today.
Thanks all for your help
You can use eval() function in the following manner
$.each(strategies, function(index, value) {
strategy = "strategy_" + value;
eval(strategy+"()");
});

how to assign a variable value to another variable instead of reference dojo javascript

I m trying to change stores of dijit/form/select on fly. For that purpose, I need to retrieve a store from server. I need to save this store in some temporary store, and make changes to temporary store in my code.
In my code below, requiredStore has the data received from server.
I need to create a new temporary store, in my case temporaryStore, that can be assiged data in requiredStore.(instead of temporaryStore being a reference to requiredStore)So that, when I remove/change values in temporaryStore, requiredStore is not affected. The following is the code, I have used.
function getDropDownContents() {
require([
"dojo/store/Memory",
"dijit/form/Select",
"dojo/data/ObjectStore",
"dojo/request",
"dojo/domReady!"
],
function (Memory, Select, ObjectStore, request) {
var os;
var def = new dojo.Deferred();
dojo.xhrGet({
url: "pageToGetValues.aspx",
handleAs: "json",
load: function (res) {
requiredStore = new Memory({ data: res });
temporaryStore = requiredStore;
getOptionsToSelect('dropdown1');
var select = dijit.byId('dropdown1');
select.on('change', function (evt) {
getOptionsToSelect('dropdown2');
});
myFormDialog.show();
}
});
});
}
But, I don't know, what javaScript principles I m not following, coz , when I m changing temporaryStore, requiredStore is also getting changed.
You need to either do a deep clone of requiredStore (going through properties and prototype to create a perfect duplicate), or else just create a different memory store altogether:
requiredStore = new Memory({ data:res });
temporaryStore = new Memory({ data: res });
I don't know why you wouldn't use this approach, but if you want to do a deep clone this question will help:
What is the most efficient way to deep clone an object in JavaScript?

Accessing object literals in Javascript

This code is an example from Marionette:
AppLayout = Backbone.Marionette.Layout.extend(
{
template: "#layout-template",
regions:
{
menu: "#menu",
content: "#content"
}
});
var layout = new AppLayout();
layout.menu.show(new MenuView());
layout.content.show(new MainContentView());
The last two lines confuse me. Why doesn't it read:
layout.regions.menu.show(new MenuView());
layout.regions.content.show(new MainContentView());
Can someone please explain why layout.menu works and layout.regions.menu doesn't?
What if I wanted to access template? Wouldn't that be layout.template? template and regions are at the same depth inside layout.
Here is the constructor function from the marionette code:
// Ensure the regions are avialable when the `initialize` method
// is called.
constructor: function () {
this._firstRender = true;
this.initializeRegions();
var args = Array.prototype.slice.apply(arguments);
Marionette.ItemView.apply(this, args);
},
I believe it was implemented that way because 'layout.menu' is shorter and simpler than 'layout.regions.menu'. Looks like you expected the literal "#menu" to be replaced with a region manager object.
The options you passed in when creating the view, including the template, can be found in layout.options. So in your case layout.options.template should equal '#layout-template', and the regions definition hash would be at layout.options.regions... still the same level.
Unless there is more to the example then you are showing like the Backbone.Marionette.Layout methods, then its not accessing regions.menu like you think it is.
With just the code you have provided the code above is actually creating a menu attribute, which then has a show attribute so your layout object would actually look like this:
layout {
menu : {
show : new MenuView
},
content : {
show : new MainContentView
},
template: "#layout-template",
regions:
{
menu: "#menu",
content: "#content"
}
}
In javascript the (dot) operator can be used to access a property of an attribute or if no property with that name exists then it will create that property.
I'm not familiar with the backbone.js framework but my guess is that they provide for skipping part of the property lookup chain. which means that the above would end up producing this as your layout object:
layout {
template: "#layout-template",
regions:
{
menu : {
show : new MenuView
},
content : {
show : new MainContentView
}
}
}
But again that's just a guess on my part since I don't use backbone.
You can learn more about the object model and how it works with inheritance right here.

Variable function names in Require & Backbone

I'm using Require.js and Backbone, and have a Backbone router module like:
define([
"views/global",
"views/project/edit",
"views/project/list",
], function(GlobalView, edit, list){
return Backbone.Router.extend({
routes: {
"projects/:action/" : "projectsAction",
},
projectsAction : function(action) {
/* .... lots of code cut out here .... */
/* Create and render the action specified */
this.subView = new eval(action+"()").render();
}
});
});
This is an example, I've cut a lot of setup code out of projectAction.
I would like the URL: /projects/list to run projectAction, with the action param = list, and then the list module from the Require.js function to be called. I'm currently doing it with eval(), but I'm wondering if there is a better way?
Basically, in Javascript, can you refer to a variable, with another variable name, without using eval()?
I guess a shorter version would be, how do you do:
var name = "Math.random";
name(); // = 0.34343....
Without eval()?
You cannot access a variable having the name in a string. But you can create a mapping:
var actions = {
edit: edit,
list: list
};
And then you can access the function by the key:
projectsAction : function(action) {
this.subView = new actions[action]().render();
}
The best way imo, is to use the require function of requirejs:
projectsAction : function(action) {
/* .... lots of code cut out here .... */
/* Create and render the action specified */
var self = this;
require('views/project/' + action, function(view) {
(self.subView = new view).render();
}
}
As it would also cut the boilerplate from having lots of actions.

Categories