define( ['jquery', 'underscore', 'pgadmin', 'backbone', 'backform', 'alertify', 'pgadmin.browser.node'], function($, _, pgAdmin, Backbone, Backform, Alertify, Node) { var pgBrowser = pgAdmin.Browser; // Store value in DOM as stringified JSON. var StringOrJSONFormatter = function() {}; _.extend(StringOrJSONFormatter.prototype, { fromRaw: function(rawData, model) { return JSON.stringify(_.escape(rawData)); }, toRaw: function(formattedData, model) { if (typeof(formattedData) == 'string') { return _.unescape(formattedData); } return JSON.parse(formattedData); } }); /* * NodeAjaxOptionsControl * This control will fetch the options required to render the select * control, from the url specific to the pgAdmin.Browser node object. * * In order to use this properly, schema require to set the 'url' property, * which exposes the data for this node. * * In case the url is not providing the data in proper format, we can * specify the 'transform' function too, which will convert the fetched * data to proper 'label', 'value' format. */ var NodeAjaxOptionsControl = Backform.NodeAjaxOptionsControl = Backform.SelectControl.extend({ defaults: _.extend(Backform.SelectControl.prototype.defaults, { url: undefined, transform: undefined, url_with_id: false, first_empty: false, empty_value: '-- None --', select2: { allowClear: true, placeholder: 'Select from the list', width: 'style' } }), template: _.template([ '', '
', ' ', '
'].join("\n")), formatter: StringOrJSONFormatter, initialize: function() { /* * Initialization from the original control. */ Backform.SelectControl.prototype.initialize.apply(this, arguments); /* * We're about to fetch the options required for this control. */ var self = this, url = self.field.get('url') || self.defaults.url, m = self.model.top || self.model; // Hmm - we found the url option. // That means - we needs to fetch the options from that node. if (url) { var node = this.field.get('schema_node'), node_info = this.field.get('node_info'), full_url = node.generate_url.apply( node, [ null, url, this.field.get('node_data'), this.field.get('url_with_id') || false, node_info ]), cache_level = this.field.get('cache_level') || node.type, cache_node = this.field.get('cache_node'); cache_node = (cache_node && pgAdmin.Browser.Nodes['cache_node']) || node; /* * We needs to check, if we have already cached data for this url. * If yes - use that, and do not bother about fetching it again, * and use it. */ var data = cache_node.cache(url, node_info, cache_level); if (this.field.get('version_compitible') && (_.isUndefined(data) || _.isNull(data))) { m.trigger('pgadmin:view:fetching', m, self.field); $.ajax({ async: false, url: full_url, success: function(res) { /* * We will cache this data for short period of time for avoiding * same calls. */ data = cache_node.cache(url, node_info, cache_level, res.data); }, error: function() { m.trigger('pgadmin:view:fetch:error', m, self.field); } }); m.trigger('pgadmin:view:fetched', m, self.field); } // To fetch only options from cache, we do not need time from 'at' // attribute but only options. // // It is feasible that the data may not have been fetched. data = (data && data.data) || []; /* * Transform the data */ transform = this.field.get('transform') || self.defaults.transform; if (transform && _.isFunction(transform)) { // We will transform the data later, when rendering. // It will allow us to generate different data based on the // dependencies. self.field.set('options', transform.bind(self, data)); } else { self.field.set('options', data); } } }, render: function() { /* * Let SelectControl render it, we will do our magic on the * select control in it. */ Backform.SelectControl.prototype.render.apply(this, arguments); var d = this.field.toJSON(), select2_opts = _.defaults({}, d.select2, this.defaults.select2), evalF = function(f, d, m) { return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f); }; /* * If select2 options do not have any disabled property on this field * and schema has disabled property then we need to apply it */ if(!_.has(select2_opts, 'disabled') && (d && d.disabled)) { _.extend(select2_opts, { disabled: evalF(d.disabled, d, this.model) }); } /* * Add empty option as Select2 requires any empty '