47 function ajax_autocompleter($selected, $htmlname, $url, $urloption =
'', $minLength = 2, $autoselect = 0, $ajaxoptions = array(), $moreparams =
'')
51 if (empty($minLength)) {
55 $dataforrenderITem =
'ui-autocomplete';
56 $dataforitem =
'ui-autocomplete-item';
58 if (defined(
'JS_QUERY_AUTOCOMPLETE_RENDERITEM')) {
59 $dataforrenderITem = constant(
'JS_QUERY_AUTOCOMPLETE_RENDERITEM');
61 if (defined(
'JS_QUERY_AUTOCOMPLETE_ITEM')) {
62 $dataforitem = constant(
'JS_QUERY_AUTOCOMPLETE_ITEM');
65 $htmlnamejquery = str_replace(
'.',
'\\\\.', $htmlname);
69 $script =
'<input type="hidden" name="'.$htmlname.
'" id="'.$htmlname.
'" value="'.$selected.
'" '.($moreparams ? $moreparams :
'').
' />';
71 $script .=
'<!-- Javascript code for autocomplete of field '.$htmlname.
' -->'.
"\n";
72 $script .=
'<script>'.
"\n";
73 $script .=
'$(document).ready(function() {
74 var autoselect = '.((int) $autoselect).
';
75 var options = '.json_encode($ajaxoptions).
'; /* Option of actions to do after keyup, or after select */
77 /* Remove selected id as soon as we type or delete a char (it means old selection is wrong). Use keyup/down instead of change to avoid loosing the product id. This is needed only for select of predefined product */
78 $("input#search_'.$htmlnamejquery.
'").keydown(function(e) {
79 if (e.keyCode != 9) /* If not "Tab" key */
81 if (e.keyCode == 13) { return false; } /* disable "ENTER" key useful for barcode readers */
82 console.log("Clear id previously selected for field '.$htmlname.
'");
83 $("#'.$htmlnamejquery.
'").val("");
87 // Check options for secondary actions when keyup
88 $("input#search_'.$htmlnamejquery.
'").keyup(function() {
89 if ($(this).val().length == 0)
91 $("#search_'.$htmlnamejquery.
'").val("");
92 $("#'.$htmlnamejquery.
'").val("").trigger("change");
93 if (options.option_disabled) {
94 $("#" + options.option_disabled).removeAttr("disabled");
96 if (options.disabled) {
97 $.each(options.disabled, function(key, value) {
98 $("#" + value).removeAttr("disabled");
101 if (options.update) {
102 $.each(options.update, function(key, value) {
103 $("#" + key).val("").trigger("change");
107 $.each(options.show, function(key, value) {
108 $("#" + value).hide().trigger("hide");
111 if (options.update_textarea) {
112 $.each(options.update_textarea, function(key, value) {
113 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
114 CKEDITOR.instances[key].setData("");
116 $("#" + key).html("");
123 $("input#search_'.$htmlnamejquery.
'").autocomplete({
124 source: function( request, response ) {
125 $.get("'.$url.($urloption ?
'?'.$urloption :
'').
'", { "'.str_replace(
'.',
'_', $htmlname).
'": request.term }, function(data){
128 response($.map( data, function(item) {
129 if (autoselect == 1 && data.length == 1) {
130 $("#search_'.$htmlnamejquery.
'").val(item.value);
131 $("#'.$htmlnamejquery.
'").val(item.key).trigger("change");
133 var label = item.label.toString();
135 if (options.update) {
136 $.each(options.update, function(key, value) {
137 update[key] = item[value];
141 if (options.update_textarea) {
142 $.each(options.update_textarea, function(key, value) {
143 textarea[key] = item[value];
147 console.log("Return value from GET to the rest of code");
148 return { label: label,
151 disabled: item.disabled,
157 discount: item.discount,
158 pricebasetype: item.pricebasetype,
159 price_ht: item.price_ht,
160 price_ttc: item.price_ttc,
161 price_unit_ht: item.price_unit_ht,
162 price_unit_ht_locale: item.price_unit_ht_locale,
163 description : item.description,
164 ref_customer: item.ref_customer,
165 tva_tx: item.tva_tx }
168 console.error("Error: Ajax url '.$url.($urloption ?
'?'.$urloption :
'').
' has returned an empty page. Should be an empty json array.");
173 minLength: '.((
int) $minLength).
',
174 select: function( event, ui ) { // Function ran once new value has been selected into javascript combo
175 console.log("We will trigger change on input '.$htmlname.
' because of the select definition of autocomplete code for input#search_'.$htmlname.
'");
176 console.log("Selected id = "+ui.item.id+" - If this value is null, it means you select a record with key that is null so selection is not effective");
178 console.log("Propagate before some properties retrieved by ajax into data-xxx properties");
180 // For supplier price and customer when price by quantity is off
181 $("#'.$htmlnamejquery.
'").attr("data-up", ui.item.price_ht);
182 $("#'.$htmlnamejquery.
'").attr("data-up-locale", ui.item.price_unit_ht_locale);
183 $("#'.$htmlnamejquery.
'").attr("data-base", ui.item.pricebasetype);
184 $("#'.$htmlnamejquery.
'").attr("data-qty", ui.item.qty);
185 $("#'.$htmlnamejquery.
'").attr("data-discount", ui.item.discount);
186 $("#'.$htmlnamejquery.
'").attr("data-description", ui.item.description);
187 $("#'.$htmlnamejquery.
'").attr("data-ref-customer", ui.item.ref_customer);
188 $("#'.$htmlnamejquery.
'").attr("data-tvatx", ui.item.tva_tx);
190 if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) {
192 // For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on
193 $("#'.$htmlnamejquery.
'").attr("data-pbq", ui.item.pbq);
194 $("#'.$htmlnamejquery.
'").attr("data-pbqup", ui.item.price_ht);
195 $("#'.$htmlnamejquery.
'").attr("data-pbqbase", ui.item.pricebasetype);
196 $("#'.$htmlnamejquery.
'").attr("data-pbqqty", ui.item.qty);
197 $("#'.$htmlnamejquery.
'").attr("data-pbqpercent", ui.item.discount);
201 // A new value has been selected, we trigger the handlers on #htmlnamejquery
202 console.log("Trigger changes on #'.$htmlnamejquery.
'");
203 $("#'.$htmlnamejquery.
'").val(ui.item.id).trigger("change"); // Select new value
205 // Disable an element
206 if (options.option_disabled) {
207 console.log("Make action option_disabled on #"+options.option_disabled+" with disabled="+ui.item.disabled)
208 if (ui.item.disabled) {
209 $("#" + options.option_disabled).prop("disabled", true);
211 $.jnotify(options.error, "error", true); // Output with jnotify the error message
213 if (options.warning) {
214 $.jnotify(options.warning, "warning", false); // Output with jnotify the warning message
217 $("#" + options.option_disabled).removeAttr("disabled");
221 if (options.disabled) {
222 console.log("Make action disabled on each "+options.option_disabled)
223 $.each(options.disabled, function(key, value) {
224 $("#" + value).prop("disabled", true);
228 console.log("Make action show on each "+options.show)
229 $.each(options.show, function(key, value) {
230 $("#" + value).show().trigger("show");
235 if (ui.item.update) {
236 console.log("Make action update on each ui.item.update")
237 // loop on each "update" fields
238 $.each(ui.item.update, function(key, value) {
239 console.log("Set value "+value+" into #"+key);
240 $("#" + key).val(value).trigger("change");
243 if (ui.item.textarea) {
244 console.log("Make action textarea on each ui.item.textarea")
245 $.each(ui.item.textarea, function(key, value) {
246 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
247 CKEDITOR.instances[key].setData(value);
248 CKEDITOR.instances[key].focus();
250 $("#" + key).html(value);
251 $("#" + key).focus();
255 console.log("ajax_autocompleter new value selected, we trigger change also on original component so on field #search_'.$htmlname.
'");
257 $("#search_'.$htmlnamejquery.
'").trigger("change"); // We have changed value of the combo select, we must be sure to trigger all js hook binded on this event. This is required to trigger other javascript change method binded on original field by other code.
260 }).data("'.$dataforrenderITem.
'")._renderItem = function( ul, item ) {
262 .data( "'.$dataforitem.
'", item ) // jQuery UI > 1.10.0
263 .append( \'<a><span class="tag">\' + item.label + "</span></a>" )
268 $script .=
'</script>';
289 $script =
'<!-- Autocomplete -->'.
"\n";
290 $script .=
'<script>';
291 $script .=
'jQuery(document).ready(function() {
292 var fields = '.json_encode($fields).
';
293 var nboffields = fields.length;
294 var autoselect = '.$autoselect.
';
295 //alert(fields + " " + nboffields);
297 jQuery("input#'.$htmlname.
'").autocomplete({
299 minLength: '.$minLength.
',
300 source: function( request, response ) {
301 jQuery.getJSON( "'.$url.($option ?
'?'.$option :
'').
'", { '.$htmlname.
': request.term }, function(data){
302 response( jQuery.map( data, function( item ) {
303 if (autoselect == 1 && data.length == 1) {
304 jQuery("#'.$htmlname.
'").val(item.value);
305 // TODO move this to specific request
307 jQuery("#state_id").html(item.states);
309 for (i=0;i<nboffields;i++) {
310 if (item[fields[i]]) { // If defined
311 //alert(item[fields[i]]);
312 jQuery("#" + fields[i]).val(item[fields[i]]);
320 select: function( event, ui ) {
322 for (i=0;i<nboffields;i++) {
323 //alert(fields[i] + " = " + ui.item[fields[i]]);
324 if (fields[i]=="selectcountry_id")
326 if (ui.item[fields[i]] > 0) // Do not erase country if unknown
328 oldvalue=jQuery("#" + fields[i]).val();
329 newvalue=ui.item[fields[i]];
330 //alert(oldvalue+" "+newvalue);
331 jQuery("#" + fields[i]).val(ui.item[fields[i]]);
332 if (oldvalue != newvalue) // To force select2 to refresh visible content
334 needtotrigger="#" + fields[i];
337 // If we set new country and new state, we need to set a new list of state to allow change
338 if (ui.item.states && ui.item["state_id"] != jQuery("#state_id").value) {
339 jQuery("#state_id").html(ui.item.states);
343 else if (fields[i]=="state_id" || fields[i]=="state_id")
345 if (ui.item[fields[i]] > 0) // Do not erase state if unknown
347 oldvalue=jQuery("#" + fields[i]).val();
348 newvalue=ui.item[fields[i]];
349 //alert(oldvalue+" "+newvalue);
350 jQuery("#" + fields[i]).val(ui.item[fields[i]]); // This may fails if not correct country
351 if (oldvalue != newvalue) // To force select2 to refresh visible content
353 needtotrigger="#" + fields[i];
357 else if (ui.item[fields[i]]) { // If defined
358 oldvalue=jQuery("#" + fields[i]).val();
359 newvalue=ui.item[fields[i]];
360 //alert(oldvalue+" "+newvalue);
361 jQuery("#" + fields[i]).val(ui.item[fields[i]]);
362 if (oldvalue != newvalue) // To force select2 to refresh visible content
364 needtotrigger="#" + fields[i];
368 if (needtotrigger != "") // To force select2 to refresh visible content
370 // We introduce a delay so hand is back to js and all other js change can be done before the trigger that may execute a submit is done
371 // This is required for example when changing zip with autocomplete that change the country
372 jQuery(needtotrigger).delay(500).queue(function() {
373 jQuery(this).trigger("change");
380 $script .=
'</script>';
399 $msg =
'<div id="dialog-info" title="'.dol_escape_htmltag($newtitle).
'">';
401 $msg .=
'</div>'.
"\n";
404 jQuery("#dialog-info").dialog({
411 jQuery(this).dialog(\'close\');
438 function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete =
'resolve', $idforemptyvalue =
'-1')
443 if (!empty($conf->browser->layout) && $conf->browser->layout ==
'phone' && !empty($conf->global->MAIN_DISALLOW_SELECT2_WITH_SMARTPHONE)) {
447 if (!empty($conf->global->MAIN_DISABLE_AJAX_COMBOX)) {
450 if (empty($conf->use_javascript_ajax)) {
453 if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && !defined(
'REQUIRE_JQUERY_MULTISELECT')) {
456 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
460 if (empty($minLengthToAutocomplete)) {
461 $minLengthToAutocomplete = 0;
464 $tmpplugin =
'select2';
465 $msg =
"\n".
'<!-- JS CODE TO ENABLE '.$tmpplugin.
' for id = '.$htmlname.
' -->
467 $(document).ready(function () {
468 $(\''.(preg_match(
'/^\./', $htmlname) ? $htmlname :
'#'.$htmlname).
'\').
'.$tmpplugin.'({
470 width: \''.$widthTypeOfAutocomplete.
'\',
471 minimumInputLength:
'.$minLengthToAutocomplete.',
472 language: select2arrayoflanguage,
473 containerCssClass: \
':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
474 selectionCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
475 templateResult: function (data, container) { /* Format visible output into combo list */
476 /* Code to add class of origin OPTION propagated to the new select2 <li> tag */
477 if (data.element) { $(container).addClass($(data.element).attr("class")); }
478 //console.log($(data.element).attr("data-html"));
479 if (data.id == '.((int) $idforemptyvalue).
' && $(data.element).attr("data-html") == undefined) {
482 if ($(data.element).attr("data-html") != undefined) return htmlEntityDecodeJs($(data.element).attr("data-html")); // If property html set, we decode html entities and use this
485 templateSelection: function (selection) { /* Format visible output of selected value */
486 if (selection.id == '.((int) $idforemptyvalue).
') return \'<span class="placeholder">\'+selection.text+\'</span>\';
487 return selection.text;
489 escapeMarkup: function(markup) {
492 dropdownCssClass: \'ui-dialog\'
495 $msg .=
'.select2(\'focus\')';
499 if (is_array($events) && count($events)) {
501 jQuery("#'.$htmlname.
'").change(function () {
502 var obj = '.json_encode($events).
';
503 $.each(obj, function(key,values) {
504 if (values.method.length) {
505 runJsCodeForEvent'.$htmlname.
'(values);
510 function runJsCodeForEvent'.$htmlname.
'(obj) {
511 var id = $("#'.$htmlname.
'").val();
512 var method = obj.method;
514 var htmlname = obj.htmlname;
515 var showempty = obj.showempty;
516 console.log("Run runJsCodeForEvent-'.$htmlname.
' from ajax_combobox id="+id+" method="+method+" showempty="+showempty+" url="+url+" htmlname="+htmlname);
525 $.each(obj.params, function(key,action) {
527 var num = response.num;
529 $("#" + key).removeAttr(action);
531 $("#" + key).attr(action, action);
535 $("select#" + htmlname).html(response.value);
537 var selecthtml_str = response.value;
538 var selecthtml_dom=$.parseHTML(selecthtml_str);
539 if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
540 $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
543 $("#inputautocomplete"+htmlname).val("");
545 $("select#" + htmlname).change(); /* Trigger event change */
552 $msg .=
"</script>\n";
573 function ajax_constantonoff($code, $input = array(), $entity =
null, $revertonoff = 0, $strict = 0, $forcereload = 0, $marginleftonlyshort = 2, $forcenoajax = 0, $setzeroinsteadofdel = 0, $suffix =
'', $mode =
'')
575 global $conf, $langs, $user;
577 $entity = ((isset($entity) && is_numeric($entity) && $entity >= 0) ? $entity : $conf->entity);
578 if (!isset($input)) {
582 if (empty($conf->use_javascript_ajax) || $forcenoajax) {
583 if (empty($conf->global->$code)) {
584 print
'<a href="'.$_SERVER[
'PHP_SELF'].
'?action=set_'.$code.
'&token='.
newToken().
'&entity='.$entity.($mode ?
'&mode='.$mode :
'').($forcereload ?
'&dol_resetcache=1' :
'').
'">'.
img_picto($langs->trans(
"Disabled"),
'off').
'</a>';
586 print
'<a href="'.$_SERVER[
'PHP_SELF'].
'?action=del_'.$code.
'&token='.
newToken().
'&entity='.$entity.($mode ?
'&mode='.$mode :
'').($forcereload ?
'&dol_resetcache=1' :
'').
'">'.
img_picto($langs->trans(
"Enabled"),
'on').
'</a>';
589 $out =
"\n<!-- Ajax code to switch constant ".$code.
" -->".
'
591 $(document).ready(function() {
592 var input = '.json_encode($input).
';
593 var url = \''.DOL_URL_ROOT.
'/core/ajax/constantonoff.php\';
595 var entity = \
''.dol_escape_js($entity).
'\';
596 var strict = \
''.dol_escape_js($strict).
'\';
597 var userid = \
''.dol_escape_js($user->id).
'\';
598 var yesButton = \
''.dol_escape_js($langs->transnoentities(
"Yes")).
'\';
599 var noButton = \
''.dol_escape_js($langs->transnoentities(
"No")).
'\';
600 var token = \
''.currentToken().
'\';
603 $(
"#set_" +
code).click(
function() {
604 if (input.alert && input.alert.set) {
605 if (input.alert.set.yesButton) yesButton = input.alert.set.yesButton;
606 if (input.alert.set.noButton) noButton = input.alert.set.noButton;
607 confirmConstantAction(
"set", url,
code, input, input.alert.set, entity, yesButton, noButton, strict, userid, token);
609 setConstant(url,
code, input, entity, 0,
'.((int) $forcereload).', userid, token);
614 $(
"#del_" +
code).click(
function() {
615 if (input.alert && input.alert.del) {
616 if (input.alert.del.yesButton) yesButton = input.alert.del.yesButton;
617 if (input.alert.del.noButton) noButton = input.alert.del.noButton;
618 confirmConstantAction(
"del", url,
code, input, input.alert.del, entity, yesButton, noButton, strict, userid, token);
620 if (empty($setzeroinsteadofdel)) {
621 $out .=' delConstant(url,
code, input, entity, 0,
'.((int) $forcereload).', userid, token);
';
623 $out .=' setConstant(url,
code, input, entity, 0,
'.((int) $forcereload).', userid, token, 0);
';
630 $out .= '<div
id=
"confirm_'.$code.'" title=
"" style=
"display: none;"></div>
';
631 $out .= '<span
id=
"set_'.$code.'" class=
"valignmiddle linkobject '.(!empty($conf->global->$code) ? 'hideobject' : '').'">
'.($revertonoff ?img_picto($langs->trans("Enabled"), 'switch_on
', '', false, 0, 0, '', '', $marginleftonlyshort) : img_picto($langs->trans("Disabled"), 'switch_off
', '', false, 0, 0, '', '', $marginleftonlyshort)).'</span>
';
632 $out .= '<span
id=
"del_'.$code.'" class=
"valignmiddle linkobject '.(!empty($conf->global->$code) ? '' : 'hideobject').'">
'.($revertonoff ?img_picto($langs->trans("Disabled"), 'switch_off
'.$suffix, '', false, 0, 0, '', '', $marginleftonlyshort) : img_picto($langs->trans("Enabled"), 'switch_on
'.$suffix, '', false, 0, 0, '', '', $marginleftonlyshort)).'</span>
';
652 function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = array(), $morecss = '')
658 var input =
'.json_encode($input).';
661 $(
"#set_'.$code.'_'.$object->id.'").click(
function() {
662 $.get(
"'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
664 field: \''.$field.
'\',
666 element: \''.$object->element.
'\',
667 id: \
''.$object->id.
'\',
668 token: \
''.newToken().
'\'
671 $(
"#set_'.$code.'_'.$object->id.'").hide();
672 $(
"#del_'.$code.'_'.$object->id.'").show();
674 if (input.disabled && input.disabled.length > 0) {
675 $.each(input.disabled,
function(key,value) {
676 $(
"#" + value).removeAttr(
"disabled");
677 if ($(
"#" + value).hasClass(
"butActionRefused") ==
true) {
678 $(
"#" + value).removeClass(
"butActionRefused");
679 $(
"#" + value).addClass(
"butAction");
683 }
else if (input.showhide && input.showhide.length > 0) {
684 $.each(input.showhide,
function(key,value) {
685 $(
"#" + value).show();
692 $(
"#del_'.$code.'_'.$object->id.'").click(
function() {
693 $.get(
"'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
695 field: \''.$field.
'\',
697 element: \''.$object->element.
'\',
698 id: \
''.$object->id.
'\',
699 token: \
''.newToken().
'\'
702 $(
"#del_'.$code.'_'.$object->id.'").hide();
703 $(
"#set_'.$code.'_'.$object->id.'").show();
705 if (input.disabled && input.disabled.length > 0) {
706 $.each(input.disabled,
function(key,value) {
707 $(
"#" + value).prop(
"disabled",
true);
708 if ($(
"#" + value).hasClass(
"butAction") ==
true) {
709 $(
"#" + value).removeClass(
"butAction");
710 $(
"#" + value).addClass(
"butActionRefused");
714 }
else if (input.showhide && input.showhide.length > 0) {
715 $.each(input.showhide,
function(key,value) {
716 $(
"#" + value).hide();
723 $out .= '<span
id=
"set_'.$code.'_'.$object->id.'" class=
"linkobject '.($object->$code == 1 ? 'hideobject' : '').($morecss ? ' '.$morecss : '').'">
'.img_picto($langs->trans($text_off), 'switch_off
').'</span>
';
724 $out .= '<span
id=
"del_'.$code.'_'.$object->id.'" class=
"linkobject '.($object->$code == 1 ? '' : 'hideobject').($morecss ? ' '.$morecss : '').'">
'.img_picto($langs->trans($text_on), 'switch_on
').'</span>
';