adding all weblabels from weblabels.fsf.org
[weblabels.fsf.org.git] / www.fsf.org / 20131028 / files / crm.fsf.org / jquery.crmeditable.js
CommitLineData
5a920362 1/*
2 +--------------------------------------------------------------------+
3 | CiviCRM version 4.2 |
4 +--------------------------------------------------------------------+
5 | This file is a part of CiviCRM. |
6 | |
7 | CiviCRM is free software; you can copy, modify, and distribute it |
8 | under the terms of the GNU Affero General Public License |
9 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
10 | |
11 | CiviCRM is distributed in the hope that it will be useful, but |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
14 | See the GNU Affero General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Affero General Public |
17 | License and the CiviCRM Licensing Exception along |
18 | with this program; if not, contact CiviCRM LLC |
19 | at info[AT]civicrm[DOT]org. If you have questions about the |
20 | GNU Affero General Public License or the licensing of CiviCRM, |
21 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
22 +--------------------------------------------------------------------+
23
24*
25* Copyright (C) 2012 Xavier Dutoit
26* Licensed to CiviCRM under the Academic Free License version 3.0.
27*
28*
29* This offers two features:
30* - crmEditable() edit in place of a single field
31* (mostly a wrapper that binds jeditable features with the ajax api and replies on crm-entity crmf-{field} html conventions)
32* if you want to add an edit in place on a template:
33* - add a class crm-entity and id {EntityName}-{Entityid} higher in the dom
34* - add a class crm-editable and crmf-{FieldName} around the field (you can add a span if needed)
35* - add data-action=create if you need to specify the api action to call (default setvalue)
36* crmf- stands for crm field
37* - crmForm()
38* this embed a civicrm form and make it in place (load+ajaxForm)
39* to make it easier to customize the form (eg. hide a button...) it triggers a 'load' event on the form. you can then catch the load on your code (using the $('#id_of_the_form').on(function(){//do something
40*/
41
42
43(function($){
44
45 $.fn.crmEditable = function (options) {
46
47 // for a jquery object (the crm-editable), find the entity name and id to apply the changes to
48 // call result function(entity,id). The caller is responsible to use these params and do the needed
49 var getEntityID = function (field,result) {
50 var domid= $(field).closest('.crm-entity');
51 if (!domid) {
52 $().crmNotification ("Couldn't get the entity id. You need to set class='crm-entity' on a parent element of the field",'notification',domid);
53 return false;
54 }
55 // trying to extract using the html5 data
56 if (domid.data('entity')) {
57 result (domid.data('entity'),domid.data('id'));
58 return true;
59 }
60 domid=domid.attr('id');
61 if (!domid) {
62 $().crmNotification ("FATAL crm-editable: Couldn't get the entity id. You need to set class='crm-entity' id='{entityName}-{id}'",'notification',domid);
63 return false;
64 }
65 var e=domid.match(/(\S*)-(\S*)/);
66 if (!e) {
67 $().crmNotification ("Couldn't get the entity id. You need to set class='crm-entity' id='{entityName}-{id}'",'notification',this);
68 return false;
69 }
70 result(e[1],e[2]);
71 return true;
72 }
73 // param in : a dom object that contains the field name as a class crmf-xxx
74 var getFieldName = function (field) {
75 if ($(field).data('field')) {
76 return $(field).data('field');
77 }
78 var fieldName=field.className.match(/crmf-(\S*)/)[1];
79 if (!fieldName) {
80 $().crmNotification ("Couldn't get the crm-editable field name to modify. You need to set crmf-{field_name} or data-{field_name}",'notification',field);
81 return false;
82 }
83 return fieldName;
84 }
85
86
87 var checkable = function () {
88 $(this).change (function() {
89 var params={sequential:1};
90 var entity = null;
91 var checked = $(this).is(':checked');
92 if (!getEntityID (this,function (e,id) {
93 entity=e;
94 params.id = id;
95
96 })) { return };
97
98 params['field']=getFieldName(this);
99 if (!params['field'])
100 return false;
101 params['value']=checked?'1':'0';//seems that the ajax backend gets lost with boolean
102
103 //$().crmAPI.call(this,entity,'create',params,{ create is still too buggy & perf
104 $().crmAPI.call(this,entity,'setvalue',params,{
105 error: function (data) {
106 editableSettings.error.call(this,entity,fieldName,checked,data);
107 },
108 success: function (data) {
109 editableSettings.success.call(this,entity,fieldName,checked,data);
110 }
111 });
112 });
113 };
114
115 var defaults = {
116 form:{},
117 callBack:function(data){
118 if (data.is_error) {
119 editableSettings.error.call (this,data);
120 } else {
121 return editableSettings.success.call (this,data);
122 }
123 },
124 error: function(entity,field,value,data) {
125 $().crmNotification (data.error_message,'error',data);
126 $(this).removeClass ('crm-editable-saving').addClass('crm-editable-error');
127 },
128 success: function(entity,field,value,data) {
129 var $i=$(this);
130 $().crmNotification (false);
131 $i.removeClass ('crm-editable-saving').removeClass ('crm-editable-error');
132 $i.html(value);
133 }
134 }
135
136 var editableSettings = $.extend({}, defaults, options);
137 return this.each(function() {
138 var $i = $(this);
139 var fieldName = "";
140
141 if (this.nodeName == "INPUT" && this.type=="checkbox") {
142 checkable.call(this,this);
143 return;
144 }
145
146 if (this.nodeName = 'A') {
147 if (this.className.indexOf('crmf-') == -1) { // it isn't a jeditable field
148 var formSettings= $.extend({}, editableSettings.form ,
149 {source: $i.attr('href')
150 ,success: function (result) {
151 if ($i.hasClass('crm-dialog')) {
152 $('.ui-dialog').dialog('close').remove();
153 } else
154 $i.next().slideUp().remove();
155 $i.trigger('success',result);
156 }
157 });
158 var id= $i.closest('.crm-entity').attr('id');
159 if (id) {
160 var e=id.match(/(\S*)-(\S*)/);
161 if (!e)
162 $().crmNotification ("Couldn't get the entity id. You need to set class='crm-entity' id='{entityName}-{id}'",'notification',this);
163 formSettings.entity=e[1];
164 formSettings.id=e[2];
165 }
166 if ($i.hasClass('crm-dialog')) {
167 $i.click (function () {
168 var $n=$('<div>Loading</div>').appendTo('body');
169 $n.dialog ({modal:true,width:500});
170 $n.crmForm (formSettings);
171 return false;
172 });
173 } else {
174 $i.click (function () {
175 var $n=$i.next();
176 if (!$n.hasClass('crm-target')) {
177 $n=$i.after('<div class="crm-target"></div>').next();
178 } else {
179 $n.slideToggle();
180 return false;
181 };
182 $n.crmForm (formSettings);
183 return false;
184 });
185 }
186 return;
187 }
188 }
189
190
191 var settings = {
192 tooltip : 'Click to edit...',
193 placeholder : '<span class="crm-editable-placeholder">Click to edit</span>',
194 data: function(value, settings) {
195 return value.replace(/<(?:.|\n)*?>/gm, '');
196 }
197 };
198 if ($i.data('placeholder')) {
199 settings.placeholder = $i.data('placeholder');
200 } else {
201 settings.placeholder = '<span class="crm-editable-placeholder">Click to edit</span>';
202 }
203 if ($i.data('tooltip')) {
204 settings.placeholder = $i.data('tooltip')
205 } else {
206 settings.tooltip = 'Click to edit...';
207 }
208
209 $i.addClass ('crm-editable-enabled');
210 $i.editable(function(value,settings) {
211 //$i.editable(function(value,editableSettings) {
212 parent=$i.closest('.crm-entity');
213 if (!parent) {
214 $().crmNotification ("crm-editable: you need to define one parent element that has a class .crm-entity",'notification',this);
215 return;
216 }
217
218 $i.addClass ('crm-editable-saving');
219 var params = {};
220 var entity = null;
221 params['field']=getFieldName(this);
222 if (!params['field'])
223 return false;
224 params['value']=value;
225 if (!getEntityID (this,function (e,id) {
226 entity=e;
227 params.id = id;
228 })) {return;}
229
230 if (params.id == "new") {
231 params.id = '';
232 }
233
234 if ($i.data('action')) {
235 params[params['field']]=value;//format for create at least
236 action=$i.data('action');
237 } else {
238 action="setvalue";
239 }
240 $().crmAPI.call(this,entity,action,params,{
241 //cj().crmAPI.call(this,entity,'setvalue/create',params,{
242 error: function (data) {
243 editableSettings.error.call(this,entity,fieldName,value,data);
244 },
245 success: function (data) {
246 editableSettings.success.call(this,entity,fieldName,value,data);
247 }
248 });
249 },settings);
250 });
251 }
252
253})(jQuery);
254//})(cj);
255
256
257(function($){
258
259 $.fn.crmForm = function (options ) {
260 var settings = $.extend( {
261 'title':'',
262 'entity':'',
263 'action':'get',
264 'id':0,
265 'sequential':1,
266 'dialog': false,
267 'load' : function (target){},
268 'success' : function (result) {
269 $(this).html ("Saved");
270 }
271 }, options);
272
273
274 return this.each(function() {
275 var formLoaded = function (target) {
276 var $this =$(target);
277 var destination="<input type='hidden' name='civicrmDestination' value='"+$.crmURL('civicrm/ajax/rest',{
278 'sequential':settings.sequential,
279 'json':'html',
280 'entity':settings.entity,
281 'action':settings.action,
282 'id':settings.id
283 })+"' />";
284 $this.find('form').ajaxForm({
285 beforeSubmit :function () {
286 $this.html("<div class='crm-editable-saving'>Saving...</div>");
287 return true;
288 },
289 success:function(response) {
290 if (response.indexOf('crm-error') >= 0) { // we got an error, re-display the page
291 $this.html(response);
292 formLoaded(target);
293 } else {
294 if (response[0] == '{')
295 settings.success($.parseJSON (response));
296 else
297 settings.success(response);
298 }
299 }
300 }).append('<input type="hidden" name="snippet" value="1"/>'+destination).trigger('load');
301
302 settings.load(target);
303 };
304
305 var $this = $(this);
306 if (settings.source && settings.source.indexOf('snippet') == -1) {
307 if (settings.source.indexOf('?') >= 0)
308 settings.source = settings.source + "&snippet=1";
309 else
310 settings.source = settings.source + "?snippet=1";
311 }
312
313
314 $this.html ("Loading...");
315 if (settings.dialog)
316 $this.dialog({width:'auto',minWidth:600});
317 $this.load (settings.source ,function (){formLoaded(this)});
318
319 });
320 };
321
322})(jQuery);
323//})(cj);
324