47function ajax_autocompleter($selected, $htmlname, $url, $urloption =
'', $minLength = 2, $autoselect = 0, $ajaxoptions = array(), $moreparams =
'')
49 if (empty($minLength)) {
53 $dataforrenderITem =
'ui-autocomplete';
54 $dataforitem =
'ui-autocomplete-item';
56 if (defined(
'JS_QUERY_AUTOCOMPLETE_RENDERITEM')) {
57 $dataforrenderITem = constant(
'JS_QUERY_AUTOCOMPLETE_RENDERITEM');
59 if (defined(
'JS_QUERY_AUTOCOMPLETE_ITEM')) {
60 $dataforitem = constant(
'JS_QUERY_AUTOCOMPLETE_ITEM');
63 $htmlnamejquery = str_replace(
'.',
'\\\\.', $htmlname);
67 $script =
'<input type="hidden" name="'.$htmlname.
'" id="'.$htmlname.
'" value="'.$selected.
'" '.($moreparams ? $moreparams :
'').
' />';
69 $script .=
'<!-- Javascript code for autocomplete of field '.$htmlname.
' -->'.
"\n";
70 $script .=
'<script>'.
"\n";
71 $script .=
'$(document).ready(function() {
72 var autoselect = '.((int) $autoselect).
';
73 var options = '.json_encode($ajaxoptions).
'; /* Option of actions to do after keyup, or after select */
75 /* 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 */
76 $("input#search_'.$htmlnamejquery.
'").keydown(function(e) {
77 if (e.keyCode != 9) /* If not "Tab" key */
79 if (e.keyCode == 13) { return false; } /* disable "ENTER" key useful for barcode readers */
80 console.log("Clear id previously selected for field '.$htmlname.
'");
81 $("#'.$htmlnamejquery.
'").val("");
85 // Check options for secondary actions when keyup
86 $("input#search_'.$htmlnamejquery.
'").keyup(function() {
87 if ($(this).val().length == 0)
89 $("#search_'.$htmlnamejquery.
'").val("");
90 $("#'.$htmlnamejquery.
'").val("").trigger("change");
91 if (options.option_disabled) {
92 $("#" + options.option_disabled).removeAttr("disabled");
94 if (options.disabled) {
95 $.each(options.disabled, function(key, value) {
96 $("#" + value).removeAttr("disabled");
100 $.each(options.update, function(key, value) {
101 $("#" + key).val("").trigger("change");
105 $.each(options.show, function(key, value) {
106 $("#" + value).hide().trigger("hide");
109 if (options.update_textarea) {
110 $.each(options.update_textarea, function(key, value) {
111 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
112 CKEDITOR.instances[key].setData("");
114 $("#" + key).html("");
121 $("input#search_'.$htmlnamejquery.
'").autocomplete({
122 source: function( request, response ) {
123 $.get("'.$url.($urloption ?
'?'.$urloption :
'').
'", { "'.str_replace(
'.',
'_', $htmlname).
'": request.term }, function(data){
126 response($.map( data, function(item) {
127 if (autoselect == 1 && data.length == 1) {
128 $("#search_'.$htmlnamejquery.
'").val(item.value);
129 $("#'.$htmlnamejquery.
'").val(item.key).trigger("change");
132 if (item.label != null) {
133 label = item.label.toString();
136 if (options.update) {
137 $.each(options.update, function(key, value) {
138 update[key] = item[value];
142 if (options.update_textarea) {
143 $.each(options.update_textarea, function(key, value) {
144 textarea[key] = item[value];
148 console.log("Return value from GET to the rest of code");
149 return { label: label,
152 disabled: item.disabled,
158 discount: item.discount,
159 pricebasetype: item.pricebasetype,
160 price_ht: item.price_ht,
161 price_ttc: item.price_ttc,
162 price_unit_ht: item.price_unit_ht,
163 price_unit_ht_locale: item.price_unit_ht_locale,
165 if (isModEnabled(
'multicurrency')) {
167 multicurrency_code: item.multicurrency_code,
168 multicurrency_unitprice: item.multicurrency_unitprice,
172 description : item.description,
173 ref_customer: item.ref_customer,
175 default_vat_code: item.default_vat_code
179 console.error("Error: Ajax url '.$url.($urloption ?
'?'.$urloption :
'').
' has returned an empty page. Should be an empty json array.");
184 minLength: '.((
int) $minLength).
',
185 select: function( event, ui ) { // Function ran once new value has been selected into javascript combo
186 console.log("We will trigger change on input '.$htmlname.
' because of the select definition of autocomplete code for input#search_'.$htmlname.
'");
187 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");
189 console.log("Propagate before some properties retrieved by ajax into data-xxx properties of #'.$htmlnamejquery.
' component");
190 //console.log(ui.item);
192 // For supplier price and customer when price by quantity is off
193 $("#'.$htmlnamejquery.
'").attr("data-up", ui.item.price_ht);
194 $("#'.$htmlnamejquery.
'").attr("data-up-locale", ui.item.price_unit_ht_locale);
195 $("#'.$htmlnamejquery.
'").attr("data-base", ui.item.pricebasetype);
196 $("#'.$htmlnamejquery.
'").attr("data-qty", ui.item.qty);
197 $("#'.$htmlnamejquery.
'").attr("data-discount", ui.item.discount);
198 $("#'.$htmlnamejquery.
'").attr("data-description", ui.item.description);
199 $("#'.$htmlnamejquery.
'").attr("data-ref-customer", ui.item.ref_customer);
200 $("#'.$htmlnamejquery.
'").attr("data-tvatx", ui.item.tva_tx);
201 $("#'.$htmlnamejquery.
'").attr("data-default-vat-code", ui.item.default_vat_code);
205 // For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on
206 console.log("PRODUIT_CUSTOMER_PRICES_BY_QTY is on, propagate also prices by quantity into data-pbqxxx properties");
207 $("#'.$htmlnamejquery.
'").attr("data-pbq", ui.item.pbq);
208 $("#'.$htmlnamejquery.
'").attr("data-pbqup", ui.item.price_ht);
209 $("#'.$htmlnamejquery.
'").attr("data-pbqbase", ui.item.pricebasetype);
210 $("#'.$htmlnamejquery.
'").attr("data-pbqqty", ui.item.qty);
211 $("#'.$htmlnamejquery.
'").attr("data-pbqpercent", ui.item.discount);
215 // A new value has been selected, we trigger the handlers on #htmlnamejquery
216 console.log("Trigger changes on #'.$htmlnamejquery.
'");
217 $("#'.$htmlnamejquery.
'").val(ui.item.id).trigger("change"); // Select new value
219 // Complementary actions
221 // Disable an element
222 if (options.option_disabled) {
223 console.log("Make action option_disabled on #"+options.option_disabled+" with disabled="+ui.item.disabled)
224 if (ui.item.disabled) {
225 $("#" + options.option_disabled).prop("disabled", true);
227 $.jnotify(options.error, "error", true); // Output with jnotify the error message
229 if (options.warning) {
230 $.jnotify(options.warning, "warning", false); // Output with jnotify the warning message
233 $("#" + options.option_disabled).removeAttr("disabled");
237 if (options.disabled) {
238 console.log("Make action disabled on each "+options.option_disabled)
239 $.each(options.disabled, function(key, value) {
240 $("#" + value).prop("disabled", true);
244 console.log("Make action show on each "+options.show)
245 $.each(options.show, function(key, value) {
246 $("#" + value).show().trigger("show");
251 if (ui.item.update) {
252 console.log("Make action update on each ui.item.update (if there is)")
253 // loop on each "update" fields
254 $.each(ui.item.update, function(key, value) {
255 console.log("Set value "+value+" into #"+key);
256 $("#" + key).val(value).trigger("change");
259 if (ui.item.textarea) {
260 console.log("Make action textarea on each ui.item.textarea (if there is)")
261 $.each(ui.item.textarea, function(key, value) {
262 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
263 CKEDITOR.instances[key].setData(value);
264 CKEDITOR.instances[key].focus();
266 $("#" + key).html(value);
267 $("#" + key).focus();
271 console.log("ajax_autocompleter new value selected, we trigger change also on original component so on field #search_'.$htmlname.
'");
273 $("#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.
276 }).data("'.$dataforrenderITem.
'")._renderItem = function( ul, item ) {
278 .data( "'.$dataforitem.
'", item ) // jQuery UI > 1.10.0
279 .append( \'<a><span class="tag">\' + item.label + "</span></a>" )
284 $script .=
'</script>';
455function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete =
'resolve', $idforemptyvalue =
'-1', $morecss =
'')
460 if (!empty($conf->browser->layout) && $conf->browser->layout ==
'phone' &&
getDolGlobalString(
'MAIN_DISALLOW_SELECT2_WITH_SMARTPHONE')) {
467 if (empty($conf->use_javascript_ajax)) {
470 if (!
getDolGlobalString(
'MAIN_USE_JQUERY_MULTISELECT') && !defined(
'REQUIRE_JQUERY_MULTISELECT')) {
477 if (empty($minLengthToAutocomplete)) {
478 $minLengthToAutocomplete = 0;
481 $moreselect2theme = ($morecss ?
dol_escape_js(
' '.$morecss) :
'');
482 $moreselect2theme = preg_replace(
'/widthcentpercentminus[^\s]*/',
'', $moreselect2theme);
484 $tmpplugin =
'select2';
485 $msg =
"\n".
'<!-- JS CODE TO ENABLE '.$tmpplugin.
' for id = '.$htmlname.
' -->
487 $(document).ready(function () {
488 $(\''.(preg_match(
'/^\./', $htmlname) ? $htmlname :
'#'.$htmlname).
'\').
'.$tmpplugin.'({
490 if (preg_match(
'/onrightofpage/', $morecss)) {
491 $msg .=
' dropdownAutoWidth: true, dropdownParent: $(\'#'.$htmlname.
'\').parent(),
'."\n";
493 $msg .= ' width: \
''.dol_escape_js($widthTypeOfAutocomplete).
'\',
494 minimumInputLength:
'.((int) $minLengthToAutocomplete).',
495 language: select2arrayoflanguage,
496 matcher:
function (params, data) {
497 if ($.trim(params.term) ===
"") {
500 keywords = (params.term).split(
" ");
501 for (var i = 0; i < keywords.length; i++) {
502 if (((data.text).toUpperCase()).indexOf((keywords[i]).toUpperCase()) == -1) {
508 theme: \
'default'.$moreselect2theme.
'\',
509 containerCssClass: \
':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
510 selectionCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
511 dropdownCssClass: \'ui-dialog\',
512 templateResult: function (data, container) { /* Format visible output into combo list */
513 /* Code to add class of origin OPTION propagated to the new select2 <li> tag */
514 if (data.element) { $(container).addClass($(data.element).attr("class")); }
515 //console.log("data html is "+$(data.element).attr("data-html"));
516 if (data.id == '.((int) $idforemptyvalue).
' && $(data.element).attr("data-html") == undefined) {
519 if ($(data.element).attr("data-html") != undefined) {
520 /* If property html set, we decode html entities and use this. */
521 /* Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, \'\', 0, 1) when building the select option. */
522 return htmlEntityDecodeJs($(data.element).attr("data-html"));
526 templateSelection: function (selection) { /* Format visible output of selected value */
527 if (selection.id == '.((int) $idforemptyvalue).
') return \'<span class="placeholder">\'+selection.text+\'</span>\';
528 return selection.text;
530 escapeMarkup: function(markup) {
535 $msg .=
'.select2(\'focus\')';
540 $msg .=
"</script>\n";
636function ajax_constantonoff($code, $input = array(), $entity =
null, $revertonoff = 0, $strict = 0, $forcereload = 0, $marginleftonlyshort = 2, $forcenoajax = 0, $setzeroinsteadofdel = 0, $suffix =
'', $mode =
'', $morecss =
'inline-block')
638 global $conf, $langs, $user;
640 $entity = ((isset($entity) && is_numeric($entity) && $entity >= 0) ? $entity : $conf->entity);
641 if (!isset($input)) {
645 if (empty($conf->use_javascript_ajax) || $forcenoajax) {
646 if (empty($conf->global->$code)) {
647 $out =
'<a '.($morecss ?
'class="'.$morecss.
'" ' :
'').
'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>';
649 $out =
'<a '.($morecss ?
'class="'.$morecss.
'" ' :
'').
' 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>';
652 $out =
"\n<!-- Ajax code to switch constant ".$code.
" -->".
'
654 $(document).ready(function() {
655 var input = '.json_encode($input).
';
656 var url = \''.DOL_URL_ROOT.
'/core/ajax/constantonoff.php\';
658 var entity = \
''.dol_escape_js($entity).
'\';
659 var strict = \
''.dol_escape_js($strict).
'\';
660 var userid = \
''.dol_escape_js($user->id).
'\';
661 var yesButton = \
''.dol_escape_js($langs->transnoentities(
"Yes")).
'\';
662 var noButton = \
''.dol_escape_js($langs->transnoentities(
"No")).
'\';
663 var token = \
''.currentToken().
'\';
666 $(
"#set_" + code).click(
function() {
667 if (input.alert && input.alert.set) {
668 if (input.alert.set.yesButton) yesButton = input.alert.set.yesButton;
669 if (input.alert.set.noButton) noButton = input.alert.set.noButton;
670 confirmConstantAction(
"set", url, code, input, input.alert.set, entity, yesButton, noButton, strict, userid, token);
672 setConstant(url, code, input, entity, 0,
'.((int) $forcereload).', userid, token);
677 $(
"#del_" + code).click(
function() {
678 if (input.alert && input.alert.del) {
679 if (input.alert.del.yesButton) yesButton = input.alert.del.yesButton;
680 if (input.alert.del.noButton) noButton = input.alert.del.noButton;
681 confirmConstantAction(
"del", url, code, input, input.alert.del, entity, yesButton, noButton, strict, userid, token);
683 if (empty($setzeroinsteadofdel)) {
684 $out .=' delConstant(url, code, input, entity, 0,
'.((int) $forcereload).', userid, token);
';
686 $out .=' setConstant(url, code, input, entity, 0,
'.((int) $forcereload).', userid, token, 0);
';
693 $out .= '<div
id=
"confirm_'.$code.'" title=
"" style=
"display: none;"></div>
';
694 $out .= '<span
id=
"set_'.$code.'" class=
"valignmiddle inline-block 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>
';
695 $out .= '<span
id=
"del_'.$code.'" class=
"valignmiddle inline-block 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>
';
717function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = array(), $morecss = '
', $htmlname = '', $forcenojs = 0)
719 global $conf, $langs;
721 if (empty($htmlname)) {
724 //var_dump($object->module); var_dump($object->element);
728 if (!empty($conf->use_javascript_ajax)) {
731 var input =
'.json_encode($input).';
734 $(
"#set_'.$htmlname.'_'.$object->id.'").click(
function() {
735 console.log(
"Click managed by ajax_object_onoff");
736 $.get(
"'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
738 field: \''.dol_escape_js($field).
'\',
740 element: \''.dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.
'@'.$object->module).
'\',
741 id: \
''.((int) $object->id).
'\',
742 token: \
''.currentToken().
'\'
745 $(
"#set_'.$htmlname.'_'.$object->id.'").hide();
746 $(
"#del_'.$htmlname.'_'.$object->id.'").show();
748 if (input.disabled && input.disabled.length > 0) {
749 $.each(input.disabled,
function(key,value) {
750 $(
"#" + value).removeAttr(
"disabled");
751 if ($(
"#" + value).hasClass(
"butActionRefused") == true) {
752 $(
"#" + value).removeClass(
"butActionRefused");
753 $(
"#" + value).addClass(
"butAction");
757 }
else if (input.showhide && input.showhide.length > 0) {
758 $.each(input.showhide,
function(key,value) {
759 $(
"#" + value).show();
766 $(
"#del_'.$htmlname.'_'.$object->id.'").click(
function() {
767 console.log(
"Click managed by ajax_object_onoff");
768 $.get(
"'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
770 field: \''.dol_escape_js($field).
'\',
772 element: \''.
dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.
'@'.$object->module).
'\',
773 id: \''.((int) $object->id).
'\',
777 $("#del_'.$htmlname.
'_'.$object->id.
'").hide();
778 $("#set_'.$htmlname.
'_'.$object->id.
'").show();
779 // Disable another element
780 if (input.disabled && input.disabled.length > 0) {
781 $.each(input.disabled, function(key,value) {
782 $("#" + value).prop("disabled", true);
783 if ($("#" + value).hasClass("butAction") == true) {
784 $("#" + value).removeClass("butAction");
785 $("#" + value).addClass("butActionRefused");
788 // Hide another element
789 } else if (input.showhide && input.showhide.length > 0) {
790 $.each(input.showhide, function(key,value) {
791 $("#" + value).hide();
800 $switchon =
'switch_on';
801 $switchoff =
'switch_off';
804 $tmparray = explode(
':', $text_on);
805 if (!empty($tmparray[1])) {
806 $text_on = $tmparray[0];
807 $switchon = $tmparray[1];
808 if (!empty($tmparray[2])) {
809 $cssswitchon = $tmparray[2];
812 $tmparray = explode(
':', $text_off);
813 if (!empty($tmparray[1])) {
814 $text_off = $tmparray[0];
815 $switchoff = $tmparray[1];
816 if (!empty($tmparray[2])) {
817 $cssswitchoff = $tmparray[2];
821 if (empty($conf->use_javascript_ajax) || $forcenojs) {
822 $out .=
'<a id="set_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'hideobject' :
'').($morecss ?
' '.$morecss :
'').
'" href="'.DOL_URL_ROOT.
'/core/ajax/objectonoff.php?action=set&token='.newToken().
'&id='.((int) $object->id).
'&element='.urlencode($object->element).
'&field='.urlencode($field).
'&value=1&backtopage='.urlencode($_SERVER[
"PHP_SELF"].
'?id='.$object->id).
'">'.
img_picto($langs->trans($text_off), $switchoff,
'', false, 0, 0,
'', $cssswitchoff).
'</a>';
823 $out .=
'<a id="del_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'' :
'hideobject').($morecss ?
' '.$morecss :
'').
'" href="'.DOL_URL_ROOT.
'/core/ajax/objectonoff.php?action=set&token='.newToken().
'&id='.((int) $object->id).
'&element='.urlencode($object->element).
'&field='.urlencode($field).
'&value=0&backtopage='.urlencode($_SERVER[
"PHP_SELF"].
'?id='.$object->id).
'">'.
img_picto($langs->trans($text_on), $switchon,
'', false, 0, 0,
'', $cssswitchon).
'</a>';
825 $out .=
'<span id="set_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'hideobject' :
'').($morecss ?
' '.$morecss :
'').
'">'.
img_picto($langs->trans($text_off), $switchoff,
'', false, 0, 0,
'', $cssswitchoff).
'</span>';
826 $out .=
'<span id="del_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'' :
'hideobject').($morecss ?
' '.$morecss :
'').
'">'.
img_picto($langs->trans($text_on), $switchon,
'', false, 0, 0,
'', $cssswitchon).
'</span>';
ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array(), $moreparams='')
Generic function that return javascript to add to a page to transform a common input field into an au...
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
ajax_multiautocompleter($htmlname, $fields, $url, $option='', $minLength=2, $autoselect=0)
Generic function that return javascript to add to a page to transform a common input field into an au...
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)