1 | define([ |
---|
2 | "dojo/_base/kernel", |
---|
3 | "dojo/_base/lang", |
---|
4 | "dojo/_base/connect", |
---|
5 | "dojo/_base/declare", |
---|
6 | "dojo/_base/fx", |
---|
7 | "dojo/_base/sniff", |
---|
8 | "dojo/dom", |
---|
9 | "dojo/dom-style", |
---|
10 | "dojo/dom-construct", |
---|
11 | "dijit/_Widget", |
---|
12 | "dijit/_Templated", |
---|
13 | "dijit/_Container", |
---|
14 | "dijit/Editor", |
---|
15 | "dijit/form/TextBox", |
---|
16 | "dijit/form/SimpleTextarea", |
---|
17 | "./FeedEntryViewer", |
---|
18 | "../io/model", |
---|
19 | "dojo/text!./templates/FeedEntryEditor.html", |
---|
20 | "dojo/text!./templates/PeopleEditor.html", |
---|
21 | "dojo/i18n!./nls/FeedEntryViewer", |
---|
22 | "dojo/i18n!./nls/FeedEntryEditor", |
---|
23 | "dojo/i18n!./nls/PeopleEditor" |
---|
24 | ], function (dojo, lang, connect, declare, fx, has, domUtil, domStyle, domConstruct, |
---|
25 | _Widget, _Templated, _Container, Editor, TextBox, SimpleTextarea, |
---|
26 | FeedEntryViewer, model, template, peopleEditorTemplate, i18nViewer, i18nEditor, i18nPeople) { |
---|
27 | dojo.experimental("dojox.atom.widget.FeedEntryEditor"); |
---|
28 | |
---|
29 | |
---|
30 | var FeedEntryEditor = declare("dojox.atom.widget.FeedEntryEditor", FeedEntryViewer,{ |
---|
31 | // summary: |
---|
32 | // An ATOM feed entry editor that allows viewing of the individual attributes of an entry. |
---|
33 | |
---|
34 | _contentEditor: null, |
---|
35 | _oldContent: null, |
---|
36 | _setObject: null, |
---|
37 | enableEdit: false, |
---|
38 | _contentEditorCreator: null, |
---|
39 | _editors: {}, |
---|
40 | entryNewButton: null, |
---|
41 | _editable: false, //Flag denoting if the current entry is editable or not. |
---|
42 | |
---|
43 | //Templates for the HTML rendering. Need to figure these out better, admittedly. |
---|
44 | templateString: template, |
---|
45 | |
---|
46 | postCreate: function(){ |
---|
47 | if(this.entrySelectionTopic !== ""){ |
---|
48 | this._subscriptions = [dojo.subscribe(this.entrySelectionTopic, this, "_handleEvent")]; |
---|
49 | } |
---|
50 | var _nlsResources = i18nViewer; |
---|
51 | this.displayOptions.innerHTML = _nlsResources.displayOptions; |
---|
52 | this.feedEntryCheckBoxLabelTitle.innerHTML = _nlsResources.title; |
---|
53 | this.feedEntryCheckBoxLabelAuthors.innerHTML = _nlsResources.authors; |
---|
54 | this.feedEntryCheckBoxLabelContributors.innerHTML = _nlsResources.contributors; |
---|
55 | this.feedEntryCheckBoxLabelId.innerHTML = _nlsResources.id; |
---|
56 | this.close.innerHTML = _nlsResources.close; |
---|
57 | this.feedEntryCheckBoxLabelUpdated.innerHTML = _nlsResources.updated; |
---|
58 | this.feedEntryCheckBoxLabelSummary.innerHTML = _nlsResources.summary; |
---|
59 | this.feedEntryCheckBoxLabelContent.innerHTML = _nlsResources.content; |
---|
60 | |
---|
61 | _nlsResources = i18nEditor; |
---|
62 | this.doNew.innerHTML = _nlsResources.doNew; |
---|
63 | this.edit.innerHTML = _nlsResources.edit; |
---|
64 | this.save.innerHTML = _nlsResources.save; |
---|
65 | this.cancel.innerHTML = _nlsResources.cancel; |
---|
66 | }, |
---|
67 | |
---|
68 | setEntry: function(/*object*/entry, /*object*/feed, /*boolean*/leaveMenuState){ |
---|
69 | // summary: |
---|
70 | // Function to set the current entry that is being edited. |
---|
71 | // entry: |
---|
72 | // Instance of dojox.atom.io.model.Entry to display for reading/editing. |
---|
73 | if(this._entry !== entry){ |
---|
74 | //If we swap entries, we don't want to keep the menu states and modes. |
---|
75 | this._editMode=false; |
---|
76 | leaveMenuState=false; |
---|
77 | }else{ |
---|
78 | leaveMenuState = true; |
---|
79 | } |
---|
80 | FeedEntryEditor.superclass.setEntry.call(this, entry, feed); |
---|
81 | this._editable = this._isEditable(entry); |
---|
82 | if(!leaveMenuState && !this._editable){ |
---|
83 | domStyle.set(this.entryEditButton, 'display', 'none'); |
---|
84 | domStyle.set(this.entrySaveCancelButtons, 'display', 'none'); |
---|
85 | } |
---|
86 | if(this._editable && this.enableEdit){ |
---|
87 | if(!leaveMenuState){ |
---|
88 | domStyle.set(this.entryEditButton, 'display', ''); |
---|
89 | //TODO double check this &&... |
---|
90 | if(this.enableMenuFade && this.entrySaveCancelButton){ |
---|
91 | fx.fadeOut({node: this.entrySaveCancelButton,duration: 250}).play(); |
---|
92 | } |
---|
93 | } |
---|
94 | } |
---|
95 | }, |
---|
96 | |
---|
97 | _toggleEdit: function(){ |
---|
98 | // summary: |
---|
99 | // Internal function for toggling/enabling the display of edit mode |
---|
100 | // returns: |
---|
101 | // Nothing. |
---|
102 | if(this._editable && this.enableEdit){ |
---|
103 | domStyle.set(this.entryEditButton, 'display', 'none'); |
---|
104 | domStyle.set(this.entrySaveCancelButtons, 'display', ''); |
---|
105 | this._editMode = true; |
---|
106 | |
---|
107 | //Rebuild the view using the same entry and feed. |
---|
108 | this.setEntry(this._entry, this._feed, true); |
---|
109 | } |
---|
110 | }, |
---|
111 | |
---|
112 | _handleEvent: function(/*object*/entrySelectionEvent){ |
---|
113 | // summary: |
---|
114 | // Internal function for listening to a topic that will handle entry notification. |
---|
115 | // entrySelectionEvent: |
---|
116 | // The topic message containing the entry that was selected for view. |
---|
117 | // returns: |
---|
118 | // Nothing. |
---|
119 | if(entrySelectionEvent.source != this && entrySelectionEvent.action == "delete" && |
---|
120 | entrySelectionEvent.entry && entrySelectionEvent.entry == this._entry){ |
---|
121 | domStyle.set(this.entryEditButton, 'display', 'none'); |
---|
122 | } |
---|
123 | FeedEntryEditor.superclass._handleEvent.call(this, entrySelectionEvent); |
---|
124 | }, |
---|
125 | |
---|
126 | _isEditable: function(/*object*/entry){ |
---|
127 | // summary: |
---|
128 | // Internal function for determining of a particular entry is editable. |
---|
129 | // description: |
---|
130 | // Internal function for determining of a particular entry is editable. |
---|
131 | // This is used for determining if the delete action should be displayed or not. |
---|
132 | // entry: |
---|
133 | // The dojox.atom.io.model.Entry object to examine |
---|
134 | // returns: |
---|
135 | // Boolean denoting if the entry seems editable or not.. |
---|
136 | var retVal = false; |
---|
137 | if(entry && entry !== null && entry.links && entry.links !== null){ |
---|
138 | for(var x in entry.links){ |
---|
139 | if(entry.links[x].rel && entry.links[x].rel == "edit"){ |
---|
140 | retVal = true; |
---|
141 | break; |
---|
142 | } |
---|
143 | } |
---|
144 | } |
---|
145 | return retVal; |
---|
146 | }, |
---|
147 | |
---|
148 | // The following set<Attribute> functions override the corresponding functions in FeedEntryViewer. These handle |
---|
149 | // the editMode flag by inserting appropriate editor widgets inside of just splashing the content in the page. |
---|
150 | setTitle: function(/*DOM node*/titleAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
151 | // summary: |
---|
152 | // Function to set the contents of the title node in the template to some value from the entry. |
---|
153 | // description: |
---|
154 | // Function to set the contents of the title node in the template to some value from the entry. |
---|
155 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
156 | // titleAnchorNode: |
---|
157 | // The DOM node to attach the title data to. |
---|
158 | // editMode: |
---|
159 | // Boolean to indicate if the display should be in edit mode or not. |
---|
160 | // entry: |
---|
161 | // The Feed Entry to work with. |
---|
162 | |
---|
163 | if(!editMode){ |
---|
164 | FeedEntryEditor.superclass.setTitle.call(this, titleAnchorNode, editMode, entry); |
---|
165 | if(entry.title && entry.title.value && entry.title.value !== null){ |
---|
166 | this.setFieldValidity("title", true); |
---|
167 | } |
---|
168 | }else{ |
---|
169 | if(entry.title && entry.title.value && entry.title.value !== null){ |
---|
170 | if(!this._toLoad){ |
---|
171 | this._toLoad = []; |
---|
172 | } |
---|
173 | this.entryTitleSelect.value = entry.title.type; |
---|
174 | |
---|
175 | var editor = this._createEditor(titleAnchorNode, entry.title, true, entry.title.type === "html" || entry.title.type === "xhtml"); |
---|
176 | editor.name = "title"; |
---|
177 | this._toLoad.push(editor); |
---|
178 | this.setFieldValidity("titleedit",true); |
---|
179 | this.setFieldValidity("title",true); |
---|
180 | } |
---|
181 | } |
---|
182 | }, |
---|
183 | |
---|
184 | setAuthors: function(/*DOM node*/authorsAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
185 | // summary: |
---|
186 | // Function to set the contents of the author node in the template to some value from the entry. |
---|
187 | // description: |
---|
188 | // Function to set the contents of the author node in the template to some value from the entry. |
---|
189 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
190 | // authorsAnchorNode: |
---|
191 | // The DOM node to attach the author data to. |
---|
192 | // editMode: |
---|
193 | // Boolean to indicate if the display should be in edit mode or not. |
---|
194 | // entry: |
---|
195 | // The Feed Entry to work with. |
---|
196 | if(!editMode){ |
---|
197 | FeedEntryEditor.superclass.setAuthors.call(this, authorsAnchorNode, editMode, entry); |
---|
198 | if(entry.authors && entry.authors.length > 0){ |
---|
199 | this.setFieldValidity("authors", true); |
---|
200 | } |
---|
201 | }else{ |
---|
202 | if(entry.authors && entry.authors.length > 0){ |
---|
203 | this._editors.authors = this._createPeopleEditor(this.entryAuthorNode, {data: entry.authors, name: "Author"}); |
---|
204 | this.setFieldValidity("authors", true); |
---|
205 | } |
---|
206 | } |
---|
207 | }, |
---|
208 | |
---|
209 | |
---|
210 | setContributors: function(/*DOM node*/contributorsAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
211 | // summary: |
---|
212 | // Function to set the contents of the contributor node in the template to some value from the entry. |
---|
213 | // description: |
---|
214 | // Function to set the contents of the contributor node in the template to some value from the entry. |
---|
215 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
216 | // contributorsAnchorNode: |
---|
217 | // The DOM node to attach the contributor data to. |
---|
218 | // editMode: |
---|
219 | // Boolean to indicate if the display should be in edit mode or not. |
---|
220 | // entry: |
---|
221 | // The Feed Entry to work with. |
---|
222 | if(!editMode){ |
---|
223 | FeedEntryEditor.superclass.setContributors.call(this, contributorsAnchorNode, editMode, entry); |
---|
224 | if(entry.contributors && entry.contributors.length > 0){ |
---|
225 | this.setFieldValidity("contributors", true); |
---|
226 | } |
---|
227 | }else{ |
---|
228 | if(entry.contributors && entry.contributors.length > 0){ |
---|
229 | this._editors.contributors = this._createPeopleEditor(this.entryContributorNode, {data: entry.contributors, name: "Contributor"}); |
---|
230 | this.setFieldValidity("contributors", true); |
---|
231 | } |
---|
232 | } |
---|
233 | }, |
---|
234 | |
---|
235 | |
---|
236 | setId: function(/*DOM node*/idAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
237 | // summary: |
---|
238 | // Function to set the contents of the ID node in the template to some value from the entry. |
---|
239 | // description: |
---|
240 | // Function to set the contents of the ID node in the template to some value from the entry. |
---|
241 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
242 | // idAnchorNode: |
---|
243 | // The DOM node to attach the ID data to. |
---|
244 | // editMode: |
---|
245 | // Boolean to indicate if the display should be in edit mode or not. |
---|
246 | // entry: |
---|
247 | // The Feed Entry to work with. |
---|
248 | if(!editMode){ |
---|
249 | FeedEntryEditor.superclass.setId.call(this, idAnchorNode, editMode, entry); |
---|
250 | if(entry.id && entry.id !== null){ |
---|
251 | this.setFieldValidity("id", true); |
---|
252 | } |
---|
253 | }else{ |
---|
254 | if(entry.id && entry.id !== null){ |
---|
255 | this._editors.id = this._createEditor(idAnchorNode, entry.id); |
---|
256 | this.setFieldValidity("id",true); |
---|
257 | } |
---|
258 | } |
---|
259 | }, |
---|
260 | |
---|
261 | setUpdated: function(/*DOM node*/updatedAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
262 | // summary: |
---|
263 | // Function to set the contents of the updated node in the template to some value from the entry. |
---|
264 | // description: |
---|
265 | // Function to set the contents of the updated node in the template to some value from the entry. |
---|
266 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
267 | // updatedAnchorNode: |
---|
268 | // The DOM node to attach the updated data to. |
---|
269 | // editMode: |
---|
270 | // Boolean to indicate if the display should be in edit mode or not. |
---|
271 | // entry: |
---|
272 | // The Feed Entry to work with. |
---|
273 | if(!editMode){ |
---|
274 | FeedEntryEditor.superclass.setUpdated.call(this, updatedAnchorNode, editMode, entry); |
---|
275 | if(entry.updated && entry.updated !== null){ |
---|
276 | this.setFieldValidity("updated", true); |
---|
277 | } |
---|
278 | }else{ |
---|
279 | if(entry.updated && entry.updated !== null){ |
---|
280 | this._editors.updated = this._createEditor(updatedAnchorNode, entry.updated); |
---|
281 | this.setFieldValidity("updated",true); |
---|
282 | } |
---|
283 | } |
---|
284 | }, |
---|
285 | |
---|
286 | |
---|
287 | setSummary: function(/*DOM node*/summaryAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
288 | // summary: |
---|
289 | // Function to set the contents of the summary node in the template to some value from the entry. |
---|
290 | // description: |
---|
291 | // Function to set the contents of the summary node in the template to some value from the entry. |
---|
292 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
293 | // summaryAnchorNode: |
---|
294 | // The DOM node to attach the summary data to. |
---|
295 | // editMode: |
---|
296 | // Boolean to indicate if the display should be in edit mode or not. |
---|
297 | // entry: |
---|
298 | // The Feed Entry to work with. |
---|
299 | if(!editMode){ |
---|
300 | FeedEntryEditor.superclass.setSummary.call(this, summaryAnchorNode, editMode, entry); |
---|
301 | if(entry.summary && entry.summary.value && entry.summary.value !== null){ |
---|
302 | this.setFieldValidity("summary", true); |
---|
303 | } |
---|
304 | }else{ |
---|
305 | if(entry.summary && entry.summary.value && entry.summary.value !== null){ |
---|
306 | if(!this._toLoad){ |
---|
307 | this._toLoad = []; |
---|
308 | } |
---|
309 | this.entrySummarySelect.value = entry.summary.type; |
---|
310 | |
---|
311 | var editor = this._createEditor(summaryAnchorNode, entry.summary, true, entry.summary.type === "html" || entry.summary.type === "xhtml"); |
---|
312 | editor.name = "summary"; |
---|
313 | this._toLoad.push(editor); |
---|
314 | this.setFieldValidity("summaryedit",true); |
---|
315 | this.setFieldValidity("summary",true); |
---|
316 | } |
---|
317 | } |
---|
318 | }, |
---|
319 | |
---|
320 | setContent: function(/*DOM node*/contentAnchorNode, /*boolean*/editMode, /*object*/entry){ |
---|
321 | // summary: |
---|
322 | // Function to set the contents of the content node in the template to some value from the entry. |
---|
323 | // description: |
---|
324 | // Function to set the contents of the content node in the template to some value from the entry. |
---|
325 | // This exists specifically so users can over-ride how the title data is filled out from an entry. |
---|
326 | // summaryAnchorNode: |
---|
327 | // The DOM node to attach the content data to. |
---|
328 | // editMode: |
---|
329 | // Boolean to indicate if the display should be in edit mode or not. |
---|
330 | // entry: |
---|
331 | // The Feed Entry to work with. |
---|
332 | if(!editMode){ |
---|
333 | FeedEntryEditor.superclass.setContent.call(this, contentAnchorNode, editMode, entry); |
---|
334 | if(entry.content && entry.content.value && entry.content.value !== null){ |
---|
335 | this.setFieldValidity("content",true); |
---|
336 | } |
---|
337 | }else{ |
---|
338 | if(entry.content && entry.content.value && entry.content.value !== null){ |
---|
339 | if(!this._toLoad){ |
---|
340 | this._toLoad = []; |
---|
341 | } |
---|
342 | this.entryContentSelect.value = entry.content.type; |
---|
343 | var editor = this._createEditor(contentAnchorNode, entry.content, true, entry.content.type === "html" || entry.content.type === "xhtml"); |
---|
344 | editor.name = "content"; |
---|
345 | this._toLoad.push(editor); |
---|
346 | this.setFieldValidity("contentedit",true); |
---|
347 | this.setFieldValidity("content",true); |
---|
348 | } |
---|
349 | } |
---|
350 | }, |
---|
351 | |
---|
352 | _createEditor: function(/*DOM node*/anchorNode, /*DOM node*/node, /*boolean*/multiline, /*object*/rte){ |
---|
353 | // summary: |
---|
354 | // Function to create an appropriate text editor widget based on the given parameters. |
---|
355 | // anchorNode: |
---|
356 | // The DOM node to attach the editor widget to. |
---|
357 | // node: |
---|
358 | // An object containing the value to be put into the editor. This ranges from an anonymous object |
---|
359 | // with a value parameter to a dojox.atom.io.model.Content object. |
---|
360 | // multiline: |
---|
361 | // A boolean indicating whether the content should be multiline (such as a textarea) instead of a |
---|
362 | // single line (such as a textbox). |
---|
363 | // rte: |
---|
364 | // A boolean indicating whether the content should be a rich text editor widget. |
---|
365 | // returns: |
---|
366 | // Either a widget (for textarea or textbox widgets) or an anonymous object to be used to create a |
---|
367 | // rich text area widget. |
---|
368 | var viewNode; |
---|
369 | var box; |
---|
370 | if(!node){ |
---|
371 | if(rte){ |
---|
372 | // Returns an anonymous object which would then be loaded later, after the containing element |
---|
373 | // exists on the page. |
---|
374 | return {anchorNode: anchorNode, |
---|
375 | entryValue: "", |
---|
376 | editor: null, |
---|
377 | generateEditor: function(){ |
---|
378 | // The only way I found I could get the editor to behave consistently was to |
---|
379 | // create the content on a span, and allow the content editor to replace it. |
---|
380 | // This gets around the dynamic/delayed way in which content editors get created. |
---|
381 | var node = document.createElement("div"); |
---|
382 | node.innerHTML = this.entryValue; |
---|
383 | this.anchorNode.appendChild(node); |
---|
384 | var _editor = new Editor({}, node); |
---|
385 | this.editor = _editor; |
---|
386 | return _editor; |
---|
387 | } |
---|
388 | }; |
---|
389 | } |
---|
390 | if(multiline){ |
---|
391 | // If multiline, create a textarea |
---|
392 | viewNode = document.createElement("textarea"); |
---|
393 | anchorNode.appendChild(viewNode); |
---|
394 | domStyle.set(viewNode, 'width', '90%'); |
---|
395 | box = new SimpleTextarea({},viewNode); |
---|
396 | }else{ |
---|
397 | // If single line, create a textbox. |
---|
398 | viewNode = document.createElement("input"); |
---|
399 | anchorNode.appendChild(viewNode); |
---|
400 | domStyle.set(viewNode, 'width', '95%'); |
---|
401 | box = new TextBox({},viewNode); |
---|
402 | } |
---|
403 | box.attr('value', ''); |
---|
404 | return box; |
---|
405 | } |
---|
406 | |
---|
407 | // Check through the node parameter to get the value to be used. |
---|
408 | var value; |
---|
409 | if(node.value !== undefined){ |
---|
410 | value = node.value; |
---|
411 | }else if(node.attr){ |
---|
412 | value = node.attr('value'); |
---|
413 | }else{ |
---|
414 | value = node; |
---|
415 | } |
---|
416 | if(rte){ |
---|
417 | // Returns an anonymous object which would then be loaded later, after the containing element |
---|
418 | // exists on the page. |
---|
419 | if(value.indexOf("<") != -1){ |
---|
420 | value = value.replace(/</g, "<"); |
---|
421 | } |
---|
422 | return {anchorNode: anchorNode, |
---|
423 | entryValue: value, |
---|
424 | editor: null, |
---|
425 | generateEditor: function(){ |
---|
426 | // The only way I found I could get the editor to behave consistently was to |
---|
427 | // create the content on a span, and allow the content editor to replace it. |
---|
428 | // This gets around the dynamic/delayed way in which content editors get created. |
---|
429 | var node = document.createElement("div"); |
---|
430 | node.innerHTML = this.entryValue; |
---|
431 | this.anchorNode.appendChild(node); |
---|
432 | var _editor = new Editor({}, node); |
---|
433 | this.editor = _editor; |
---|
434 | return _editor; |
---|
435 | } |
---|
436 | }; |
---|
437 | } |
---|
438 | if(multiline){ |
---|
439 | // If multiline, create a textarea |
---|
440 | viewNode = document.createElement("textarea"); |
---|
441 | anchorNode.appendChild(viewNode); |
---|
442 | domStyle.set(viewNode, 'width', '90%'); |
---|
443 | box = new SimpleTextarea({},viewNode); |
---|
444 | }else{ |
---|
445 | // If single line, create a textbox. |
---|
446 | viewNode = document.createElement("input"); |
---|
447 | anchorNode.appendChild(viewNode); |
---|
448 | domStyle.set(viewNode, 'width', '95%'); |
---|
449 | box = new TextBox({},viewNode); |
---|
450 | } |
---|
451 | box.attr('value', value); |
---|
452 | return box; |
---|
453 | }, |
---|
454 | |
---|
455 | _switchEditor: function(/*object*/event){ |
---|
456 | // summary: |
---|
457 | // Function to switch between editor types. |
---|
458 | // description: |
---|
459 | // Function to switch between a rich text editor and a textarea widget. Used for title, summary, |
---|
460 | // And content when switching between text and html/xhtml content. |
---|
461 | // event: |
---|
462 | // The event generated by the change in the select box on the page. |
---|
463 | var type = null; |
---|
464 | var target = null; |
---|
465 | var parent = null; |
---|
466 | |
---|
467 | // Determine the source/target of this event (to determine which editor we're switching) |
---|
468 | if(has("ie")){ |
---|
469 | target = event.srcElement; |
---|
470 | }else{ |
---|
471 | target = event.target; |
---|
472 | } |
---|
473 | |
---|
474 | // Determine which editor (title, summary, or content) |
---|
475 | if(target === this.entryTitleSelect){ |
---|
476 | parent = this.entryTitleNode; |
---|
477 | type = "title"; |
---|
478 | } else if(target === this.entrySummarySelect){ |
---|
479 | parent = this.entrySummaryNode; |
---|
480 | type = "summary"; |
---|
481 | }else{ |
---|
482 | parent = this.entryContentNode; |
---|
483 | type = "content"; |
---|
484 | } |
---|
485 | |
---|
486 | // Grab the existing editor. |
---|
487 | var editor = this._editors[type]; |
---|
488 | var newEditor; |
---|
489 | var value; |
---|
490 | |
---|
491 | if(target.value === "text"){ |
---|
492 | if(editor.isInstanceOf(Editor)){ |
---|
493 | // If we're changing the type to text and our existing editor is a rich text editor, we need to destroy |
---|
494 | // it and switch to a multiline editor. |
---|
495 | value = editor.attr('value', false); |
---|
496 | editor.close(false,true); |
---|
497 | editor.destroy(); |
---|
498 | while(parent.firstChild){ |
---|
499 | domConstruct.destroy(parent.firstChild); |
---|
500 | } |
---|
501 | newEditor = this._createEditor(parent, {value: value}, true, false); |
---|
502 | this._editors[type] = newEditor; |
---|
503 | } |
---|
504 | }else{ |
---|
505 | if(!editor.isInstanceOf(Editor)){ |
---|
506 | // Otherwise, we're switching to a html or xhtml type, but we currently have a textarea widget. We need |
---|
507 | // to destroy the existing RTE and create a multiline textarea widget. |
---|
508 | value = editor.attr('value'); |
---|
509 | editor.destroy(); |
---|
510 | while(parent.firstChild){ |
---|
511 | domConstruct.destroy(parent.firstChild); |
---|
512 | } |
---|
513 | newEditor = this._createEditor(parent, {value: value}, true, true); |
---|
514 | newEditor = lang.hitch(newEditor, newEditor.generateEditor)(); |
---|
515 | this._editors[type] = newEditor; |
---|
516 | } |
---|
517 | } |
---|
518 | }, |
---|
519 | |
---|
520 | _createPeopleEditor: function(/*DOM node*/anchorNode, /*DOM node*/node){ |
---|
521 | // summary: |
---|
522 | // Creates a People Editor widget, sets its value, and returns it. |
---|
523 | // anchorNode: |
---|
524 | // The node to attach the editor to. |
---|
525 | // node: |
---|
526 | // An object containing the value to be put into the editor. Typically, this is an |
---|
527 | // dojox.atom.io.model.Person object. |
---|
528 | // returns: |
---|
529 | // A new People Editor object. |
---|
530 | var viewNode = document.createElement("div"); |
---|
531 | anchorNode.appendChild(viewNode); |
---|
532 | return new PeopleEditor(node,viewNode); |
---|
533 | }, |
---|
534 | |
---|
535 | saveEdits: function(){ |
---|
536 | // summary: |
---|
537 | // Saves edits submitted when the 'save' button is pressed. |
---|
538 | // description: |
---|
539 | // Saves edits submitted when the 'save' button is pressed. Distinguishes between new and existing |
---|
540 | // entries and saves appropriately. Fetches the values of the editors, and, if existing, compares them to |
---|
541 | // the existing values and submits the updates, otherwise creates a new entry and posts it as a new entry. |
---|
542 | // returns: |
---|
543 | // Nothing. |
---|
544 | domStyle.set(this.entrySaveCancelButtons, 'display', 'none'); |
---|
545 | domStyle.set(this.entryEditButton, 'display', ''); |
---|
546 | domStyle.set(this.entryNewButton, 'display', ''); |
---|
547 | var modifiedEntry = false; |
---|
548 | var value; |
---|
549 | var i; |
---|
550 | var changed; |
---|
551 | var entry; |
---|
552 | var authors; |
---|
553 | var contributors; |
---|
554 | if(!this._new){ |
---|
555 | entry = this.getEntry(); |
---|
556 | if(this._editors.title && (this._editors.title.attr('value') != entry.title.value || this.entryTitleSelect.value != entry.title.type)){ |
---|
557 | value = this._editors.title.attr('value'); |
---|
558 | if(this.entryTitleSelect.value === "xhtml"){ |
---|
559 | value = this._enforceXhtml(value); |
---|
560 | if(value.indexOf('<div xmlns="http://www.w3.org/1999/xhtml">') !== 0){ |
---|
561 | value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>'; |
---|
562 | } |
---|
563 | } |
---|
564 | entry.title = new model.Content("title", value, null, this.entryTitleSelect.value); |
---|
565 | modifiedEntry = true; |
---|
566 | } |
---|
567 | |
---|
568 | if(this._editors.id.attr('value') != entry.id){ |
---|
569 | entry.id = this._editors.id.attr('value'); |
---|
570 | modifiedEntry = true; |
---|
571 | } |
---|
572 | |
---|
573 | if(this._editors.summary && (this._editors.summary.attr('value') != entry.summary.value || this.entrySummarySelect.value != entry.summary.type)){ |
---|
574 | value = this._editors.summary.attr('value'); |
---|
575 | if(this.entrySummarySelect.value === "xhtml"){ |
---|
576 | value = this._enforceXhtml(value); |
---|
577 | if(value.indexOf('<div xmlns="http://www.w3.org/1999/xhtml">') !== 0){ |
---|
578 | value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>'; |
---|
579 | } |
---|
580 | } |
---|
581 | entry.summary = new model.Content("summary", value, null, this.entrySummarySelect.value); |
---|
582 | modifiedEntry = true; |
---|
583 | } |
---|
584 | |
---|
585 | if(this._editors.content && (this._editors.content.attr('value') != entry.content.value || this.entryContentSelect.value != entry.content.type)){ |
---|
586 | value = this._editors.content.attr('value'); |
---|
587 | if(this.entryContentSelect.value === "xhtml"){ |
---|
588 | value = this._enforceXhtml(value); |
---|
589 | if(value.indexOf('<div xmlns="http://www.w3.org/1999/xhtml">') !== 0){ |
---|
590 | value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>'; |
---|
591 | } |
---|
592 | } |
---|
593 | entry.content = new model.Content("content", value, null, this.entryContentSelect.value); |
---|
594 | modifiedEntry = true; |
---|
595 | } |
---|
596 | |
---|
597 | if(this._editors.authors){ |
---|
598 | if(modifiedEntry){ |
---|
599 | entry.authors = []; |
---|
600 | authors = this._editors.authors.getValues(); |
---|
601 | for(i in authors){ |
---|
602 | if(authors[i].name || authors[i].email || authors[i].uri){ |
---|
603 | entry.addAuthor(authors[i].name, authors[i].email, authors[i].uri); |
---|
604 | } |
---|
605 | } |
---|
606 | }else{ |
---|
607 | var currentAuthors = entry.authors; |
---|
608 | var searchAuthors = function(name, email, uri){ |
---|
609 | for(i in currentAuthors){ |
---|
610 | if(currentAuthors[i].name === name && currentAuthors[i].email === email && currentAuthors[i].uri === uri){ |
---|
611 | return true; |
---|
612 | } |
---|
613 | } |
---|
614 | return false; |
---|
615 | }; |
---|
616 | authors = this._editors.authors.getValues(); |
---|
617 | changed = false; |
---|
618 | for(i in authors){ |
---|
619 | if(!searchAuthors(authors[i].name, authors[i].email, authors[i].uri)){ |
---|
620 | changed = true; |
---|
621 | break; |
---|
622 | } |
---|
623 | } |
---|
624 | if(changed){ |
---|
625 | entry.authors = []; |
---|
626 | for(i in authors){ |
---|
627 | if(authors[i].name || authors[i].email || authors[i].uri){ |
---|
628 | entry.addAuthor(authors[i].name, authors[i].email, authors[i].uri); |
---|
629 | } |
---|
630 | } |
---|
631 | modifiedEntry = true; |
---|
632 | } |
---|
633 | } |
---|
634 | } |
---|
635 | |
---|
636 | if(this._editors.contributors){ |
---|
637 | if(modifiedEntry){ |
---|
638 | entry.contributors = []; |
---|
639 | contributors = this._editors.contributors.getValues(); |
---|
640 | for(i in contributors){ |
---|
641 | if(contributors[i].name || contributors[i].email || contributors[i].uri){ |
---|
642 | entry.addAuthor(contributors[i].name, contributors[i].email, contributors[i].uri); |
---|
643 | } |
---|
644 | } |
---|
645 | }else{ |
---|
646 | var currentContributors = entry.contributors; |
---|
647 | var searchContributors = function(name, email, uri){ |
---|
648 | for(i in currentContributors){ |
---|
649 | if(currentContributors[i].name === name && currentContributors[i].email === email && currentContributors[i].uri === uri){ |
---|
650 | return true; |
---|
651 | } |
---|
652 | } |
---|
653 | return false; |
---|
654 | }; |
---|
655 | contributors = this._editors.contributors.getValues(); |
---|
656 | changed = false; |
---|
657 | for(i in contributors){ |
---|
658 | if(searchContributors(contributors[i].name, contributors[i].email, contributors[i].uri)){ |
---|
659 | changed = true; |
---|
660 | break; |
---|
661 | } |
---|
662 | } |
---|
663 | if(changed){ |
---|
664 | entry.contributors = []; |
---|
665 | for(i in contributors){ |
---|
666 | if(contributors[i].name || contributors[i].email || contributors[i].uri){ |
---|
667 | entry.addContributor(contributors[i].name, contributors[i].email, contributors[i].uri); |
---|
668 | } |
---|
669 | } |
---|
670 | modifiedEntry = true; |
---|
671 | } |
---|
672 | } |
---|
673 | } |
---|
674 | |
---|
675 | if(modifiedEntry){ |
---|
676 | dojo.publish(this.entrySelectionTopic, [{action: "update", source: this, entry: entry, callback: this._handleSave }]); |
---|
677 | //TODO: REMOVE BELOW |
---|
678 | //var atomIO = new dojox.atom.io.Connection(); |
---|
679 | //atomIO.updateEntry(entry, dojo.hitch(this,this._handleSave)); |
---|
680 | //WARNING: Use above when testing with SimpleProxy (or any other servlet which |
---|
681 | // doesn't actually create a new entry and return it properly) |
---|
682 | //atomIO.updateEntry(entry, dojo.hitch(this,this._handleSave), true); |
---|
683 | } |
---|
684 | }else{ |
---|
685 | this._new = false; |
---|
686 | entry = new model.Entry(); |
---|
687 | |
---|
688 | value = this._editors.title.attr('value'); |
---|
689 | if(this.entryTitleSelect.value === "xhtml"){ |
---|
690 | value = this._enforceXhtml(value); |
---|
691 | value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>'; |
---|
692 | } |
---|
693 | entry.setTitle(value, this.entryTitleSelect.value); |
---|
694 | entry.id = this._editors.id.attr('value'); |
---|
695 | |
---|
696 | authors = this._editors.authors.getValues(); |
---|
697 | for(i in authors){ |
---|
698 | if(authors[i].name || authors[i].email || authors[i].uri){ |
---|
699 | entry.addAuthor(authors[i].name, authors[i].email, authors[i].uri); |
---|
700 | } |
---|
701 | } |
---|
702 | |
---|
703 | contributors = this._editors.contributors.getValues(); |
---|
704 | for(i in contributors){ |
---|
705 | if(contributors[i].name || contributors[i].email || contributors[i].uri){ |
---|
706 | entry.addContributor(contributors[i].name, contributors[i].email, contributors[i].uri); |
---|
707 | } |
---|
708 | } |
---|
709 | |
---|
710 | |
---|
711 | value = this._editors.summary.attr('value'); |
---|
712 | if(this.entrySummarySelect.value === "xhtml"){ |
---|
713 | value = this._enforceXhtml(value); |
---|
714 | value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>'; |
---|
715 | } |
---|
716 | entry.summary = new model.Content("summary", value, null, this.entrySummarySelect.value); |
---|
717 | |
---|
718 | value = this._editors.content.attr('value'); |
---|
719 | if(this.entryContentSelect.value === "xhtml"){ |
---|
720 | value = this._enforceXhtml(value); |
---|
721 | value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>'; |
---|
722 | } |
---|
723 | entry.content = new model.Content("content", value, null, this.entryContentSelect.value); |
---|
724 | |
---|
725 | domStyle.set(this.entryNewButton, 'display', ''); |
---|
726 | dojo.publish(this.entrySelectionTopic, [{action: "post", source: this, entry: entry }]); |
---|
727 | } |
---|
728 | this._editMode = false; |
---|
729 | |
---|
730 | //Rebuild the view using the same entry and feed. |
---|
731 | this.setEntry(entry, this._feed, true); |
---|
732 | }, |
---|
733 | |
---|
734 | _handleSave: function(/*object*/entry, /*string*/ location){ |
---|
735 | // summary: |
---|
736 | // Function for handling the save of an entry, cleaning up the display after the edit is completed. |
---|
737 | // entry: dojox.atom.io.model.Entry object |
---|
738 | // The entry that was saved. |
---|
739 | // Location: String |
---|
740 | // A URL to be used, not used here, but part of the call back from the AtomIO |
---|
741 | // returns: Nothing |
---|
742 | |
---|
743 | //Close the editor and revert out. |
---|
744 | this._editMode = false; |
---|
745 | |
---|
746 | //Rebuild the view using the same entry and feed. |
---|
747 | this.clear(); |
---|
748 | this.setEntry(entry, this.getFeed(), true); |
---|
749 | }, |
---|
750 | |
---|
751 | cancelEdits: function(){ |
---|
752 | // summary: |
---|
753 | // Cancels edits and reverts the editor to its previous state (display mode) |
---|
754 | // returns: |
---|
755 | // Nothing. |
---|
756 | this._new = false; |
---|
757 | domStyle.set(this.entrySaveCancelButtons, 'display', 'none'); |
---|
758 | if(this._editable){ |
---|
759 | domStyle.set(this.entryEditButton, 'display', ''); |
---|
760 | } |
---|
761 | domStyle.set(this.entryNewButton, 'display', ''); |
---|
762 | this._editMode = false; |
---|
763 | |
---|
764 | //Rebuild the view using the same entry and feed. |
---|
765 | this.clearEditors(); |
---|
766 | this.setEntry(this.getEntry(), this.getFeed(), true); |
---|
767 | }, |
---|
768 | |
---|
769 | clear: function(){ |
---|
770 | // summary: |
---|
771 | // Clears the editor, destroys all editors, leaving the editor completely clear |
---|
772 | this._editable=false; |
---|
773 | this.clearEditors(); |
---|
774 | FeedEntryEditor.superclass.clear.apply(this); |
---|
775 | if(this._contentEditor){ |
---|
776 | // Note that the superclass clear destroys the widget since it's in the child widget list, |
---|
777 | // so this is just ref clearing. |
---|
778 | this._contentEditor = this._setObject = this._oldContent = this._contentEditorCreator = null; |
---|
779 | this._editors = {}; |
---|
780 | } |
---|
781 | }, |
---|
782 | |
---|
783 | clearEditors: function(){ |
---|
784 | for(var key in this._editors){ |
---|
785 | if(this._editors[key].isInstanceOf(Editor)){ |
---|
786 | this._editors[key].close(false, true); |
---|
787 | } |
---|
788 | this._editors[key].destroy(); |
---|
789 | } |
---|
790 | this._editors = {}; |
---|
791 | }, |
---|
792 | |
---|
793 | _enforceXhtml: function(/*string*/html){ |
---|
794 | // summary: |
---|
795 | // Function for cleaning up/enforcing the XHTML standard in HTML returned from the editor2 widget. |
---|
796 | // html: |
---|
797 | // HTML string to be enforced as xhtml. |
---|
798 | // returns: |
---|
799 | // string of cleaned up HTML. |
---|
800 | var xhtml = null; |
---|
801 | if(html){ |
---|
802 | //Handle <BR> |
---|
803 | var brRegExp = /<br>/g; |
---|
804 | xhtml = html.replace(brRegExp, "<br/>"); |
---|
805 | |
---|
806 | //Handle <HR> |
---|
807 | xhtml = this._closeTag(xhtml, "hr"); |
---|
808 | |
---|
809 | //Handle <img> |
---|
810 | xhtml = this._closeTag(xhtml, "img"); |
---|
811 | } |
---|
812 | return xhtml; |
---|
813 | }, |
---|
814 | |
---|
815 | _closeTag: function(/*string*/xhtml, /*string*/tag){ |
---|
816 | // summary: |
---|
817 | // Function for closing tags in a text of HTML/XHTML |
---|
818 | // xhtml: String |
---|
819 | // XHTML string which needs the closing tag. |
---|
820 | // tag: |
---|
821 | // The tag to close. |
---|
822 | // returns: |
---|
823 | // string of cleaned up HTML. |
---|
824 | |
---|
825 | // NOTE: Probably should redo this function in a more efficient way. This could get expensive. |
---|
826 | var tagStart = "<" + tag; |
---|
827 | var tagIndex = xhtml.indexOf(tagStart); |
---|
828 | if(tagIndex !== -1){ |
---|
829 | while (tagIndex !== -1){ |
---|
830 | var tempString = ""; |
---|
831 | var foundTagEnd = false; |
---|
832 | for (var i = 0; i < xhtml.length; i++){ |
---|
833 | var c = xhtml.charAt(i); |
---|
834 | if(i <= tagIndex ||foundTagEnd){ |
---|
835 | tempString += c; |
---|
836 | } |
---|
837 | else |
---|
838 | { |
---|
839 | if(c === '>'){ |
---|
840 | tempString += "/"; |
---|
841 | foundTagEnd = true; |
---|
842 | } |
---|
843 | tempString +=c; |
---|
844 | } |
---|
845 | } |
---|
846 | xhtml = tempString; |
---|
847 | tagIndex = xhtml.indexOf(tagStart, tagIndex + 1); |
---|
848 | } |
---|
849 | } |
---|
850 | return xhtml; |
---|
851 | }, |
---|
852 | |
---|
853 | _toggleNew: function(){ |
---|
854 | // summary: |
---|
855 | // Function to put the editor into a state to create a new entry. |
---|
856 | |
---|
857 | // Hide the edit/new buttons and show the save/cancel buttons. |
---|
858 | domStyle.set(this.entryNewButton, 'display', 'none'); |
---|
859 | domStyle.set(this.entryEditButton, 'display', 'none'); |
---|
860 | domStyle.set(this.entrySaveCancelButtons, 'display', ''); |
---|
861 | |
---|
862 | // Reset the type select boxes to text. |
---|
863 | this.entrySummarySelect.value = "text"; |
---|
864 | this.entryContentSelect.value = "text"; |
---|
865 | this.entryTitleSelect.value = "text"; |
---|
866 | |
---|
867 | // Clear all nodes. |
---|
868 | this.clearNodes(); |
---|
869 | this._new = true; |
---|
870 | |
---|
871 | var _nlsResources = i18nViewer; |
---|
872 | // Create all headers and editors. |
---|
873 | var titleHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.title}); |
---|
874 | this.entryTitleHeader.appendChild(titleHeader.domNode); |
---|
875 | |
---|
876 | this._editors.title = this._createEditor(this.entryTitleNode, null); |
---|
877 | this.setFieldValidity("title",true); |
---|
878 | |
---|
879 | var authorHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.authors}); |
---|
880 | this.entryAuthorHeader.appendChild(authorHeader.domNode); |
---|
881 | |
---|
882 | this._editors.authors = this._createPeopleEditor(this.entryAuthorNode, {name: "Author"}); |
---|
883 | this.setFieldValidity("authors", true); |
---|
884 | |
---|
885 | var contributorHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.contributors}); |
---|
886 | this.entryContributorHeader.appendChild(contributorHeader.domNode); |
---|
887 | |
---|
888 | this._editors.contributors = this._createPeopleEditor(this.entryContributorNode, {name: "Contributor"}); |
---|
889 | this.setFieldValidity("contributors", true); |
---|
890 | |
---|
891 | var idHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.id}); |
---|
892 | this.entryIdHeader.appendChild(idHeader.domNode); |
---|
893 | |
---|
894 | this._editors.id = this._createEditor(this.entryIdNode, null); |
---|
895 | this.setFieldValidity("id",true); |
---|
896 | |
---|
897 | var updatedHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.updated}); |
---|
898 | this.entryUpdatedHeader.appendChild(updatedHeader.domNode); |
---|
899 | |
---|
900 | this._editors.updated = this._createEditor(this.entryUpdatedNode, null); |
---|
901 | this.setFieldValidity("updated",true); |
---|
902 | |
---|
903 | var summaryHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.summary}); |
---|
904 | this.entrySummaryHeader.appendChild(summaryHeader.domNode); |
---|
905 | |
---|
906 | this._editors.summary = this._createEditor(this.entrySummaryNode, null, true); |
---|
907 | this.setFieldValidity("summaryedit",true); |
---|
908 | this.setFieldValidity("summary",true); |
---|
909 | |
---|
910 | var contentHeader = new FeedEntryViewer.EntryHeader({title: _nlsResources.content}); |
---|
911 | this.entryContentHeader.appendChild(contentHeader.domNode); |
---|
912 | |
---|
913 | this._editors.content = this._createEditor(this.entryContentNode, null, true); |
---|
914 | this.setFieldValidity("contentedit",true); |
---|
915 | this.setFieldValidity("content",true); |
---|
916 | |
---|
917 | // Show the sections. |
---|
918 | this._displaySections(); |
---|
919 | }, |
---|
920 | |
---|
921 | _displaySections: function(){ |
---|
922 | // summary: |
---|
923 | // Function to display the appropriate sections based on validity. |
---|
924 | |
---|
925 | // Hide select boxes. |
---|
926 | domStyle.set(this.entrySummarySelect, 'display', 'none'); |
---|
927 | domStyle.set(this.entryContentSelect, 'display', 'none'); |
---|
928 | domStyle.set(this.entryTitleSelect, 'display', 'none'); |
---|
929 | |
---|
930 | // Show select boxes if the flags are set. |
---|
931 | if(this.isFieldValid("contentedit")){ |
---|
932 | domStyle.set(this.entryContentSelect, 'display', ''); |
---|
933 | } |
---|
934 | if(this.isFieldValid("summaryedit")){ |
---|
935 | domStyle.set(this.entrySummarySelect, 'display', ''); |
---|
936 | } |
---|
937 | if(this.isFieldValid("titleedit")){ |
---|
938 | domStyle.set(this.entryTitleSelect, 'display', ''); |
---|
939 | } |
---|
940 | // Call super's _displaySections. |
---|
941 | FeedEntryEditor.superclass._displaySections.apply(this); |
---|
942 | |
---|
943 | // If we have editors to load after the nodes are created on the page, execute those now. |
---|
944 | if(this._toLoad){ |
---|
945 | for(var i in this._toLoad){ |
---|
946 | var editor; |
---|
947 | if(this._toLoad[i].generateEditor){ |
---|
948 | editor = lang.hitch(this._toLoad[i], this._toLoad[i].generateEditor)(); |
---|
949 | }else{ |
---|
950 | editor = this._toLoad[i]; |
---|
951 | } |
---|
952 | this._editors[this._toLoad[i].name] = editor; |
---|
953 | this._toLoad[i] = null; |
---|
954 | } |
---|
955 | this._toLoad = null; |
---|
956 | } |
---|
957 | } |
---|
958 | }); |
---|
959 | |
---|
960 | var PeopleEditor = declare("dojox.atom.widget.PeopleEditor", [_Widget, _Templated, _Container],{ |
---|
961 | // summary: |
---|
962 | // An editor for dojox.atom.io.model.Person objects. |
---|
963 | // description: |
---|
964 | // An editor for dojox.atom.io.model.Person objects. Displays multiple rows for the respective arrays |
---|
965 | // of people. Can add/remove rows on the fly. |
---|
966 | templateString: peopleEditorTemplate, |
---|
967 | |
---|
968 | _rows: [], |
---|
969 | _editors: [], |
---|
970 | _index: 0, |
---|
971 | _numRows: 0, |
---|
972 | |
---|
973 | postCreate: function(){ |
---|
974 | // Initializer function for the PeopleEditor widget. |
---|
975 | var _nlsResources = i18nPeople; |
---|
976 | if(this.name){ |
---|
977 | if(this.name == "Author"){ |
---|
978 | this.peopleEditorButton.appendChild(document.createTextNode("["+_nlsResources.addAuthor+"]")); |
---|
979 | }else if(this.name == "Contributor"){ |
---|
980 | this.peopleEditorButton.appendChild(document.createTextNode("["+_nlsResources.addContributor+"]")); |
---|
981 | } |
---|
982 | }else{ |
---|
983 | this.peopleEditorButton.appendChild(document.createTextNode("["+_nlsResources.add+"]")); |
---|
984 | } |
---|
985 | this._editors = []; |
---|
986 | |
---|
987 | if(!this.data || this.data.length===0){ |
---|
988 | this._createEditors(null, null, null, 0, this.name); |
---|
989 | this._index = 1; |
---|
990 | }else{ |
---|
991 | for(var i in this.data){ |
---|
992 | this._createEditors(this.data[i].name, this.data[i].email, this.data[i].uri, i); |
---|
993 | this._index++; |
---|
994 | this._numRows++; |
---|
995 | } |
---|
996 | } |
---|
997 | }, |
---|
998 | |
---|
999 | destroy: function(){ |
---|
1000 | for(var key in this._editors){ |
---|
1001 | for(var key2 in this._editors[key]){ |
---|
1002 | this._editors[key][key2].destroy(); |
---|
1003 | } |
---|
1004 | } |
---|
1005 | this._editors = []; |
---|
1006 | }, |
---|
1007 | |
---|
1008 | _createEditors: function(/*string*/name, /*string*/email, /*string*/uri, /*int*/index, /*string*/widgetName){ |
---|
1009 | // summary: |
---|
1010 | // creates editor boxes (textbox widgets) for the individual values of a Person. |
---|
1011 | // name: |
---|
1012 | // The name of this Person. |
---|
1013 | // email: |
---|
1014 | // The email of this Person. |
---|
1015 | // uri: |
---|
1016 | // The Person's URI. |
---|
1017 | // index: |
---|
1018 | // The row index to use for this Person. |
---|
1019 | var row = document.createElement("tr"); |
---|
1020 | this.peopleEditorEditors.appendChild(row); |
---|
1021 | row.id = "removeRow"+index; |
---|
1022 | |
---|
1023 | var node = document.createElement("td"); |
---|
1024 | node.setAttribute('align', 'right'); |
---|
1025 | row.appendChild(node); |
---|
1026 | node.colSpan = 2; |
---|
1027 | |
---|
1028 | if(this._numRows>0){ |
---|
1029 | var hr = document.createElement("hr"); |
---|
1030 | node.appendChild(hr); |
---|
1031 | hr.id = "hr"+index; |
---|
1032 | } |
---|
1033 | |
---|
1034 | row = document.createElement("span"); |
---|
1035 | node.appendChild(row); |
---|
1036 | row.className = "peopleEditorButton"; |
---|
1037 | domStyle.set(row, 'font-size', 'x-small'); |
---|
1038 | connect.connect(row, "onclick", this, "_removeEditor"); |
---|
1039 | row.id = "remove"+index; |
---|
1040 | |
---|
1041 | node = document.createTextNode("[X]"); |
---|
1042 | row.appendChild(node); |
---|
1043 | |
---|
1044 | row = document.createElement("tr"); |
---|
1045 | this.peopleEditorEditors.appendChild(row); |
---|
1046 | row.id = "editorsRow"+index; |
---|
1047 | |
---|
1048 | var labelNode = document.createElement("td"); |
---|
1049 | row.appendChild(labelNode); |
---|
1050 | domStyle.set(labelNode, 'width', '20%'); |
---|
1051 | |
---|
1052 | node = document.createElement("td"); |
---|
1053 | row.appendChild(node); |
---|
1054 | |
---|
1055 | row = document.createElement("table"); |
---|
1056 | labelNode.appendChild(row); |
---|
1057 | domStyle.set(row, 'width', '100%'); |
---|
1058 | |
---|
1059 | labelNode = document.createElement("tbody"); |
---|
1060 | row.appendChild(labelNode); |
---|
1061 | |
---|
1062 | row = document.createElement("table"); |
---|
1063 | node.appendChild(row); |
---|
1064 | domStyle.set(row, 'width', '100%'); |
---|
1065 | |
---|
1066 | node = document.createElement("tbody"); |
---|
1067 | row.appendChild(node); |
---|
1068 | |
---|
1069 | this._editors[index] = []; |
---|
1070 | this._editors[index].push(this._createEditor(name, widgetName+'name'+index, 'Name:', labelNode, node)); |
---|
1071 | this._editors[index].push(this._createEditor(email, widgetName+'email'+index, 'Email:', labelNode, node)); |
---|
1072 | this._editors[index].push(this._createEditor(uri, widgetName+'uri'+index, 'URI:', labelNode, node)); |
---|
1073 | }, |
---|
1074 | |
---|
1075 | _createEditor: function(/*string*/value, /*string*/id, /*string*/name, /*DOM node*/labelNode, /*DOM node*/node){ |
---|
1076 | // summary: |
---|
1077 | // Creates an individual editor widget (textbox) for a value. |
---|
1078 | // value: |
---|
1079 | // The initial value of the textbox |
---|
1080 | // id: |
---|
1081 | // The id the textbox should have. |
---|
1082 | // name: |
---|
1083 | // The text to put in the label element for this textbox. |
---|
1084 | // labelNode: |
---|
1085 | // The node to attach the label to. |
---|
1086 | // node: |
---|
1087 | // The node to attach the editor rows to. |
---|
1088 | // returns: |
---|
1089 | // Editor widget. |
---|
1090 | var row = document.createElement("tr"); |
---|
1091 | labelNode.appendChild(row); |
---|
1092 | |
---|
1093 | var label = document.createElement("label"); |
---|
1094 | label.setAttribute('for', id); |
---|
1095 | label.appendChild(document.createTextNode(name)); |
---|
1096 | labelNode = document.createElement("td"); |
---|
1097 | labelNode.appendChild(label); |
---|
1098 | row.appendChild(labelNode); |
---|
1099 | |
---|
1100 | row = document.createElement("tr"); |
---|
1101 | node.appendChild(row); |
---|
1102 | |
---|
1103 | node = document.createElement("td"); |
---|
1104 | row.appendChild(node); |
---|
1105 | |
---|
1106 | var viewNode = document.createElement("input"); |
---|
1107 | viewNode.setAttribute('id', id); |
---|
1108 | node.appendChild(viewNode); |
---|
1109 | domStyle.set(viewNode, 'width', '95%'); |
---|
1110 | |
---|
1111 | var box = new TextBox({},viewNode); |
---|
1112 | box.attr('value', value); |
---|
1113 | return box; |
---|
1114 | }, |
---|
1115 | |
---|
1116 | _removeEditor: function(/*object*/event){ |
---|
1117 | // summary: |
---|
1118 | // Removes a Person from our list of editors. |
---|
1119 | // description: |
---|
1120 | // Removes a Person from our list of editors by removing the block of editors that |
---|
1121 | // make up that Person. |
---|
1122 | // event: |
---|
1123 | // The event generated when the remove button is pressed on the page. |
---|
1124 | var target = null; |
---|
1125 | |
---|
1126 | if(has("ie")){ |
---|
1127 | target = event.srcElement; |
---|
1128 | }else{ |
---|
1129 | target = event.target; |
---|
1130 | } |
---|
1131 | |
---|
1132 | var id = target.id; |
---|
1133 | id = id.substring(6); |
---|
1134 | for(var key in this._editors[id]){ |
---|
1135 | this._editors[id][key].destroy(); |
---|
1136 | } |
---|
1137 | |
---|
1138 | var node = domUtil.byId("editorsRow"+id); |
---|
1139 | var parent = node.parentNode; |
---|
1140 | parent.removeChild(node); |
---|
1141 | |
---|
1142 | node = domUtil.byId("removeRow"+id); |
---|
1143 | parent = node.parentNode; |
---|
1144 | parent.removeChild(node); |
---|
1145 | |
---|
1146 | this._numRows--; |
---|
1147 | if(this._numRows === 1 && parent.firstChild.firstChild.firstChild.tagName.toLowerCase() === "hr"){ |
---|
1148 | node = parent.firstChild.firstChild; |
---|
1149 | node.removeChild(node.firstChild); |
---|
1150 | } |
---|
1151 | this._editors[id] = null; |
---|
1152 | }, |
---|
1153 | |
---|
1154 | _add: function(){ |
---|
1155 | // summary: |
---|
1156 | // Adds a new block of blank editors to represent a Person. |
---|
1157 | this._createEditors(null, null, null, this._index); |
---|
1158 | this._index++; |
---|
1159 | this._numRows++; |
---|
1160 | }, |
---|
1161 | |
---|
1162 | getValues: function(){ |
---|
1163 | // summary: |
---|
1164 | // Gets the values of this editor in an array. |
---|
1165 | // description: |
---|
1166 | // Gets the values of this editor in an array, with each Person as an object within the array. |
---|
1167 | // returns: |
---|
1168 | // An array of anonymous objects representing dojox.atom.io.model.Persons. |
---|
1169 | var values = []; |
---|
1170 | for(var i in this._editors){ |
---|
1171 | if(this._editors[i]){ |
---|
1172 | values.push({name: this._editors[i][0].attr('value'), email: this._editors[i][1].attr('value'), uri: this._editors[i][2].attr('value')}); |
---|
1173 | } |
---|
1174 | } |
---|
1175 | return values; |
---|
1176 | } |
---|
1177 | }); |
---|
1178 | |
---|
1179 | return FeedEntryEditor; |
---|
1180 | }); |
---|