今回はcontrols.
InPlaceEditorとは?
1991年にティム・
Ajax.
Ajax.
Ajax.InPlaceEditor
それでは、
去年の夏に書き直されたおかげで、
0469: // AJAX in-place editor and collection editor
0470: // Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
0471:
0472: // Use this if you notice weird scrolling problems on some browsers,
0473: // the DOM might be a bit confused when this gets called so do this
0474: // waits 1 ms (with setTimeout) until it does the activation
0475: Field.scrollFreeActivate = function(field) {
0476: setTimeout(function() {
0477: Field.activate(field);
0478: }, 1);
0479: }
0480:
475~480行目のField.
0481: Ajax.InPlaceEditor = Class.create({
0482: initialize: function(element, url, options) {
0483: this.url = url;
0484: this.element = element = $(element);
0485: this.prepareOptions();
0486: this._controls = { };
0487: arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
0488: Object.extend(this.options, options || { });
0489: if (!this.options.formId && this.element.id) {
0490: this.options.formId = this.element.id + '-inplaceeditor';
0491: if ($(this.options.formId))
0492: this.options.formId = '';
0493: }
0494: if (this.options.externalControl)
0495: this.options.externalControl = $(this.options.externalControl);
0496: if (!this.options.externalControl)
0497: this.options.externalControlOnly = false;
0498: this._originalBackground = this.element.getStyle('background-color') || 'transparent';
0499: this.element.title = this.options.clickToEditText;
0500: this._boundCancelHandler = this.handleFormCancellation.bind(this);
0501: this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
0502: this._boundFailureHandler = this.handleAJAXFailure.bind(this);
0503: this._boundSubmitHandler = this.handleFormSubmission.bind(this);
0504: this._boundWrapperHandler = this.wrapUp.bind(this);
0505: this.registerListeners();
0506: },
481~506行目のinitializeは、
483行目で、
485行目で、
488行目で、
494行目で、
498行目で、
500~504行目で、
505行目で、
0507: checkForEscapeOrReturn: function(e) {
0508: if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
0509: if (Event.KEY_ESC == e.keyCode)
0510: this.handleFormCancellation(e);
0511: else if (Event.KEY_RETURN == e.keyCode)
0512: this.handleFormSubmission(e);
0513: },
507~513行目のcheckForEscapeOrReturnは、
508行目で、
509行目で、
511行目で、
0514: createControl: function(mode, handler, extraClasses) {
0515: var control = this.options[mode + 'Control'];
0516: var text = this.options[mode + 'Text'];
0517: if ('button' == control) {
0518: var btn = document.createElement('input');
0519: btn.type = 'submit';
0520: btn.value = text;
0521: btn.className = 'editor_' + mode + '_button';
0522: if ('cancel' == mode)
0523: btn.onclick = this._boundCancelHandler;
0524: this._form.appendChild(btn);
0525: this._controls[mode] = btn;
0526: } else if ('link' == control) {
0527: var link = document.createElement('a');
0528: link.href = '#';
0529: link.appendChild(document.createTextNode(text));
0530: link.onclick = 'cancel' == mode ? this._boundCancelHandler: this._boundSubmitHandler;
0531: link.className = 'editor_' + mode + '_link';
0532: if (extraClasses)
0533: link.className += ' ' + extraClasses;
0534: this._form.appendChild(link);
0535: this._controls[mode] = link;
0536: }
0537: },
514~537行目のcreateControlは、
これらは設定しだいで、
0538: createEditField: function() {
0539: var text = (this.options.loadTextURL ? this.options.loadingText: this.getText());
0540: var fld;
0541: if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
0542: fld = document.createElement('input');
0543: fld.type = 'text';
0544: var size = this.options.size || this.options.cols || 0;
0545: if (0 < size) fld.size = size;
0546: } else {
0547: fld = document.createElement('textarea');
0548: fld.rows = (1 >= this.options.rows ? this.options.autoRows: this.options.rows);
0549: fld.cols = this.options.cols || 40;
0550: }
0551: fld.name = this.options.paramName;
0552: fld.value = text; // No HTML breaks conversion anymore
0553: fld.className = 'editor_field';
0554: if (this.options.submitOnBlur)
0555: fld.onblur = this._boundSubmitHandler;
0556: this._controls.editor = fld;
0557: if (this.options.loadTextURL)
0558: this.loadExternalText();
0559: this._form.appendChild(this._controls.editor);
0560: },
538~560行目のcreateEditFieldは、
539行目で、
542行目で、
547行目で、
551行目で、
552行目で、
553行目で、
554行目で、
557行目で、
0561: createForm: function() {
0562: var ipe = this;
0563: function addText(mode, condition) {
0564: var text = ipe.options['text' + mode + 'Controls'];
0565: if (!text || condition === false) return;
0566: ipe._form.appendChild(document.createTextNode(text));
0567: };
0568: this._form = $(document.createElement('form'));
0569: this._form.id = this.options.formId;
0570: this._form.addClassName(this.options.formClassName);
0571: this._form.onsubmit = this._boundSubmitHandler;
0572: this.createEditField();
0573: if ('textarea' == this._controls.editor.tagName.toLowerCase())
0574: this._form.appendChild(document.createElement('br'));
0575: if (this.options.onFormCustomization)
0576: this.options.onFormCustomization(this, this._form);
0577: addText('Before', this.options.okControl || this.options.cancelControl);
0578: this.createControl('ok', this._boundSubmitHandler);
0579: addText('Between', this.options.okControl && this.options.cancelControl);
0580: this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
05>0581: addText('After', this.options.okControl || this.options.cancelControl);
0582: },
561~582行目のcreateFormは、
<form id=options.formId className=options.formClassName onsubmit=_boundSubmitHandler>
createEditField() ここに入力エリアが入る
入力エリアがtextarea要素なら <br> を挿入
options.textBeforeControls 文字列が入る
createControl('ok'); 'ok'ボタンやリンクが入る
options.textBetweenControls 文字列が入る
createControl('cancel'); 'cancel'リンクやボタンが入る
options.textAfterControls 文字列が入る
</form>
563行目のaddTextはオプションのoptions.
575行目で、
0583: destroy: function() {
0584: if (this._oldInnerHTML)
0585: this.element.innerHTML = this._oldInnerHTML;
0586: this.leaveEditMode();
0587: this.unregisterListeners();
0588: },
583~588行目のdestroyは、
584行目で、
586行目で、
587行目で、
0589: enterEditMode: function(e) {
0590: if (this._saving || this._editing) return;
0591: this._editing = true;
0592: this.triggerCallback('onEnterEditMode');
0593: if (this.options.externalControl)
0594: this.options.externalControl.hide();
0595: this.element.hide();
0596: this.createForm();
0597: this.element.parentNode.insertBefore(this._form, this.element);
0598: if (!this.options.loadTextURL)
0599: this.postProcessEditField();
0600: if (e) Event.stop(e);
0601: },
589~601行目はenterEditModeです。この関数は、
592行目で、
593行目で、
595行目で、
596行目で、
597行目で、
598行目で、
0602: enterHover: function(e) {
0603: if (this.options.hoverClassName)
0604: this.element.addClassName(this.options.hoverClassName);
0605: if (this._saving) return;
0606: this.triggerCallback('onEnterHover');
0607: },
602~607行目のenterHoverは、
603行目で、
605行目で、
606行目でonEnterHoverフックを呼びます。このフックは、
0608: getText: function() {
0609: return this.element.innerHTML;
0610: },
608~610行目のgetTextは、
0611: handleAJAXFailure: function(transport) {
0612: this.triggerCallback('onFailure', transport);
0613: if (this._oldInnerHTML) {
0614: this.element.innerHTML = this._oldInnerHTML;
0615: this._oldInnerHTML = null;
0616: }
0617: },
611~617行目のhandleAJAXFailureは、
612行目で、
613行目で、
0618: handleFormCancellation: function(e) {
0619: this.wrapUp();
0620: if (e) Event.stop(e);
0621: },
618~621行目のhandleFormCancellationは、
0622: handleFormSubmission: function(e) {
0623: var form = this._form;
0624: var value = $F(this._controls.editor);
0625: this.prepareSubmission();
0626: var params = this.options.callback(form, value) || '';
0627: if (Object.isString(params))
0628: params = params.toQueryParams();
0629: params.editorId = this.element.id;
0630: if (this.options.htmlResponse) {
0631: var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
0632: Object.extend(options, {
0633: parameters: params,
0634: onComplete: this._boundWrapperHandler,
0635: onFailure: this._boundFailureHandler
0636: });
0637: new Ajax.Updater({ success: this.element }, this.url, options);
0638: } else {
0639: var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
0640: Object.extend(options, {
0641: parameters: params,
0642: onComplete: this._boundWrapperHandler,
0643: onFailure: this._boundFailureHandler
0644: });
0645: new Ajax.Request(this.url, options);
0646: }
0647: if (e) Event.stop(e);
0648: },
622~648行目のhandleFormSubmissionは、
625行目で、
626行目以降で、
Ajaxの完了時は、
失敗時は、
options.
options.
0649: leaveEditMode: function() {
0650: this.element.removeClassName(this.options.savingClassName);
0651: this.removeForm();
0652: this.leaveHover();
0653: this.element.style.backgroundColor = this._originalBackground;
0654: this.element.show();
0655: if (this.options.externalControl)
0656: this.options.externalControl.show();
0657: this._saving = false;
0658: this._editing = false;
0659: this._oldInnerHTML = null;
0660: this.triggerCallback('onLeaveEditMode');
0661: },
649~661行目のleaveEditModeは、
651行目で、
652行目で、
653行目で、
654行目で、
655行目で、
660行目で、
0662: leaveHover: function(e) {
0663: if (this.options.hoverClassName)
0664: this.element.removeClassName(this.options.hoverClassName);
0665: if (this._saving) return;
0666: this.triggerCallback('onLeaveHover');
0667: },
662~667行目のleaveHoverは、
663行目で、
665行目で、
666行目で、
0668: loadExternalText: function() {
0669: this._form.addClassName(this.options.loadingClassName);
0670: this._controls.editor.disabled = true;
0671: var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
0672: Object.extend(options, {
0673: parameters: 'editorId=' + encodeURIComponent(this.element.id),
0674: onComplete: Prototype.emptyFunction,
0675: onSuccess: function(transport) {
0676: this._form.removeClassName(this.options.loadingClassName);
0677: var text = transport.responseText;
0678: if (this.options.stripLoadedTextTags)
0679: text = text.stripTags();
0680: this._controls.editor.value = text;
0681: this._controls.editor.disabled = false;
0682: this.postProcessEditField();
0683: }.bind(this),
0684: onFailure: this._boundFailureHandler
0685: });
0686: new Ajax.Request(this.options.loadTextURL, options);
0687: },
668~687行目のloadExternalTextは、
669行目で、
670行目で、
672~685行目で、
673行目で、
674行目で、
675行目で、
676行目で、
677行目で、
678行目で、
680行目で、
681行目で、
682行目で、
684行目で、
686行目で、
0688: postProcessEditField: function() {
0689: var fpc = this.options.fieldPostCreation;
0690: if (fpc)
0691: $(this._controls.editor)['focus' == fpc ? 'focus': 'activate']();
0692: },
688~692行目のpostProcessEditFieldは、
0693: prepareOptions: function() {
0694: this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
0695: Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
0696: [this._extraDefaultOptions].flatten().compact().each(function(defs) {
0697: Object.extend(this.options, defs);
0698: }.bind(this));
0699: },
693~699行目の prepareOptionsはデフォルトのオプションをthis.
0700: prepareSubmission: function() {
0701: this._saving = true;
0702: this.removeForm();
0703: this.leaveHover();
0704: this.showSaving();
0705: },
700~705行目のprepareSubmissionは、
0706: registerListeners: function() {
0707: this._listeners = { };
0708: var listener;
0709: $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
0710: listener = this[pair.value].bind(this);
0711: this._listeners[pair.key] = listener;
0712: if (!this.options.externalControlOnly)
0713: this.element.observe(pair.key, listener);
0714: if (this.options.externalControl)
0715: this.options.externalControl.observe(pair.key, listener);
0716: }.bind(this));
0717: },
706~717行目のregisterListenersは、
709行目で、
デフォルトではこれらを要素と外部コントロールの両方に登録しますが、
0718: removeForm: function() {
0719: if (!this._form) return;
0720: this._form.remove();
0721: this._form = null;
0722: this._controls = { };
0723: },
718~723行目のremoveFormは、
0724: showSaving: function() {
0725: this._oldInnerHTML = this.element.innerHTML;
0726: this.element.innerHTML = this.options.savingText;
0727: this.element.addClassName(this.options.savingClassName);
0728: this.element.style.backgroundColor = this._originalBackground;
0729: this.element.show();
0730: },
724~730行目の showSaving は、
725行目で、
726行目で、
727行目で、
728行目で、
729行目で、
0731: triggerCallback: function(cbName, arg) {
0732: if ('function' == typeof this.options[cbName]) {
0733: this.options[cbName](this, arg);
0734: }
0735: },
731~735行目のtriggerCallbackはオプションであたえられたフックを呼ぶ関数です。
0736: unregisterListeners: function() {
0737: $H(this._listeners).each(function(pair) {
0738: if (!this.options.externalControlOnly)
0739: this.element.stopObserving(pair.key, pair.value);
0740: if (this.options.externalControl)
0741: this.options.externalControl.stopObserving(pair.key, pair.value);
0742: }.bind(this));
0743: },
736~743行目のunregisterListenersは、
0744: wrapUp: function(transport) {
0745: this.leaveEditMode();
0746: // Can't use triggerCallback due to backward compatibility: requires
0747: // binding + direct element
0748: this._boundComplete(transport, this.element);
0749: }
0750: });
0751:
744~751行目のwrapUpは、
745行目で、
748行目の_boundCompleteの実体はoptions.
0752: Object.extend(Ajax.InPlaceEditor.prototype, {
0753: dispose: Ajax.InPlaceEditor.prototype.destroy
0754: });
0755:
InPlaceEditorクラスにdisposeメソッドを追加しています。このメソッドはdestoryメソッド同様、
以上でAjax.
InPlaceCollectionEditorとは
InPlaceCollectionEditorでは、
オプションで、
Ajax.InPlaceCollectionEditor
それでは、
処理の流れは、
その中で、
0756: Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
0757: initialize: function($super, element, url, options) {
0758: this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
0759: $super(element, url, options);
0760: },
0761:
757~761行目のinitializeは、
0762: createEditField: function() {
0763: var list = document.createElement('select');
0764: list.name = this.options.paramName;
0765: list.size = 1;
0766: this._controls.editor = list;
0767: this._collection = this.options.collection || [];
0768: if (this.options.loadCollectionURL)
0769: this.loadCollection();
0770: else
0771: this.checkForExternalText();
0772: this._form.appendChild(this._controls.editor);
0773: },
0774:
762~774行目のcreateEditFieldは、
763行目で、
764行目で、
767行目で、
769行目で、
771行目で、
0775: loadCollection: function() {
0776: this._form.addClassName(this.options.loadingClassName);
0777: this.showLoadingText(this.options.loadingCollectionText);
0778: var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
0779: Object.extend(options, {
0780: parameters: 'editorId=' + encodeURIComponent(this.element.id),
0781: onComplete: Prototype.emptyFunction,
0782: onSuccess: function(transport) {
0783: var js = transport.responseText.strip();
0784: if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
0785: throw 'Server returned an invalid collection representation.';
0786: this._collection = eval(js);
0787: this.checkForExternalText();
0788: }.bind(this),
0789: onFailure: this.onFailure
0790: });
0791: new Ajax.Request(this.options.loadCollectionURL, options);
0792: },
0793:
775~793行目のloadCollectionは、
776行目で、
777行目で、
778~791行目で、
780行目で、
781行目で、
782行目で、
783行目で、
784行目で、
786行目で、
787行目で、
791行目で、
0794: showLoadingText: function(text) {
0795: this._controls.editor.disabled = true;
0796: var tempOption = this._controls.editor.firstChild;
0797: if (!tempOption) {
0798: tempOption = document.createElement('option');
0799: tempOption.value = '';
0800: this._controls.editor.appendChild(tempOption);
0801: tempOption.selected = true;
0802: }
0803: tempOption.update((text || '').stripScripts().stripTags());
0804: },
0805:
793~805行目のshowLoadingTextは、
795行目で、
796行目で、
797~802行目で、
803行目で、
0806: checkForExternalText: function() {
0807: this._text = this.getText();
0808: if (this.options.loadTextURL)
0809: this.loadExternalText();
0810: else
0811: this.buildOptionList();
0812: },
0813:
806~813行目のcheckForExternalTextは、
807行目で、
808行目で、
Ajaxを使う必要がなければ、
0814: loadExternalText: function() {
0815: this.showLoadingText(this.options.loadingText);
0816: var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
0817: Object.extend(options, {
0818: parameters: 'editorId=' + encodeURIComponent(this.element.id),
0819: onComplete: Prototype.emptyFunction,
0820: onSuccess: function(transport) {
0821: this._text = transport.responseText.strip();
0822: this.buildOptionList();
0823: }.bind(this),
0824: onFailure: this.onFailure
0825: });
0826: new Ajax.Request(this.options.loadTextURL, options);
0827: },
0828:
814~828行目のloadExternalTextは、
815行目で、
816~825行目で、
818行目で、
819行目で、
820行目で、
821行目で、
822行目で、
824行目で、
826行目で、
0829: buildOptionList: function() {
0830: this._form.removeClassName(this.options.loadingClassName);
0831: this._collection = this._collection.map(function(entry) {
0832: return 2 === entry.length ? entry: [entry, entry].flatten();
0833: });
0834: var marker = ('value' in this.options) ? this.options.value: this._text;
0835: var textFound = this._collection.any(function(entry) {
0836: return entry[0] == marker;
0837: }.bind(this));
0838: this._controls.editor.update('');
0839: var option;
0840: this._collection.each(function(entry, index) {
0841: option = document.createElement('option');
0842: option.value = entry[0];
0843: option.selected = textFound ? entry[0] == marker: 0 == index;
0844: option.appendChild(document.createTextNode(entry[1]));
0845: this._controls.editor.appendChild(option);
0846: }.bind(this));
0847: this._controls.editor.disabled = false;
0848: Field.scrollFreeActivate(this._controls.editor);
0849: }
0850: });
0851:
829~851行目のbuildOptionListは、
this._collectionの内容は、
831行目で、
834行目のmarkerは、
835行目のtextFoundには、
838行目で、
840~846行目で、
- <option value="one" selected=false>はい</option>
- <option value="two" selected=true>いいえ</option>
- <option value="three" selected=false>無回答</option>
847行目で、
848行目で、
0852: //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
0853: //**** This only exists for a while, in order to let ****
0854: //**** users adapt to the new API. Read up on the new ****
0855: //**** API and convert your code to it ASAP! ****
0856:
0857: Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
0858: if (!options) return;
0859: function fallback(name, expr) {
0860: if (name in options || expr === undefined) return;
0861: options[name] = expr;
0862: };
0863: fallback('cancelControl', (options.cancelLink ? 'link': (options.cancelButton ? 'button':
0864: options.cancelLink == options.cancelButton == false ? false: undefined)));
0865: fallback('okControl', (options.okLink ? 'link': (options.okButton ? 'button':
0866: options.okLink == options.okButton == false ? false: undefined)));
0867: fallback('highlightColor', options.highlightcolor);
0868: fallback('highlightEndColor', options.highlightendcolor);
0869: };
0870:
852~870行目のdealWithDeprecatedOptionsは古いオプションを扱うための関数です。いずれ削除されるので、
cancelLink,cancelButton,okLink,okButton,highlightcolor,highlightendcolorという古いオプションを、
0871: Object.extend(Ajax.InPlaceEditor, {
0872: DefaultOptions: {
0873: ajaxOptions: { },
0874: autoRows: 3, // Use when multi-line w/ rows == 1
0875: cancelControl: 'link', // 'link'|'button'|false
0876: cancelText: 'cancel',
0877: clickToEditText: 'Click to edit',
0878: externalControl: null, // id|elt
0879: externalControlOnly: false,
0880: fieldPostCreation: 'activate', // 'activate'|'focus'|false
0881: formClassName: 'inplaceeditor-form',
0882: formId: null, // id|elt
0883: highlightColor: '#ffff99',
0884: highlightEndColor: '#ffffff',
0885: hoverClassName: '',
0886: htmlResponse: true,
0887: loadingClassName: 'inplaceeditor-loading',
0888: loadingText: 'Loading...',
0889: okControl: 'button', // 'link'|'button'|false
0890: okText: 'ok',
0891: paramName: 'value',
0892: rows: 1, // If 1 and multi-line, uses autoRows
0893: savingClassName: 'inplaceeditor-saving',
0894: savingText: 'Saving...',
0895: size: 0,
0896: stripLoadedTextTags: false,
0897: submitOnBlur: false,
0898: textAfterControls: '',
0899: textBeforeControls: '',
0900: textBetweenControls: ''
0901: },
871~901行目は、
0902: DefaultCallbacks: {
0903: callback: function(form) {
0904: return Form.serialize(form);
0905: },
0906: onComplete: function(transport, element) {
0907: // For backward compatibility, this one is bound to the IPE, and passes
0908: // the element directly. It was too often customized, so we don't break it.
0909: new Effect.Highlight(element, {
0910: startcolor: this.options.highlightColor, keepBackgroundImage: true });
0911: },
0912: onEnterEditMode: null,
0913: onEnterHover: function(ipe) {
0914: ipe.element.style.backgroundColor = ipe.options.highlightColor;
0915: if (ipe._effect)
0916: ipe._effect.cancel();
0917: },
0918: onFailure: function(transport, ipe) {
0919: alert('Error communication with the server: ' + transport.responseText.stripTags());
0920: },
0921: onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
0922: onLeaveEditMode: null,
0923: onLeaveHover: function(ipe) {
0924: ipe._effect = new Effect.Highlight(ipe.element, {
0925: startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
0926: restorecolor: ipe._originalBackground, keepBackgroundImage: true
0927: });
0928: }
0929: },
902~929行目は、
callbackは入力フォームの内容がサーバに送信される直前に呼ばれます。この時点で、
入力フォームはDOMから除かれ、 'Saving...'が表示されています。
このフックは引数に、入力フォームと入力フォームの内容 (デフォルトでは入力フォームがForm. serializeでシリアライズされたもの) をとります。これを使うことで、 入力フォームの内容を簡単にカスタマイズすることができます。 onEnterEditModeは、
編集が始まる直前に呼ばれます、 原則として"その場で編集"要素をクリックしてすぐです。外部コントロールは、 (もしあれば) まだ表示されたままです。要素もそのままです。入力フォームはまだ生成されていません。
このフックがとる引数はひとつで、InPlaceEditorのインスタンスです。 onLeaveEditModeは対称で、
すべての編集作業が終わって入力フォームがページのDOMから取り払われたあとに呼ばれます。
フックの引数はonEnterEditModeと同じです。onEnterHoverは、
カーソルが"その場で編集"要素の上にはいったときに呼ばれます。デフォルトでは、 背景の色をhighlightColorオプションの色にします。
このフックがとる引数はひとつで、InPlaceEditorのインスタンスです。 onLeaveHoverは対称で、
カーソルが要素の上からでたときに呼ばれます。Effect. Highlightで背景色をハイライトしてから、 元の色に戻します (背景イメージもハイライトします)。 onCompleteは編集をキャンセルしたときと、
編集を完了してサーバーに送信が成功したときに呼ばれます。ハイライトして反応を示します (背景イメージもハイライトします)。
このフックがとる引数はふたつです。XMLHttpRequestオブジェクト(キャンセルのときはundefinedです) と"その場で編集"要素です。 onFailureは、
内部でAjaxリクエストが失敗したとき (あるいはHTTPレスポンスが2xxコードでなかったとき) に呼ばれます。デフォルトではレスポンスの内容の詳細が書かれたメッセージボックスを表示します。
このフックは引数にXMLHttpRequestとInPlaceEditorのインスタンスをとります。onFormCustomizationは最近になって新設されたフックで、
フォームをカスタマイズしやすくするために用意されました。フォームが作成されてすぐに呼ばれます。この時点では、 他のコントロール (OKボタン/Cancelリンクなど) はまだありません。
このフックは引数にInPlaceEditorのインスタンスとフォームをとります。自分でコントロールをいくつか追加したいときはここでappendChildを使えばいいので、ずいぶん便利になりました。
0930: Listeners: {
0931: click: 'enterEditMode',
0932: keydown: 'checkForEscapeOrReturn',
0933: mouseover: 'enterHover',
0934: mouseout: 'leaveHover'
0935: }
0936: });
0937:
930~937行目は、
0938: Ajax.InPlaceCollectionEditor.DefaultOptions = {
0939: loadingCollectionText: 'Loading options...'
0940: };
0941:
938~941行目は、
以上でAjax.
Form.Element.DelayedObserver
0942: // Delayed observer, like Form.Element.Observer,
0943: // but waits for delay after last key input
0944: // Ideal for live-search fields
0945:
0946: Form.Element.DelayedObserver = Class.create({
0947: initialize: function(element, delay, callback) {
0948: this.delay = delay || 0.5;
0949: this.element = $(element);
0950: this.callback = callback;
0951: this.timer = null;
0952: this.lastValue = $F(this.element);
0953: Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
0954: },
0955: delayedListener: function(event) {
0956: if(this.lastValue == $F(this.element)) return;
0957: if(this.timer) clearTimeout(this.timer);
0958: this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
0959: this.lastValue = $F(this.element);
0960: },
0961: onTimerEvent: function() {
0962: this.timer = null;
0963: this.callback(this.element, $F(this.element));
0964: }
0965: });
942~965行目のForm.
以上で、