';
187 | }
188 | //html += '
';
189 | html += this.buildElements(form, 0);
190 | //html += '
';
191 | if (this.options.pageMenu)
192 | html += '
';
193 | html += this.endFormHTML(form);
194 | return html; //.replace(/undefined/g, '')
195 | },
196 |
197 | updateElements: function(o, depth) {
198 | //Symple.log('Form Builder: Update Elements:', o);
199 | if (typeof o.elements != 'undefined') {
200 | var prev = o;
201 | var curr;
202 | depth++;
203 | for (var i = 0; i < o.elements.length; i++) {
204 | curr = o.elements[i];
205 | if (curr.type == 'page')
206 | ; // nothing to do...
207 | else if (curr.type == 'section')
208 | this.updateSectionHTML(curr);
209 | else {
210 |
211 | // Update the element
212 | if (this.hasHTMLElement(curr.id))
213 | this.updateFieldHTML(curr);
214 |
215 | // Insert the element
216 | else {
217 | var parent = this.getHTMLElement(prev.id);
218 | var html = this.fieldToHTML(curr);
219 | parent.after(html);
220 | }
221 | }
222 | if (curr.elements)
223 | this.updateElements(curr, depth);
224 | prev = curr;
225 | }
226 | }
227 | },
228 |
229 | buildElements: function(o, depth) {
230 | //Symple.log('Form Builder: Build Elements:', o);
231 | var html = '';
232 |
233 | // Start containers...
234 | if (o.type == 'page')
235 | html += this.startPageHTML(o);
236 | else if (o.type == 'section')
237 | html += this.startSectionHTML(o);
238 | else
239 | html += this.fieldToHTML(o);
240 |
241 | // Loop next level...
242 | if (typeof o.elements == 'object') {
243 | depth++;
244 | for (var i = 0; i < o.elements.length; i++) {
245 | var a = o.elements[i];
246 | html += this.buildElements(a, depth);
247 | }
248 | }
249 |
250 | // End containers...
251 | if (o.type == 'page')
252 | html += this.endPageHTML(o);
253 | else if (o.type == 'section')
254 | html += this.endSectionHTML(o);
255 |
256 | /*
257 | if (typeof o.elements == 'object') {
258 | depth++;
259 | for (var i = 0; i < o.elements.length; i++) {
260 | var a = o.elements[i];
261 | if (typeof a == 'object') {
262 | if (a.type == 'page')
263 | html += this.fieldToHTML(a);
264 |
265 | // Next level...
266 | if (typeof a.elements == 'object')
267 | html += this.buildElements(a, depth);
268 | }
269 | }
270 | }
271 | */
272 |
273 | return html;
274 | },
275 |
276 | buildPageMenu: function(o, depth) {
277 | var html = '';
278 | var root = depth == 0;
279 | if (root)
280 | html += '';
300 | return html;
301 | },
302 |
303 | startFormHTML: function(o) {
304 | var className = this.options.formClass;
305 | if (this.options.pageMenu)
306 | className += ' symple-paged-form';
307 |
308 | var html = '';
337 | if (o.label)
338 | html += '
' + o.label + '
';
339 | if (o.hint)
340 | html += '
' + o.hint + '
';
341 | html += '
' + (o.error ? o.error : '') + '
';
342 | //if (o.error)
343 | // html += '
' + o.error + '
';
344 | return html;
345 | },
346 |
347 | endPageHTML: function(o) {
348 | return '
';
349 | },
350 |
351 | startSectionHTML: function(o) {
352 | var id = this.getElementID(o);
353 | //if (id == 'undefined' && o.label)
354 | // id = this.form.id + '-' + o.label.paramaterize();
355 | var className = '';
356 | //if (o.live)
357 | // className += ' live';
358 |
359 | var html = ''
360 | html += '';
492 | if (o.label)
493 | html += this.buildLabel(o);
494 | html += '
';
495 | return html;
496 | },
497 |
498 | endFieldHTML: function(o) {
499 | var html = '';
500 | if (o.hint)
501 | html += '
' + o.hint + '
';
502 | html += '
' + (o.error ? o.error : '') + '
';
503 | html += '
';
504 | html += '
';
505 | return html;
506 | },
507 |
508 | // Updates field HTML from JSON.
509 | updateFieldHTML: function(field) {
510 | Symple.log('Form Builder: Updating Field HTML:', field)
511 |
512 | var el = this.element.find('[name="' + field.id + '"]');
513 | if (el.length) {
514 | switch (el.get(0).nodeName) {
515 | case 'INPUT':
516 | el.val(field.values[0]);
517 | break;
518 | case 'TEXTAREA':
519 | el.text(field.values[0]);
520 | break;
521 | case 'SELECT':
522 | $('option:selected', el).attr('selected', false);
523 | for (var ia = 0; ia < field.values.length; ia++) {
524 | $('option[value="' + field.values[ia] + '"]', el).attr('selected', true);
525 | }
526 | break;
527 | default: return null;
528 | }
529 |
530 | var fel = el.parents('.field:first');
531 | if (field.error) {
532 | fel.find('.error').text(field.error).show();
533 | } else
534 | fel.find('.error').hide();
535 | /*
536 | Symple.log('Form Builder: Updating Field HTML: Error Field:', fel.html())
537 | // afterBuild will show/hide errors
538 | var fel = el.parents('.field:first');
539 | fel.find('.error').text(field.error ? field.error : '');
540 | */
541 | fel.find('.loading').remove(); // for live fields, not built in yet
542 | }
543 |
544 | return el;
545 | },
546 |
547 | fieldToHTML: function(o) {
548 | var html = '';
549 | try {
550 | Symple.log('Form Builder: Building:', 'build' + o.type.classify() + 'Field');
551 | html += this['build' + o.type.classify() + 'Field'](o);
552 | }
553 | catch(e) {
554 | Symple.log('Form Builder: Unrecognised form field:', o.type, e);
555 | }
556 | return html;
557 | },
558 |
559 | // Update internal form data from a partial.
560 | mergeFormElements: function(destination, source) {
561 | if (destination.elements && source.elements) {
562 | for (var si = 0; si < source.elements.length; si++) {
563 | // Recurse if there are sub elements
564 | if (source.elements[si].elements) {
565 | for (var di = 0; di < destination.elements.length; di++) {
566 | if (destination.elements[di].id == source.elements[si].id) {
567 | arguments.callee(destination.elements[di], source.elements[si]);
568 | }
569 | }
570 | }
571 | // Update the current field
572 | else {
573 | for (var di = 0; di < destination.elements.length; di++) {
574 | if (destination.elements[di].id == source.elements[si].id) {
575 | Symple.log('Form Builder: mergeFormElements:', destination.elements[di], source.elements[si]);
576 | destination.elements[di] = source.elements[si];
577 | }
578 | }
579 | }
580 | }
581 | }
582 | }
583 | };
584 |
585 |
586 | // -----------------------------------------------------------------------------
587 | // JQuery Plugin
588 | //
589 | (function(jQuery){
590 | $.sympleForm = $.sympleForm || {}
591 |
592 | $.sympleForm.options = {
593 | formClass: 'stacked',
594 | pageMenu: false,
595 | afterBuild: function(form, el) {},
596 | onSubmit: function(form, el) {}
597 | };
598 |
599 | $.sympleForm.build = function(form, options) {
600 | return createForm(form, $('';
165 | if (message.from &&
166 | typeof(message.from) == 'object' &&
167 | typeof(message.from.name) == 'string')
168 | html += '' + message.from.name + ': ';
169 | html += '' + (typeof(message.body) == 'undefined' ? message.data : message.body) + '';
170 | html += '' + this.formatTime(time) + '';
171 | html += '
';
172 | return html;
173 | },
174 |
175 | messageTime: function(message) {
176 | return typeof(message.sent_at) == 'undefined' ? new Date() : Symple.parseISODate(message.sent_at)
177 | },
178 |
179 | isScrollBottom: function(elem) {
180 | return (elem[0].scrollHeight - elem.scrollTop() == elem.outerHeight());
181 | },
182 |
183 | getOrCreateDateSection: function(message) {
184 | var time = message.time ? message.time : this.messageTime(message);
185 | var dateStr = time.toDateString();
186 | var section = this.messages.find('.section[data-date="' + dateStr + '"]');
187 | if (!section.length) {
188 | section = $(
189 | '