Remoto - VFS: form.js Source File
Remoto - VFS
form.js
Go to the documentation of this file.
1 
2 define( [
3  'remoto!stdlib:js/panes/pane.js',
4  'remoto!stdlib:js/include/preferences.js',
5  'remoto!stdlib:js/widgets/widgetFactory.js',
6  'remoto!stdlib:js/paneManager/paneManager.js',
7  'remoto!stdlib:js/include/objectRegistry.js',
8  'remoto!stdlib:js/include/utils.js',
9  'remoto!stdlib:js/panes/panes/form.css',
10  ],
12  {
13  'use strict';
14 
34  form.prototype = new pane;
35  function form(layout)
36  {
37  pane.call(this, layout);
38 
39  if (!layout) return; //for the default constructor
40 
41  this._type = "form";
42 
43  this._attributes = {};
44  this._formJq = null;
45 
46  this._diffing = false; //don't report value changes while diff is being applied.
47  this._objectLoader = null;
48  this._useAttributes = false; //new style forms, or ones with base classes, use the attributes offset for fields... detect that.
49  this._context = {};
50 
51  this._enabledFilter = layout.enabledFilter || null; //only enable fields where this option is true or the filter is null
52  if (this._enabledFilter) //if there's a filter, remember to save it
53  this._saveFields["enabledFilter"] = this._enabledFilter;
54 
55  this._help = null;
56  this._wrapper = null; //don't remove! This is for formList panes
57 
58  //console.log(layout);
59  }
60 
69  form.prototype.createHTML = function(createHeader)
70  {
71  if (this._html) return this._html;
72 
73  pane.prototype.createHTML.call(this,createHeader);
74 
75  this._formJq = $("<div class='formCanvas'>").appendTo(this._content);
76 
77  return this._html;
78  }
79 
90  form.prototype.applySubscription = function(data,metadata)
91  {
92  //console.log("form apply subscription",arguments);
93 
94  if (this._subscribed)
95  { this.applyDiff(data,null);
96  return;
97  }
98 
99  this._subscribed = true;
100 
101  if (data.base || data.attributes)
102  { this._useAttributes = true;
103  //console.log(this);
104  //console.log(arguments);
105  if (metadata.context)
106  { this._context = metadata.context;
107  data = utils.resolveContextValues(data,metadata.context);
108  }
109 
110  if (!this._objectLoader)
111  this._objectLoader = new objectRegistry.objectLoader(metadata.nodeMenu || metadata.base || (metadata.context ? metadata.context.base : null) || "");
112  return this._objectLoader.fetchDefinition( data.base, data, this.applyDiff.bind(this) );
113  }
114  else
115  return this.applyDiff(data);
116  }
117 
128  form.prototype.applyDiff = function(diff,user)
129  {
130  //console.log("form apply diff",arguments);
131  //console.log(diff);
132 
133  var c,v;
134 
135  this._diffing = true;
136 
137  //diff = utils.resolveContextValues(diff,this._context);
138 
139  try
140  {
141  if (diff)
142  {
143  if (this._useAttributes && diff.attributes) //the old style of forms doesn't have an attributes field, but all the new ones do.
144  {
145  if (diff.help)
146  this._help = diff.help;
147 
148  diff = diff.attributes;
149  }
150 
151  //console.log(diff);
152  var diffSorted = utils.sortObjectByMemberAttribute(diff,"index");
153  //console.log(diffSorted);
154 
155  //for (var v in diff)
156  for (var __i=0;__i < diffSorted.length; __i++)
157  {
158  v = diffSorted[__i].__key;
159  c = diff[v];
160 
161  if (!(c instanceof Object)) //includes arrays
162  c = { value:c };
163 
164  //if (v.startsWith("__"))
165  // continue;
166 
167  if (this._attributes[v])
168  {
169  if (!paneManager._singlePane)
170  this._attributes[v].activeUser = user; //for arrow messages
171  else
172  this._attributes[v].activeUser = null;
173 
174  if (c) //if it's not null or false, do a set operation
175  {
176  if ("value" in c)
177  this._attributes[v].immediateValue = c.value;
178 
179  if ("options" in c)
180  this._attributes[v].applyOptions(c.options);
181 
182  //if ("tip" in c)
183  // console.warn("Have not implemented changeable tips yet.");
184 
185  //if ("label" in c)
186  // console.warn("Have not implemented changeable labels yet.");
187 
188  //console.log(user);
189  //console.trace();
190  }
191  else //else do a delete operation
192  {
193  this._attributes[v].destroy();
194  delete this._attributes[v];
195  console.error("FIXME: delete widget: '"+v+"' ... need to post update.");
196  }
197 
198  this._attributes[v].activeUser = null;
199  }
200  else //if it doesn't exist, create it
201  {
202  var d = utils.copyObject(c);
203 
204  if (!d) continue;
205 
206  d.variable = v;
207  if (!d.change) //we may want to override the form's normal functionality.
208  d.change = this.changeField.bind(this);
209 
210  var w = widgetFactory( d );
211 
212  if (w)
213  { this._attributes[v] = w;
214  //console.log(w);
215 
216  // if (widget._group)
217  // widget._group._rowJq.append( w.createHTML() );
218  // else
219  this._formJq.append( w.createHTML() );
220 
221  w.activate();
222 
223  if (this._enabledFilter)
224  {
225  var e = this._enabledFilter;
226  if (!w._options[e])
227  w.enabled = false;
228  }
229  }
230  else
231  {
232  if (preferences.fetch('reportFormErrors')===true)
233  {
234  console.dir(c);
235  //throw "Bad Widget: "+c;
236  }
237  }
238  }
239  }
240  }
241  else
242  console.error("diff was null!");
243  }
244  catch (err)
245  {
246  console.error("Caught exception: "+err.message);
247  console.log(diff);
248  console.log(diffSorted);
249  }
250 
251  this._diffing = false;
252  }
253 
262  form.prototype.applySettings = function(settings)
263  {
264  //console.log("form applySettings -- form has no settings!");
265  //console.log(settings);
266  }
267 
278  form.prototype.changeField = function(variable,value,widget)
279  {
280  //if a form is being changed, don't emit updates
281  //for a form that doesn't have a path (like when a form is used to create a new object in a modal), don't emit.
282 
283  if (!this._diffing && this._path)
284  {
285  //console.log("Change field!... need to post updates");
286  //console.log(arguments);
287 
288  var u = {};
289  u[variable] = { value:value };
290 
291  if (this._useAttributes)
292  u = { attributes:u };
293 
294  //objectRegistry.applyDiff( this._path, u, null, this ); //propagate changes to any other instance on this path.
295  //paneManager.applyDiff( this._path, u, null, this );
296  objectRegistry.applyDiff( this._path, u, null, this._parent ); //propagate changes to any other instance on this path.
297 
298  this.postUpdate( u );
299 
300  /*
301  console.log(variable);
302  if (variable === "name")
303  {
304  console.log("emit rename tab here");
305  }
306  */
307  }
308  }
309 
318  form.prototype.getField = function(field)
319  {
320  if (field in this._attributes)
321  return this._attributes[field];
322 
323  return null;
324  }
325 
334  form.prototype.getValue = function(field)
335  {
336  if (field in this._attributes)
337  return this._attributes[field].value;
338 
339  return null;
340  }
341 
351  form.prototype.getValues = function()
352  {
353  var v = {};
354 
355  for(var a in this._attributes)
356  if (!this._attributes[a].isDefault)
357  v[a] = this._attributes[a].value;
358  // else
359  // { console.log("was default: "+a);
360  // console.log(this._attributes[a].value);
361  // console.log(this._attributes[a].defaultValue);
362  // }
363 
364  return v;
365  }
366 
375  form.prototype.validate = function()
376  {
377  var valid = true;
378  var v;
379 
380  for (var a in this._attributes)
381  { v = this._attributes[a].validate();
382  valid = (v===true) && valid;
383  }
384 
385  return valid;
386  }
387 
395  form.prototype.destroy = function()
396  {
397  //console.log("form destroy");
398 
399  for (var a in this._attributes)
400  this._attributes[a].destroy();
401 
402  pane.prototype.destroy.call(this);
403 
404  this._attributes = null;
405  this._help = null;
406  this._wrapper = null;
407  this._formJq = null;
408  this._objectLoader = null;
409  }
410 
411  return form;
412  }
413 );
414 
setter value
a setter DOCME
setter user
a setter DOCME
Form renderer.
applySettings(settings)
validate()
form(layout)
getField(field)
Fetch a widget object by field name if it exists, or null if non-existent.
getValues()
applyDiff(diff, user)
Apply an incoming diff to the fields in this form.
getValue(field)
Fetch the value of a field if it exists, or null if non-existent.
destroy()
createHTML()
Create the jquery content object, or return it if it exists.
changeField(variable, value, widget)
applySubscription(data, metadata)
setter widget
a setter DOCME
applyDiff(id, diff, user, except)
setter postUpdate
Assign a callback to the paneFactory class for VFS_node::submit() commands.
createHeader()
Create a pane which will be mounted into a paneManager layout.
destroy()
DOCME.
createHTML()
pane(layout, object)
The paneManager manages panes in a user layout.
getter valid
a getter DOCME
fetch(v, _default)
applyDiff(diff, user)
Utility functions for javascript clients.
copyObject(source, dest)
Create a deep copy of a JSON object, extending the destination object recursively.
sortObjectByMemberAttribute(o, attr)
Sort an object by the value of an attribute of members of the object.
resolveContextValues(o, ctx)
Recursively resolve any context values in an object.
metadata(paths)
A factory and registry for loaded widget definitions.
widgetFactory(d)
Create a widget, if possible, or return a widgetLoader.
getter isDefault
Return whether or not this widget's value is its default value.