説明なし

um-conditional.js 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. var arr_all_conditions = []; //raw
  2. var um_field_conditions = {}; // filtered
  3. var um_field_default_values = {};
  4. /**
  5. * Get field default value
  6. *
  7. * @param {object} $dom
  8. * @return {object}
  9. */
  10. function um_get_field_default_value( $dom ) {
  11. var default_value = '';
  12. var type = um_get_field_type( $dom );
  13. switch ( type ) {
  14. case 'text':
  15. case 'number':
  16. case 'date':
  17. case 'textarea':
  18. case 'select':
  19. default_value = $dom.find('input:text,input[type="number"],textarea,select').val();
  20. break;
  21. case 'multiselect':
  22. default_value = $dom.find('select').val();
  23. break;
  24. case 'radio':
  25. if ( $dom.find('input[type="radio"]:checked').length >= 1 ) {
  26. default_value = $dom.find('input[type="radio"]:checked').val();
  27. }
  28. break;
  29. case 'checkbox':
  30. if ( $dom.find('input[type="checkbox"]:checked').length >= 1 ) {
  31. if ( $dom.find('input[type="checkbox"]:checked').length > 1 ) {
  32. var arr_values = [];
  33. arr_values.push( default_value );
  34. $dom.find('input[type="checkbox"]:checked').each( function() {
  35. arr_values.push( jQuery(this).val() );
  36. });
  37. default_value = arr_values;
  38. } else {
  39. default_value = $dom.find('input[type="checkbox"]:checked').val();
  40. }
  41. }
  42. break;
  43. default:
  44. default_value = wp.hooks.applyFilters( 'um_conditional_logic_default_value', default_value, type, $dom );
  45. break;
  46. }
  47. return {type: type, value: default_value};
  48. }
  49. /**
  50. * Get field element by field wrapper
  51. *
  52. * @param {object} $dom
  53. * @return {object}
  54. */
  55. function um_get_field_element( $dom ) {
  56. var field_element = $dom.find( 'input,textarea,select' );
  57. var type = um_get_field_type( $dom );
  58. field_element = wp.hooks.applyFilters( 'um_conditional_logic_field_element', field_element, type, $dom );
  59. return field_element;
  60. }
  61. /**
  62. * Get field type
  63. *
  64. * @param {object} $dom
  65. * @return {string}
  66. */
  67. function um_get_field_type( $dom ) {
  68. var type = '';
  69. var classes = $dom.attr( 'class' ).split(' ');
  70. jQuery.each( classes, function ( i, d ) {
  71. if ( /um-field-type_/.test( d ) ) {
  72. type = d.replace( 'um-field-type_', '' ).trim();
  73. }
  74. });
  75. return type;
  76. }
  77. /**
  78. * Get field siblings/chidren conditions
  79. *
  80. * @param {string} field_key
  81. * @return {array}
  82. */
  83. function um_get_field_children( field_key ) {
  84. var arr_conditions = [];
  85. jQuery.each( arr_all_conditions, function ( ii, condition ) {
  86. if ( condition.field.parent === field_key ) {
  87. arr_conditions.push( condition.field.condition );
  88. }
  89. });
  90. return arr_conditions;
  91. }
  92. /**
  93. * Split single array to multi-dimensional array
  94. *
  95. * @param {array} arr
  96. * @param {integer} n
  97. * @return {array}
  98. */
  99. function um_splitup_array( arr, n ) {
  100. var rest = arr.length % n,
  101. restUsed = rest,
  102. partLength = Math.floor(arr.length / n),
  103. result = [];
  104. for (var i = 0; i < arr.length; i += partLength) {
  105. var end = partLength + i,
  106. add = false;
  107. if (rest !== 0 && restUsed) {
  108. end++;
  109. restUsed--;
  110. add = true;
  111. }
  112. result.push(arr.slice(i, end));
  113. if (add) {
  114. i++;
  115. }
  116. }
  117. var obj_result = [];
  118. jQuery.each(result, function (ii, dd) {
  119. obj_result.push({
  120. action: dd[0],
  121. if_field: dd[1],
  122. operator: dd[2],
  123. value: dd[3]
  124. });
  125. });
  126. return obj_result;
  127. }
  128. /**
  129. * Get field live value
  130. *
  131. * @param {object} $dom
  132. * @return {mixed}
  133. */
  134. function um_get_field_data( $dom ) {
  135. um_live_field = $dom.parents('.um-field').data('key');
  136. um_live_value = $dom.val();
  137. if ($dom.is(':checkbox')) {
  138. um_live_value = '';
  139. if ($dom.parents('.um-field').find('input:checked').length > 1) {
  140. $dom.parents('.um-field').find('input:checked').each(function () {
  141. um_live_value = um_live_value + jQuery(this).val() + ' ';
  142. });
  143. } else {
  144. if ($dom.parents('.um-field').find('input:checked').length >= 1) {
  145. um_live_value = $dom.parents('.um-field').find('input:checked').val();
  146. }
  147. }
  148. }
  149. if ($dom.is(':radio')) {
  150. um_live_value = $dom.parents('.um-field').find('input[type=radio]:checked').val();
  151. }
  152. return um_live_value;
  153. }
  154. /**
  155. * Checks if a value exists in an array
  156. *
  157. * @param {String} needle
  158. * @param {Array} haystack
  159. * @param {Boolean} strict
  160. * @returns {Boolean}
  161. */
  162. function um_in_array( needle, haystack, strict ) {
  163. var found = false, key;
  164. strict = !!strict;
  165. for ( key in haystack ) {
  166. if ( ( strict && haystack[ key ] === needle ) || ( ! strict && haystack[ key ] == needle ) ) {
  167. found = true;
  168. break;
  169. }
  170. }
  171. return found;
  172. }
  173. /**
  174. * Apply field conditions
  175. *
  176. * @param {object} $dom
  177. * @param {boolean} is_single_update
  178. */
  179. function um_apply_conditions( $dom, is_single_update ) {
  180. if ( ! $dom.parents('.um-field[data-key]').length ) {
  181. return;
  182. }
  183. var key = $dom.parents('.um-field[data-key]').data('key');
  184. var conditions = um_field_conditions[ key ];
  185. if ( typeof conditions === 'undefined' ) {
  186. return;
  187. }
  188. var field_type = um_get_field_type( $dom.parents('.um-field[data-key]') );
  189. var live_field_value = um_get_field_data( $dom );
  190. if (live_field_value === 'empty_file') {
  191. live_field_value = '';
  192. }
  193. var $owners = {};
  194. var $owners_values = {};
  195. var $owner_conditions = {};
  196. jQuery.each( conditions, function ( index, condition ) {
  197. if ( typeof $owners_values[ condition.owner ] == 'undefined' ) {
  198. $owners_values[ condition.owner ] = [];
  199. $owner_conditions[ condition.owner ] = {}
  200. }
  201. $owners_values[ condition.owner ].push( condition.value );
  202. $owner_conditions[ condition.owner ] = condition;
  203. });
  204. jQuery.each( conditions, function ( index, condition ) {
  205. if ( typeof $owners[ condition.owner ] == 'undefined' ) {
  206. $owners[ condition.owner ] = {};
  207. }
  208. if ( condition.operator === 'empty' ) {
  209. var field_value = Array.isArray( live_field_value ) ? live_field_value.join('') : live_field_value;
  210. if ( ! field_value || field_value === '' ) {
  211. $owners[ condition.owner ][ index ] = true;
  212. } else {
  213. $owners[ condition.owner ][ index ] = false;
  214. }
  215. }
  216. if ( condition.operator === 'not empty' ) {
  217. var field_value = Array.isArray( live_field_value ) ? live_field_value.join('') : live_field_value;
  218. if ( field_value && field_value !== '' ) {
  219. $owners[ condition.owner ][ index ] = true;
  220. } else {
  221. $owners[ condition.owner ][ index ] = false;
  222. }
  223. }
  224. if ( condition.operator === 'equals to' ) {
  225. var field_value = ( Array.isArray( live_field_value ) && live_field_value.length === 1 ) ? live_field_value[0] : live_field_value;
  226. if ( condition.value === field_value && um_in_array( field_value, $owners_values[ condition.owner ] ) ) {
  227. $owners[ condition.owner ][ index ] = true;
  228. } else {
  229. $owners[ condition.owner ][ index ] = false;
  230. }
  231. }
  232. if ( condition.operator === 'not equals' ) {
  233. var field_value = ( Array.isArray( live_field_value ) && live_field_value.length === 1 ) ? live_field_value[0] : live_field_value;
  234. if ( jQuery.isNumeric(condition.value) && parseInt(field_value) !== parseInt( condition.value ) && field_value && ! um_in_array( field_value, $owners_values[ condition.owner ] ) ) {
  235. $owners[ condition.owner ][ index ] = true;
  236. } else if ( condition.value != field_value && ! um_in_array( field_value, $owners_values[ condition.owner ] ) ) {
  237. $owners[ condition.owner ][ index ] = true;
  238. } else {
  239. $owners[ condition.owner ][ index ] = false;
  240. }
  241. }
  242. if ( condition.operator === 'greater than' ) {
  243. var field_value = ( Array.isArray( live_field_value ) && live_field_value.length === 1 ) ? live_field_value[0] : live_field_value;
  244. if ( jQuery.isNumeric( condition.value ) && parseInt( field_value ) > parseInt( condition.value ) ) {
  245. $owners[ condition.owner ][ index ] = true;
  246. } else {
  247. $owners[ condition.owner ][ index ] = false;
  248. }
  249. }
  250. if ( condition.operator === 'less than' ) {
  251. var field_value = ( Array.isArray( live_field_value ) && live_field_value.length === 1 ) ? live_field_value[0] : live_field_value;
  252. if ( jQuery.isNumeric( condition.value ) && parseInt( field_value ) < parseInt( condition.value ) ) {
  253. $owners[ condition.owner ][ index ] = true;
  254. } else {
  255. $owners[ condition.owner ][ index ] = false;
  256. }
  257. }
  258. if ( condition.operator === 'contains' ) {
  259. switch ( field_type ) {
  260. case 'multiselect':
  261. if ( live_field_value && live_field_value.indexOf( condition.value ) >= 0 && um_in_array( condition.value, live_field_value ) ) {
  262. $owners[ condition.owner ][ index ] = true;
  263. } else {
  264. $owners[ condition.owner ][ index ] = false;
  265. }
  266. break;
  267. case 'checkbox':
  268. if ( live_field_value && live_field_value.indexOf( condition.value ) >= 0 ) {
  269. $owners[ condition.owner ][ index ] = true;
  270. } else {
  271. $owners[ condition.owner ][ index ] = false;
  272. }
  273. break;
  274. default:
  275. $owners = wp.hooks.applyFilters( 'um_conditional_logic_contains_operator_owners', $owners, field_type, live_field_value, condition, index );
  276. if ( typeof $owners[ condition.owner ][ index ] === 'undefined' ) {
  277. if ( live_field_value && live_field_value.indexOf( condition.value ) >= 0 && um_in_array( live_field_value, $owners_values[ condition.owner ] ) ) {
  278. $owners[ condition.owner ][ index ] = true;
  279. } else {
  280. $owners[ condition.owner ][ index ] = false;
  281. }
  282. }
  283. break;
  284. }
  285. }
  286. }); // end foreach `conditions`
  287. jQuery.each( $owners, function ( index, field ) {
  288. if ( um_in_array( true, field ) ) {
  289. um_field_apply_action( $dom, $owner_conditions[ index ], true );
  290. } else {
  291. um_field_apply_action( $dom, $owner_conditions[ index ], false );
  292. }
  293. });
  294. $dom.trigger( 'um_fields_change' );
  295. }
  296. /**
  297. * Apply condition's action
  298. *
  299. * @param {object} $dom
  300. * @param {string} condition
  301. * @param {boolean} is_true
  302. * @returns {jQuery}
  303. */
  304. function um_field_apply_action($dom, condition, is_true) {
  305. var child_dom = jQuery('div.um-field[data-key="' + condition.owner + '"]');
  306. if ( condition.action === 'show' && is_true /*&& child_dom.is(':hidden')*/ ) {
  307. if( child_dom.is(':hidden') ){
  308. um_field_restore_default_value(child_dom);
  309. }
  310. child_dom.show();
  311. _show_in_ie( child_dom );
  312. }
  313. if ( condition.action === 'show' && ! is_true /*&& child_dom.is(':visible')*/ ) {
  314. child_dom.hide();
  315. _hide_in_ie( child_dom );
  316. }
  317. if ( condition.action === 'hide' && is_true /*&& child_dom.is(':visible')*/ ) {
  318. child_dom.hide();
  319. _hide_in_ie( child_dom );
  320. }
  321. if ( condition.action === 'hide' && ! is_true /*&& child_dom.is(':hidden')*/ ) {
  322. if( child_dom.is(':hidden') ){
  323. um_field_restore_default_value(child_dom);
  324. }
  325. child_dom.show();
  326. _show_in_ie( child_dom );
  327. }
  328. return $dom.removeClass( 'um-field-has-changed' );
  329. }
  330. /**
  331. * Restores default field value
  332. *
  333. * @param {object} $dom
  334. */
  335. function um_field_restore_default_value( $dom ) {
  336. var type = um_get_field_type( $dom );
  337. var key = $dom.data('key');
  338. var field = um_field_default_values[ key ];
  339. switch ( type ) {
  340. case 'text':
  341. case 'number':
  342. case 'date':
  343. case 'textarea':
  344. $dom.find('input:text,input[type="number"],textareas').val(field.value);
  345. break;
  346. case 'select':
  347. $dom.find('select').find('option').prop('selected', false);
  348. $dom.find('select').val(field.value);
  349. $dom.find('select').trigger('change');
  350. break;
  351. case 'multiselect':
  352. $dom.find('select').find('option').prop('selected', false);
  353. jQuery.each(field.value, function (i, value) {
  354. $dom.find('select').find('option[value="' + value + '"]').attr('selected', true);
  355. });
  356. $dom.find('select').trigger('change');
  357. break;
  358. case 'checkbox':
  359. if ( $dom.find('input[type="checkbox"]:checked').length >= 1 ) {
  360. $dom.find('input[type="checkbox"]:checked').prop('checked', false);
  361. $dom.find('span.um-field-checkbox-state i').removeClass('um-icon-android-checkbox-outline');
  362. $dom.find('span.um-field-checkbox-state i').addClass('um-icon-android-checkbox-outline-blank');
  363. $dom.find('.um-field-checkbox.active').removeClass('active');
  364. if ( Array.isArray( field.value ) ) {
  365. jQuery.each( field.value, function ( i, value ) {
  366. var cbox_elem = $dom.find('input[type="checkbox"][value="' + value + '"]');
  367. cbox_elem.attr('checked', true);
  368. cbox_elem.closest('.um-field-checkbox').find('i').removeClass('um-icon-android-checkbox-outline-blank');
  369. cbox_elem.closest('.um-field-checkbox').find('i').addClass('um-icon-android-checkbox-outline');
  370. cbox_elem.closest('.um-field-checkbox').addClass('active');
  371. });
  372. } else {
  373. var cbox_elem = $dom.find('input[type="checkbox"][value="' + field.value + '"]');
  374. cbox_elem.attr('checked', true);
  375. cbox_elem.closest('.um-field-checkbox').find('i').removeClass('um-icon-android-checkbox-outline-blank');
  376. cbox_elem.closest('.um-field-checkbox').find('i').addClass('um-icon-android-checkbox-outline');
  377. cbox_elem.closest('.um-field-checkbox').addClass('active');
  378. }
  379. }
  380. break;
  381. case 'radio':
  382. if ( $dom.find('input[type="radio"]:checked').length >= 1 ) {
  383. setTimeout( function() {
  384. $dom.find('input[type="radio"]:checked').prop('checked', false);
  385. $dom.find('span.um-field-radio-state i').removeClass('um-icon-android-radio-button-on');
  386. $dom.find('span.um-field-radio-state i').addClass('um-icon-android-radio-button-off');
  387. $dom.find('.um-field-radio.active').removeClass('active');
  388. var radio_elem = $dom.find('input[type="radio"][value="' + field.value + '"]');
  389. radio_elem.attr('checked', true);
  390. radio_elem.closest('.um-field-radio').find('i').removeClass('um-icon-android-radio-button-off');
  391. radio_elem.closest('.um-field-radio').find('i').addClass('um-icon-android-radio-button-on');
  392. radio_elem.closest('.um-field-radio').addClass('active');
  393. }, 100 );
  394. }
  395. break;
  396. default:
  397. wp.hooks.doAction( 'um_conditional_logic_restore_default_value', type, $dom, field );
  398. break;
  399. } // end switch type
  400. if ( ! $dom.hasClass( 'um-field-has-changed' ) ) {
  401. var me = um_get_field_element( $dom );
  402. if ( type === 'radio' || type === 'checkbox' ) {
  403. me = me.find( ':checked' );
  404. }
  405. if ( me ) {
  406. me.trigger( 'change' );
  407. $dom.addClass( 'um-field-has-changed' );
  408. }
  409. /*
  410. maybe future fix
  411. if ( me ) {
  412. if ( type == 'radio' || type == 'checkbox' ) {
  413. me.each( function() {
  414. if ( jQuery(this).is(':checked') ) {
  415. jQuery(this).trigger('change');
  416. }
  417. });
  418. } else {
  419. me.trigger( 'change' );
  420. }
  421. $dom.addClass( 'um-field-has-changed' );
  422. }*/
  423. }
  424. }
  425. /**
  426. * Hides sibling/child field when parent field is hidden
  427. */
  428. function um_field_hide_siblings() {
  429. jQuery.each(um_field_conditions, function (index, conditions) {
  430. if (jQuery('.um-field[data-key="' + index + '"]:hidden').length >= 1 || jQuery('.um-field[data-key="' + index + '"]').css('display') === 'none') {
  431. jQuery.each(conditions, function (key, condition) {
  432. jQuery('.um-field[data-key="' + condition.owner + '"]').hide();
  433. });
  434. }
  435. });
  436. }
  437. /**
  438. * Hides div for IE browser
  439. *
  440. * @param {object} $dom
  441. */
  442. function _hide_in_ie( $dom ){
  443. if ( typeof( jQuery.browser ) !== 'undefined' && jQuery.browser.msie ) {
  444. $dom.css({"visibility":"hidden"});
  445. }
  446. }
  447. /**
  448. * Shows div for IE browser
  449. *
  450. * @param {object} $dom
  451. */
  452. function _show_in_ie( $dom ){
  453. if ( typeof( jQuery.browser ) !== 'undefined' && jQuery.browser.msie ) {
  454. $dom.css({"visibility":"visible"});
  455. }
  456. }
  457. /**
  458. * UM Conditional fields Init
  459. */
  460. function um_init_field_conditions() {
  461. var arr_field_keys = [];
  462. jQuery( '.um-field[data-key]' ).each( function() {
  463. var key = jQuery(this).data( 'key' );
  464. arr_field_keys.push( key );
  465. var parse_attrs = {};
  466. jQuery.each( jQuery(this)[0].attributes, function ( index, attribute ) {
  467. if ( attribute.name.indexOf( 'data-cond' ) !== -1 ) {
  468. // replace "data-cond-"
  469. var cond_field_id_and_attr = attribute.name.slice( 10 );
  470. // return "n"
  471. var cond_field_id = cond_field_id_and_attr.substring( 1, 0 );
  472. //replace "n-"
  473. var cond_field_attr = cond_field_id_and_attr.slice( 2 );
  474. if ( typeof parse_attrs[cond_field_id] === 'undefined' )
  475. parse_attrs[cond_field_id] = {};
  476. parse_attrs[cond_field_id][cond_field_attr] = attribute.value;
  477. }
  478. });
  479. jQuery.each( parse_attrs, function ( ii, dd ) {
  480. var obj = {'field' :{
  481. owner: key,
  482. action: dd.action,
  483. parent: dd.field,
  484. operator: dd.operator,
  485. value: dd.value,
  486. condition: {
  487. owner: key,
  488. action: dd.action,
  489. operator: dd.operator,
  490. value: dd.value
  491. }
  492. }};
  493. arr_all_conditions.push(obj);
  494. });
  495. um_field_default_values[ jQuery(this).data('key') ] = um_get_field_default_value( jQuery(this) );
  496. });
  497. jQuery.each( arr_field_keys, function ( i, field_key ) {
  498. um_field_conditions[field_key] = um_get_field_children( field_key );
  499. });
  500. jQuery( '.um-field[data-key]:visible' ).each( function() {
  501. var $wrap_dom = jQuery(this);
  502. var me = um_get_field_element( $wrap_dom );
  503. if ( typeof me.trigger !== 'undefined' ) {
  504. me.trigger( 'change' );
  505. }
  506. });
  507. }
  508. jQuery(document).ready( function (){
  509. jQuery(document).on('change', '.um-field select, .um-field input[type="radio"], .um-field input[type="checkbox"]', function () {
  510. var me = jQuery(this);
  511. um_apply_conditions(me, false);
  512. });
  513. jQuery(document).on('input change', '.um-field input[type="text"]', function () {
  514. var me = jQuery(this);
  515. um_apply_conditions(me, false);
  516. });
  517. jQuery(document).on('input change', '.um-field input[type="number"]', function () {
  518. var me = jQuery(this);
  519. um_apply_conditions(me, false);
  520. });
  521. jQuery(document).on('input change', '.um-field input[type="password"]', function () {
  522. var me = jQuery(this);
  523. um_apply_conditions(me, false);
  524. });
  525. jQuery(document).on('change', '.um-field-image input[type="hidden"],.um-field-file input[type="hidden"]', function () {
  526. var me = jQuery(this);
  527. um_apply_conditions(me, false);
  528. });
  529. jQuery(document).on('click', '.um-finish-upload', function () {
  530. var key = jQuery(this).attr('data-key');
  531. var me = jQuery('.um-field-'+key+' input');
  532. setTimeout(function () {
  533. um_apply_conditions(me, false);
  534. }, 100);
  535. });
  536. jQuery(document).on('click', '.um-field .cancel', function () {
  537. var key = jQuery(this).parent().attr('data-key');
  538. var me = jQuery('.um-field-'+key+' input');
  539. setTimeout(function () {
  540. um_apply_conditions(me, false);
  541. }, 1000);
  542. });
  543. jQuery(document).on('um_fields_change', function () {
  544. um_field_hide_siblings();
  545. um_field_hide_siblings(); // dupes, issue with false field wrapper's visiblity validations. requires optimization.
  546. });
  547. um_init_field_conditions();
  548. });