/* jshint expr: true */
/* jshint sub:true */
/* jshint loopfunc:true */

/**
 * Core Admin JS Files
 * Not recommened to edit this file directly if you plan to upgrade the script when new versions are released.
 * Use hooks to inject custom javascript code
 */

$(window).on("load", function () {
  init_btn_with_tooltips();
});

// Set datatables error throw console log
$.fn.dataTable.ext.errMode = "throw";
$.fn.dataTableExt.oStdClasses.sWrapper =
  "dataTables_wrapper form-inline dt-bootstrap table-loading";

if (app.options.enable_google_picker == "1") {
  $.fn.googleDrivePicker.defaults.clientId = app.options.google_client_id;
  $.fn.googleDrivePicker.defaults.developerKey = app.options.google_api;
}

// Set dropzone not auto discover
Dropzone.options.newsFeedDropzone = false;
Dropzone.options.salesUpload = false;

// Check for desktop notifications permissions
if ("Notification" in window && app.options.desktop_notifications == "1") {
  Notification.requestPermission();
}

// Predefined global variables
var original_top_search_val,
  table_leads,
  table_activity_log,
  table_estimates,
  table_invoices,
  table_tasks,
  tab_active = get_url_param("tab"),
  tab_group = get_url_param("group"),
  side_bar = $("#side-menu"),
  content_wrapper = $("#wrapper"),
  setup_menu = $("#setup-menu-wrapper"),
  menu_href_selector,
  calendar_selector = $("#calendar"),
  notifications_wrapper = $("#header").find("li.notifications-wrapper"),
  doc_initial_title = document.title,
  newsfeed_posts_page = 0,
  track_load_post_likes = 0,
  track_load_comment_likes = 0,
  post_likes_total_pages = 0,
  comment_likes_total_pages = 0,
  select_picker_validated_event = false,
  postid = 0,
  lastAddedItemKey = null,
  setup_menu_item = $("#setup-menu-item");

// Custom deselect all on bootstrap ajax select input
$("body").on("loaded.bs.select change", "select.ajax-search", function (e) {
  var val = $(this).selectpicker("val");

  if (Array.isArray(val) && val.length == 0) {
    return;
  }

  if (!val || $(this).is(":disabled")) {
    return;
  }

  var $elmWrapper = $(this).parents(".bootstrap-select.ajax-search");
  if ($elmWrapper.find(".ajax-clear-values").length === 0) {
    var id = $(this).attr("id");
    var dropdownToggle = $elmWrapper
      .addClass("ajax-remove-values-option")
      .find("button.dropdown-toggle");
    dropdownToggle.after(
      '<span class="pointer ajax-clear-values" onclick="deselect_ajax_search(this); return false;" data-id="' +
        id +
        '"></span>'
    );
  }
});

// On render select remove the placeholder
$("body").on("rendered.bs.select", "select", function () {
  $(this).parents().removeClass("select-placeholder");
  $(this)
    .parents(".form-group")
    .find(".select-placeholder")
    .removeClass("select-placeholder");
});

$("body").on("loaded.bs.select", "select", function () {
  if ($(this).data("toggle") == 1) {
    $(this).selectpicker("toggle");
  }
});

// Init bootstrap selectpicker
$("body").on("loaded.bs.select", "._select_input_group", function (e) {
  $(this)
    .parents(".form-group")
    .find(".input-group-select .input-group-addon")
    .css("opacity", "1");
});

$(window).on("load resize", function (e) {
  if (!$("body").hasClass("page-small")) {
    // Add special class to minimalize page elements when screen is less than 768px
    set_body_small();
  }
  // Wait until metsiMenu, collapse and other effect finish and set wrapper height
  setTimeout(
    function () {
      mainWrapperHeightFix();
    },
    e.type == "load" ? 150 : 0
  );
});

$(document).on("mousemove", function (e) {
  if (!is_mobile() && $("body").hasClass("hide-sidebar")) {
    if (
      (isRTL == "true" && $(window).width() - e.pageX <= 10) ||
      (isRTL == "false" && e.pageX <= 10)
    ) {
      $(".hide-menu").click();
    }
  }
});

$(function () {
  // Add notifications indicator on document title
  if (totalUnreadNotifications > 0) {
    document.title = "(" + totalUnreadNotifications + ") " + doc_initial_title;
  }

  $(".screen-options-btn").on("click", function () {
    $(".screen-options-area").slideToggle();
  });

  // Make the deprecated errors more clear
  if ($("body").hasClass("has-deprecated-errors")) {
    (function () {
      var $errors = $("div:contains('A PHP Error was encountered')");
      var totalErrorsHeight = 0;
      $.each($errors, function () {
        totalErrorsHeight += $(this).outerHeight();
        $(this).css("background", "#fff");
      });
      if (totalErrorsHeight > 0) {
        $("#menu, #setup-menu-wrapper").css(
          "top",
          totalErrorsHeight + 70 + "px"
        );
      }
    })();
  }

  // Form entities where HTML is available, causing issue on mod_security servers, will entitiy encode then before saving in database entiity decode
  $("form")
    .has('[data-entities-encode="true"]')
    .on("submit.app.entity", function (e) {
      if ($(this).validate().checkForm()) {
        $.each($('[data-entities-encode="true"]'), function () {
          if (!$(this).hasClass("_entities-processed")) {
            $(this).val(htmlEntities($(this).val()));
            $(this).addClass("_entities-processed");
          }
        });
      }
    });

  /** Create New Customer **/
  add_hotkey("Shift+C", function () {
    var $leadModal = $("#lead-modal");
    var $taskModal = $("#task-modal");
    if ($leadModal.is(":visible")) {
      convert_lead_to_customer($leadModal.find('input[name="leadid"]').val());
    } else if ($taskModal.is(":visible")) {
      var $taskCommentsWrapper = $taskModal.find(".tasks-comments");
      if (!$taskCommentsWrapper.is(":visible")) {
        $taskCommentsWrapper.css("display", "block");
      }
      init_new_task_comment();
    } else {
      window.location.href = admin_url + "clients/client";
    }
  });

  /** Create New Invoice **/
  add_hotkey("Shift+I", function () {
    window.location.href = admin_url + "invoices/invoice";
  });

  /** Create New Estimate **/
  add_hotkey("Shift+E", function () {
    var $leadModal = $("#lead-modal");
    var $taskModal = $("#task-modal");
    if (!$leadModal.is(":visible") && !$taskModal.is(":visible")) {
      window.location.href = admin_url + "estimates/estimate";
    } else {
      if ($leadModal.is(":visible")) {
        $("a[lead-edit]").click();
      } else if ($taskModal.is(":visible")) {
        edit_task(
          $taskModal.find("[data-task-single-id]").attr("data-task-single-id")
        );
      }
    }
  });

  /** Marks task as finished when modal is opened **/
  add_hotkey("Shift+F", function () {
    var $taskModal = $("#task-modal");
    if ($taskModal.is(":visible")) {
      var $taskSingleBody = $taskModal.find("[data-task-single-id]");
      if ($taskSingleBody.attr("data-status") != 5) {
        mark_complete($taskSingleBody.attr("data-task-single-id"));
      }
    }
  });

  /** Create New Proposal **/
  add_hotkey("Ctrl+Shift+P", function () {
    window.location.href = admin_url + "proposals/proposal";
  });
  /** Create New Expense **/
  add_hotkey("Ctrl+Shift+E", function () {
    window.location.href = admin_url + "expenses/expense";
  });

  /** Create New Lead **/
  add_hotkey("Shift+L", function () {
    init_lead();
  });
  /** Create New Task **/
  add_hotkey("Shift+T", function () {
    var $newTaskRelationBtn = $(".new-task-relation");
    if ($newTaskRelationBtn.length > 0) {
      new_task(
        admin_url +
          "tasks/task?rel_id=" +
          $newTaskRelationBtn.attr("data-rel-id") +
          "&rel_type=" +
          $newTaskRelationBtn.attr("data-rel-type")
      );
    } else if ($("body").hasClass("project")) {
      new_task(
        admin_url + "tasks/task?rel_id=" + project_id + "&rel_type=project"
      );
    } else {
      new_task();
    }
  });
  /** Create New Project **/
  add_hotkey("Shift+P", function () {
    window.location.href = admin_url + "projects/project";
  });
  /** Create New Ticket **/
  add_hotkey("Shift+S", function () {
    window.location.href = admin_url + "tickets/add";
  });
  /** Create New Staff Member **/
  add_hotkey("Ctrl+Shift+S", function () {
    window.location.href = admin_url + "staff/member";
  });

  /** User logout **/
  add_hotkey("Ctrl+Shift+L", function () {
    logout();
  });

  /**
   * List shortcuts
   */

  /** Go to dashboard **/
  add_hotkey("Alt+D", function () {
    window.location.href = admin_url;
  });
  /** List Customers **/
  add_hotkey("Alt+C", function () {
    window.location.href = admin_url + "clients";
  });
  /** List Tasks **/
  add_hotkey("Alt+T", function () {
    window.location.href = admin_url + "tasks/list_tasks";
  });
  /** List Invoices **/
  add_hotkey("Alt+I", function () {
    window.location.href = admin_url + "invoices/list_invoices";
  });
  /** List Estimates **/
  add_hotkey("Alt+E", function () {
    window.location.href = admin_url + "estimates/list_estimates";
  });
  /** List Projects **/
  add_hotkey("Alt+P", function () {
    window.location.href = admin_url + "projects";
  });
  /** List Leads **/
  add_hotkey("Alt+L", function () {
    window.location.href = admin_url + "leads";
  });
  /** List Tickets **/
  add_hotkey("Ctrl+Alt+T", function () {
    window.location.href = admin_url + "tickets";
  });
  /** List Expenses **/
  add_hotkey("Ctrl+Alt+E", function () {
    window.location.href = admin_url + "expenses/list_expenses";
  });

  /** Sales Report **/
  add_hotkey("Alt+R", function () {
    window.location.href = admin_url + "reports/sales";
  });

  /** Settings **/
  add_hotkey("Alt+S", function () {
    window.location.href = admin_url + "settings";
  });

  /** Top Search Focus **/
  add_hotkey("Shift+K", function () {
    $("#search_input").focus();
  });

  /* Focus on seacrh on first datatable found in the DOM */
  add_hotkey("Shift+D", function () {
    $("body .dataTables_wrapper")
      .eq(0)
      .find(".dataTables_filter input")
      .focus();
  });

  add_hotkey("Shift+F", function () {
    $(".hide-menu").click();
  });

  // Init the shortcuts
  $.Shortcuts.start();

  /** TinyMCE modal fix */
  $(document).on("focusin", function (e) {
    if ($(e.target).closest(".tox-tinymce, .tox-tinymce-aux, .moxman-window, .tam-assetmanager-root").length) {
      e.stopImmediatePropagation();
    }
  });

  // Custom option to show setup menu item only on hover, not applied on mobile
  if (app.options.show_setup_menu_item_only_on_hover == 1 && !is_mobile()) {
    side_bar.hover(
      function () {
        setTimeout(function () {
          setup_menu_item.css("display", "block");
        }, 200);
      },
      function () {
        setTimeout(function () {
          setup_menu_item.css("display", "none");
        }, 1000);
      }
    );
  }

  // Store navTabs, used multiple times.
  var $navTabs = $("body").find("ul.nav-tabs");
  // Check for active tab if any found in url so we can set this tab to active - Tab active is defined on top
  if (tab_active) {
    $navTabs.find('[href="#' + tab_active + '"]').click();
  }
  // Check for active tab groups (this is custom made) and not related to boostrap - tab_group is defined on top
  if (tab_group) {
    // Do not track bootstrap default tabs
    $navTabs.find("li").not('[role="presentation"]').removeClass("active");
    // Add the class active to this group manually so the tab can be highlighted
    $navTabs
      .find('[data-group="' + tab_group + '"]')
      .parents("li")
      .addClass("active");
  }
  // Set moment locale
  moment.locale(app.locale);
  // Set timezone locale
  moment().tz(app.options.timezone).format();

  // Init tinymce editors
  init_editor();
  // Dont close dropdown on timer top click
  $("body").on(
    "click",
    "#started-timers-top,.popover-top-timer-note",
    function (e) {
      e.stopPropagation();
    }
  );
  // Init inputs used for tags
  init_tags_inputs();
  // Init all color pickers
  init_color_pickers();
  // Init tables offline (no serverside)
  initDataTableInline();

  // Bootstrap switch active or inactive global function
  $("body").on("change", ".onoffswitch input", function (event, state) {
    var switch_url = $(this).data("switch-url");
    if (!switch_url) {
      return;
    }
    switch_field(this);
  });

  /* Custom fields hyperlink */
  custom_fields_hyperlink();
  // Init lightboxes if found
  init_lightbox();
  // Init progress bars
  init_progress_bars();
  // Init datepickers
  init_datepicker();

  // jQuery validation fix for select, works only on required
  // Wrap it in another validate event because is throwing errors if the form is not yet validated
  $(document).on("app.form-validate", function (e, form) {
    if (select_picker_validated_event === true) {
      return true;
    }

    select_picker_validated_event = true;

    $(form).on(
      "change",
      "select.ajax-search, select.selectpicker",
      function (e) {
        if ($(this).selectpicker("val") && !$(this).is(":disabled")) {
          if (
            typeof $(this).rules() != "undefined" &&
            Object.keys($(this).rules()).length === 1 &&
            $(this).rules().hasOwnProperty("required")
          ) {
            var parent = $(this).parents(".form-group");
            parent.find("#" + $(this).attr("name") + "-error").remove();
            parent.removeClass("has-error");
          }
        }
      }
    );
  });

  init_selectpicker();
  // Optimize body
  set_body_small();
  // Validate all form for reminders
  init_form_reminder();
  // On document read check and init for client ajax-search
  init_ajax_search("customer", "#clientid.ajax-search");

  // Check for active class in sidebar links
  var $linkSidebarActive = side_bar.find('li > a[href="' + location + '"]');
  if ($linkSidebarActive.length) {
    $linkSidebarActive.parents("li").not(".quick-links").addClass("active");
    // Set aria expanded to true
    $linkSidebarActive.prop("aria-expanded", true);
    $linkSidebarActive
      .parents("ul.nav-second-level")
      .prop("aria-expanded", true);
    $linkSidebarActive
      .parents("li")
      .find("a:first-child")
      .prop("aria-expanded", true);
  }

  // Check for setu menu active class
  if (setup_menu.hasClass("display-block")) {
    var $linkSetupSidebarActive = setup_menu.find(
      'li > a[href="' + location + '"]'
    );
    if ($linkSetupSidebarActive.length) {
      $linkSetupSidebarActive.parents("li").addClass("active");
      $linkSetupSidebarActive.prev("active");
      $linkSetupSidebarActive
        .parents("ul.nav-second-level")
        .prop("aria-expanded", true);
      $linkSetupSidebarActive
        .parents("li")
        .find("a:first-child")
        .prop("aria-expanded", true);
    }
  }

  // Init now metisMenu for the main admin sidebar
  side_bar.metisMenu();
  // Init setup menu
  setup_menu.metisMenu();

  // Handle minimalize sidebar menu
  $(".hide-menu").click(function (e) {
    e.preventDefault();
    if ($("body").hasClass("hide-sidebar")) {
      $("body").removeClass("hide-sidebar").addClass("show-sidebar");
    } else {
      $("body").removeClass("show-sidebar").addClass("hide-sidebar");
    }
    // $("body").toggleClass(
    //   $(window).width() < 769 ? "show-sidebar" : "hide-sidebar"
    // );
    if (setup_menu.hasClass("display-block")) {
      $(".close-customizer").click();
    }
  });

  // Hide sidebar on content click on mobile
  if (is_mobile()) {
    content_wrapper.on("click", function () {
      if ($("body").hasClass("show-sidebar")) {
        $(".hide-menu").click();
      }
      if (setup_menu.hasClass("display-block")) {
        $(".close-customizer").click();
      }
    });
  }

  if (app.browser == "safari") {
    $("body").on("input", ".bootstrap-select .bs-searchbox input", function () {
      $(this).trigger("keyup");
    });
  }

  // Optimize wrapper height
  mainWrapperHeightFix();

  // Init scrollable tabs
  init_tabs_scrollable();

  // Refresh top timers on click
  $("#top-timers").on("click", function () {
    init_timers();
  });

  set_search_history(app.user_recent_searches);

  $("#search-history").on("click", ".remove-history", function (e) {
    e.stopImmediatePropagation();
    e.preventDefault();
    var index = $(this).parents("li").index();
    requestGet("misc/remove_recent_search/" + index).done(function (history) {
      var $searchHistory = $("#search-history");
      $searchHistory.find("li:eq(" + index + ")").remove();
      if ($searchHistory.find("li").length == 0) {
        $searchHistory.removeClass("display-block");
      }
    });
  });

  $("#search_input").on("click focus", function () {
    if ($(this).val() == "") {
      var $searchHistory = $("#search-history");
      if ($searchHistory.find("li").length > 0) {
        $searchHistory.css("width", $(this).outerWidth() + "px");
        $searchHistory.addClass("display-block");
      } else {
        // $searchHistory.addClass('display-block');
      }
    }
  });

  $("#search-history").on("click", "a.history", function (e) {
    e.preventDefault();
    var recentSearch = $(this).text().trim();
    $("#search_input").val(recentSearch);
    $("#search_input").trigger("paste");
  });

  // Top search input fetch results
  $("#search_input").on(
    "keyup paste" + (app.browser == "safari" ? " input" : ""),
    function () {
      var $searchHistory = $("#search-history");
      $searchHistory.removeClass("display-block");

      var q = $(this).val().trim();
      var search_results = $("#search_results");
      var top_search_button = $("#top_search_button button");

      if (q === "") {
        content_wrapper.unhighlight();
        search_results.html("");
        original_top_search_val = "";
        top_search_button
          .html('<i class="fa fa-search"></i>')
          .removeClass("search_remove");
        $searchHistory.addClass("display-block");
        return;
      }

      if (
        q.length < 2 &&
        app.user_language.indexOf("chinese") === -1 &&
        app.user_language.indexOf("japanese") === -1
      ) {
        return;
      }

      top_search_button
        .html('<i class="fa fa-remove"></i>')
        .addClass("search_remove");

      delay(function () {
        if (q == original_top_search_val) {
          return;
        }
        $.post(admin_url + "misc/search", {
          q: q,
        }).done(function (data) {
          data = JSON.parse(data);
          content_wrapper.unhighlight();
          search_results.html(data.results);
          content_wrapper.highlight(q);
          original_top_search_val = q;
          set_search_history(data.history);
        });
      }, 700);
    }
  );

  var qAdminSearchURL = get_url_param("q");
  if (qAdminSearchURL) {
    $("#search_input").val(qAdminSearchURL).trigger("keyup");
  }

  // Format timesheet duration type and do necesary checkings
  $("body").on("blur", "#timesheet_duration", function () {
    var that = $(this);
    var pattern = /[^0-9:]/gi;
    var val = $(this).val();
    val = val.replace(pattern, "");
    if (val.indexOf(":") > -1) {
      var duration_array = val.split(":");

      if (duration_array[0].length === 0) {
        duration_array[0] = "00";
      }

      if (duration_array[1] >= 60) {
        var subtr = Math.floor(parseInt(duration_array[1] / 60));
        duration_array[0] = subtr + parseInt(duration_array[0]);
        duration_array[1] = duration_array[1] - subtr * 60;
      }

      if (duration_array[0].toString().length === 1) {
        duration_array[0] = "0" + duration_array[0];
      }

      if (duration_array[1].toString().length === 1) {
        duration_array[1] = "0" + duration_array[1];
      } else if (duration_array[1].toString().length === 0) {
        duration_array[1] = "00";
      }

      val = duration_array[0] + ":" + duration_array[1];
    } else if (val.length === 1 && val.indexOf(":") === -1) {
      val = "0" + val + ":" + "00";
    } else if (val.length >= 2 && val.indexOf(":") === -1) {
      val = val + ":" + "00";
    }
    val = val == "00:00" ? "" : val;
    that.val(val);
  });

  // Switching timesheet enter type
  $("body").on("click", ".timesheet-toggle-enter-type", function (e) {
    e.preventDefault();
    var $switch_to = $(this)
      .find("span.switch-to")
      .removeClass("switch-to")
      .addClass("hide");
    $(this)
      .find("span")
      .not($switch_to)
      .removeClass("hide")
      .addClass("switch-to");
    $(".timesheet-start-end-time, .timesheet-duration").toggleClass("hide");
    $(".timesheet-start-end-time input").val("");
    $(".timesheet-duration input").val("");
  });

  // On hidden modal reminder set all values to empty and set the form action to ADD in case edit was clicked
  $("body").on("hidden.bs.modal", ".modal-reminder", function (e) {
    var $this = $(this);
    var rel_id = $this.find('input[name="rel_id"]').val();
    var rel_type = $this.find('input[name="rel_type"]').val();
    $this
      .find("form")
      .attr(
        "action",
        admin_url + "misc/add_reminder/" + rel_id + "/" + rel_type
      );
    $this.find("form").removeAttr("data-edit");
    $this.find(":input:not([type=hidden]), textarea").val("");
    $this.find('input[type="checkbox"]').prop("checked", false);
    $this.find("select").selectpicker("val", "");
  });

  // Focus the date field on reminder modal shown
  $("body").on("shown.bs.modal", ".modal-reminder", function (e) {
    if ($(this).find('form[data-edit="true"]').length == 0) {
      $(this).find("#date").focus();
    }
  });

  // On delete reminder reload the tables
  $("body").on("click", ".delete-reminder", function () {
    if (confirm_delete()) {
      requestGetJSON($(this).attr("href")).done(function (response) {
        alert_float(response.alert_type, response.message);
        if ($("#task-modal").is(":visible")) {
          _task_append_html(response.taskHtml);
        }
        reload_reminders_tables();
      });
    }
    return false;
  });

  /* Insert new checklist items on enter press */
  $("body").on(
    "keypress",
    'textarea[name="checklist-description"]',
    function (event) {
      if (event.which == "13") {
        var that = $(this);
        update_task_checklist_item(that).done(function () {
          add_task_checklist_item(that.attr("data-taskid"));
        });
        return false;
      }
    }
  );

  /* Update tasks checklist items when focusing out */
  $("body").on(
    "blur paste",
    'textarea[name="checklist-description"]',
    function () {
      update_task_checklist_item($(this));
    }
  );

  $("body").on(
    "show.bs.select",
    "select.checklist-items-template-select",
    _make_task_checklist_items_deletable
  );
  $("body").on(
    "refreshed.bs.select",
    "select.checklist-items-template-select",
    _make_task_checklist_items_deletable
  );

  // trigger jquery validation validate
  $("body").on("changed.bs.select", "select", function (e) {
    $(e.currentTarget).trigger("keyup.validate");
  });

  // Can't update if no values selected, no $_POST data send
  $("body").on(
    "changed.bs.select",
    "select.custom-field-multi-select",
    function (e) {
      var val = $(this).val();
      $(this)
        .find('option[value=""]')
        .prop("selected", val.length === 0 ? true : false);
      $(this).selectpicker("refresh");
    }
  );

  // Task single modal inline changes, eq start date, due date...
  $("body").on("change", ".task-single-inline-field", function () {
    var singleDateInputs = $("body").find(".task-single-inline-field");
    var data = {};
    $.each(singleDateInputs, function () {
      var name = $(this).attr("name");
      var val = $(this).val();
      var $parentwrap = $(this).parents(".task-single-inline-wrap");
      if (name == "startdate" && val === "") {
        $parentwrap.addClass("text-danger");
      } else if (name == "startdate" && val !== "") {
        $parentwrap.removeClass("text-danger");
      }
      if ((name == "startdate" && val !== "") || name != "startdate") {
        data[$(this).attr("name")] = val;
        // Name is required
        if (name != "startdate" && val === "") {
          $parentwrap.css("opacity", 0.5);
        } else {
          $parentwrap.css("opacity", 1);
        }
      }
    });
    var $taskModal = $("#task-modal");
    var dTaskID = $taskModal
      .find("[data-task-single-id]")
      .attr("data-task-single-id");
    $.post(admin_url + "tasks/task_single_inline_update/" + dTaskID, data);
  });

  // When user select from checklist items template add this template
  $("body").on("change", "#task-modal #checklist_items_templates", function () {
    var val = $(this).val();
    var valTemplate = $(this)
      .find('option[value="' + val + '"]')
      .html()
      .trim();
    if (valTemplate !== "") {
      var $taskModal = $("#task-modal");
      add_task_checklist_item(
        $taskModal.find("[data-task-single-id]").attr("data-task-single-id"),
        valTemplate
      );
      $(this).selectpicker("val", "");
    }
  });

  // Used on task comment date href, can be used directly to add the link in browser for scroll.
  $("body").on("click", ".task-date-as-comment-id", function (e) {
    e.preventDefault();
    var task_comment_temp = $(this).attr("href").split("#");
    var comment_position = $(
      "#" + task_comment_temp[task_comment_temp.length - 1]
    ).position();
    $("#task-modal").scrollTop(comment_position.top);
  });

  // Search by tags from the tables for any tag clicked.
  $("body").on(
    "click",
    "table.dataTable tbody .tags-labels .label-tag",
    function () {
      $(this)
        .parents("table")
        .DataTable()
        .search($(this).find(".tag").text())
        .draw();
      $("div.dataTables_filter input").focus();
    }
  );

  // Search by customer groups from the tables for any group clicked.
  $("body").on(
    "click",
    "table.dataTable tbody .customer-group-list",
    function () {
      $(this).parents("table").DataTable().search($(this).text()).draw();
      $("div.dataTables_filter input").focus();
    }
  );

  // Permissions change, apply necessary action to disable OWN or VIEW OWN
  $("[data-can-view-own], [data-can-view]").on("change", function () {
    var is_own_attr = $(this).attr("data-can-view-own");
    view_chk_selector = $(this)
      .parents("tr")
      .find(
        "td input[" +
          (typeof is_own_attr !== typeof undefined && is_own_attr !== false
            ? "data-can-view"
            : "data-can-view-own") +
          "]"
      );

    if (view_chk_selector.data("not-applicable") == true) {
      return;
    }

    view_chk_selector.prop("checked", false);
    view_chk_selector.prop("disabled", $(this).prop("checked") === true);
  });

  // Init single task data
  if (typeof taskid !== "undefined" && taskid !== "") {
    init_task_modal(taskid);
  }

  // Task checklist mark as complete/incomplete
  $("body").on("change", 'input[name="checklist-box"]', function () {
    requestGet(
      admin_url +
        "tasks/checkbox_action/" +
        $(this).parents(".checklist").data("checklist-id") +
        "/" +
        ($(this).prop("checked") === true ? 1 : 0)
    );
    recalculate_checklist_items_progress();
    if (
      $(this).prop("checked") &&
      $('button[data-hide="1"]').hasClass("hide")
    ) {
      $(this).closest(".checklist ").addClass("hide");
    }
  });

  // Fix task checklist content textarea height
  $("body").on(
    "keyup paste click",
    "textarea[name='checklist-description']",
    function (e) {
      do_task_checklist_items_height($(this));
    }
  );

  // On click on task comment textarea make it tinymce, by default is plain textarea
  $("body").on("click focus", "#task_comment", function (e) {
    init_new_task_comment();
  });

  // Delete task timesheet from the task single modal
  $("body").on("click", ".task-single-delete-timesheet", function (e) {
    e.preventDefault();
    if (confirm_delete()) {
      var _delete_timesheet_task_id = $(this).data("task-id");
      requestGet($(this).attr("href")).done(function (response) {
        init_task_modal(_delete_timesheet_task_id);
        setTimeout(function () {
          reload_tasks_tables();
          init_timers();
        }, 20);
      });
    }
  });

  $("#task-modal").on(
    "change",
    'input[name="timesheet_start_time"], input[name="timesheet_end_time"], input[name="timesheet_duration"]',
    function () {
      if (
        $(this).val() &&
        $(this).parents(".form-group").hasClass("has-error")
      ) {
        $(this).parents(".form-group").removeClass("has-error");
      }
    }
  );

  // New timesheet add manually from task single modal
  $("body").on("click", ".task-single-add-timesheet", function (e) {
    e.preventDefault();

    var start_time_input = $("body").find(
      '#task-modal input[name="timesheet_start_time"]'
    );
    var end_time_input = $("body").find(
      '#task-modal input[name="timesheet_end_time"]'
    );
    var duration_input = $("body").find(
      '#task-modal input[name="timesheet_duration"]'
    );

    var start_time = start_time_input.val();
    var end_time = end_time_input.val();
    var duration = duration_input.val();

    start_time === "" &&
      start_time_input.parents(".form-group").addClass("has-error");
    end_time === "" &&
      end_time_input.parents(".form-group").addClass("has-error");
    duration === "" &&
      duration_input.parents(".form-group").addClass("has-error");

    if ((start_time !== "" && end_time !== "") || duration !== "") {
      var data = {};
      data.timesheet_duration = duration;
      data.start_time = start_time;
      data.end_time = end_time;
      data.timesheet_task_id = $(this).data("task-id");
      data.note = $("body").find("#task_single_timesheet_note").val();
      data.timesheet_staff_id = $("body")
        .find('#task-modal select[name="single_timesheet_staff_id"]')
        .val();
      $.post(admin_url + "tasks/log_time", data).done(function (response) {
        response = JSON.parse(response);
        if (response.success === true || response.success == "true") {
          init_task_modal(data.timesheet_task_id);
          alert_float("success", response.message);
          setTimeout(function () {
            reload_tasks_tables();
          }, 20);
        } else {
          alert_float("warning", response.message);
        }
      });
    }
  });

  // Copy task href/button event.
  $("body").on("click", ".copy_task_action", function () {
    var data = {};
    $(this).prop("disabled", true);
    data.copy_from = $(this).data("task-copy-from");
    data.copy_task_assignees = $("body")
      .find("#copy_task_assignees")
      .prop("checked");
    data.copy_task_followers = $("body")
      .find("#copy_task_followers")
      .prop("checked");
    data.copy_task_checklist_items = $("body")
      .find("#copy_task_checklist_items")
      .prop("checked");
    data.copy_task_attachments = $("body")
      .find("#copy_task_attachments")
      .prop("checked");
    data.copy_task_status = $("body")
      .find('input[name="copy_task_status"]:checked')
      .val();
    $.post(admin_url + "tasks/copy", data).done(function (response) {
      response = JSON.parse(response);
      if (response.success === true || response.success == "true") {
        var $taskModal = $("#_task_modal");
        if ($taskModal.is(":visible")) {
          $taskModal.modal("hide");
        }
        init_task_modal(response.new_task_id);
        reload_tasks_tables();
      }
      alert_float(response.alert_type, response.message);
    });
    return false;
  });

  // Creates new task in specific milestones, the milestone is auto selected on the new task modal
  $("body").on("click", ".new-task-to-milestone", function (e) {
    e.preventDefault();
    var milestone_id = $(this)
      .parents(".milestone-column")
      .data("col-status-id");
    new_task(
      admin_url +
        "tasks/task?rel_type=project&rel_id=" +
        project_id +
        "&milestone_id=" +
        milestone_id
    );
    $('body [data-toggle="popover"]').popover("hide");
  });

  // On shown task add/edit modal
  $("body").on("shown.bs.modal", "#_task_modal", function (e) {
    if (!$(e.currentTarget).hasClass("edit")) {
      $("body").find("#_task_modal #name").focus();
    } else {
      if ($(this).find(".tinymce-task").val().trim() !== "") {
        init_editor(".tinymce-task", {
          height: 200,
        });
      }
    }
    init_tags_inputs();
  });

  // Remove the tinymce description task editor
  $("body").on("hidden.bs.modal", "#_task_modal", function () {
    tinyMCE.remove(".tinymce-task");
    // Clear _ticket_message from single tickets in case user tried to convert ticket to task to prevent populating the fields again with the last ticket message click
    if (typeof _ticket_message != "undefined") {
      _ticket_message = undefined;
    }

    if (
      $(this).attr("data-lead-id") != undefined &&
      !$(this).attr("data-task-created")
    ) {
      init_lead($(this).attr("data-lead-id"));
    }

    destroy_dynamic_scripts_in_element($("body #_task_modal"));

    $("#_task").empty();
  });

  // Don't allow the task modal to close if lightbox is visible in for the task attachments
  // Used when user hit the ESC button
  // Empty task data
  $("body").on("hide.bs.modal", "#task-modal", function () {
    if ($("#lightbox").is(":visible") == true) {
      return false;
    }
    if (typeof taskAttachmentDropzone != "undefined") {
      taskAttachmentDropzone.destroy();
    }
    var viewDescriptionEditor = tinyMCE.get("#task_view_description");
    if (viewDescriptionEditor) {
      // Invoke the blur event before the modal is closed in case
      // there are unsaved changes.
      // see edit_task_inline_description function
      viewDescriptionEditor.blur();

      tinyMCE.remove("#task_view_description");
    }
  });

  // Prevent closing the modal if comment is being written
  $("body").on("hide.bs.modal", "#task-modal", function (e) {
    tinymce.get().forEach(function (editor) {
      if (
        editor.id.includes("task_comment") &&
        editor.getContent() !== "" &&
        $(editor.editorContainer).is(":visible")
      ) {
        e.preventDefault();
      }
    });
  });

  // Prevent closing the modal if timesheet is being recorded/edited
  $("body").on("hide.bs.modal", "#task-modal", function (e) {
    var taskModal = $("#task-modal");
    if (taskModal.find(".timesheet-edit").is(":visible")) {
      e.preventDefault();
    }

    if (taskModal.find(".add-timesheet").is(":visible")) {
      var timesheetStartTime = taskModal.find("#timesheet_start_time").val();
      var timesheetEndTime = taskModal.find("#timesheet_end_time").val();
      var timesheetDuration = taskModal.find("#timesheet_duration").val();
      var timesheetNote = taskModal.find("#task_single_timesheet_note").val();

      if (
        timesheetStartTime !== "" ||
        timesheetEndTime !== "" ||
        timesheetDuration !== "" ||
        timesheetNote !== ""
      ) {
        e.preventDefault();
      }
    }
  });

  // On task single modal hidden remove all html data
  $("body").on("hidden.bs.modal", "#task-modal", function () {
    // Clear memory leak
    destroy_dynamic_scripts_in_element($(this));

    $(this).find(".data").empty();
  });

  // On task single modal shown perform few actions
  $("body").on("shown.bs.modal", "#task-modal", function () {
    do_task_checklist_items_height();
    init_tags_inputs();
    fix_task_modal_left_col_height();
    $(document).off("focusin.modal");
    var current_url = window.location.href;
    if (current_url.indexOf("#comment_") > -1) {
      var task_comment_id = current_url.split("#comment_");
      task_comment_id = task_comment_id[task_comment_id.length - 1];
      $('[data-task-comment-href-id="' + task_comment_id + '"]').click();
    }
  });

  // On focus out on the taks modal single update the tags in case changes are found
  $("body").on("blur", "#task-modal ul.tagit li.tagit-new input", function () {
    setTimeout(function () {
      task_single_update_tags();
    }, 100);
  });

  // Assign task to staff member
  $("body").on("change", 'select[name="select-assignees"]', function () {
    $("body").append('<div class="dt-loader"></div>');
    var data = {};
    data.assignee = $('select[name="select-assignees"]').val();
    if (data.assignee !== "") {
      data.taskid = $(this).attr("data-task-id");
      $.post(admin_url + "tasks/add_task_assignees", data).done(function (
        response
      ) {
        $("body").find(".dt-loader").remove();
        response = JSON.parse(response);
        reload_tasks_tables();
        _task_append_html(response.taskHtml);
      });
    }
  });

  // Add follower to task
  $("body").on("change", 'select[name="select-followers"]', function () {
    var data = {};
    data.follower = $('select[name="select-followers"]').val();
    if (data.follower !== "") {
      data.taskid = $(this).attr("data-task-id");
      $("body").append('<div class="dt-loader"></div>');
      $.post(admin_url + "tasks/add_task_followers", data).done(function (
        response
      ) {
        response = JSON.parse(response);
        $("body").find(".dt-loader").remove();
        _task_append_html(response.taskHtml);
      });
    }
  });

  // Task single moda tracking stats close
  $("body").on("click", ".close-task-stats", function () {
    $("#task-tracking-stats-modal").modal("hide");
  });

  // Remove tracking status div because its appended automatically to the DOM on each click
  $("body").on("hidden.bs.modal", "#task-tracking-stats-modal", function () {
    $("#tracking-stats").remove();
  });

  // Task modal single chart for logged time by assigned users
  $("body").on("show.bs.modal", "#task-tracking-stats-modal", function () {
    var tracking_chart_selector = $("body").find("#task-tracking-stats-chart");
    setTimeout(function () {
      if (typeof taskTrackingChart != "undefined") {
        taskTrackingChart.destroy();
      }
      taskTrackingChart = new Chart(tracking_chart_selector, {
        type: "line",
        data: taskTrackingStatsData,
        options: {
          legend: {
            display: false,
          },
          responsive: true,
          maintainAspectRatio: false,
          tooltips: {
            enabled: true,
            mode: "single",
            callbacks: {
              label: function (tooltipItems, data) {
                return decimalToHM(tooltipItems.yLabel);
              },
            },
          },
          scales: {
            yAxes: [
              {
                ticks: {
                  beginAtZero: true,
                  min: 0,
                  userCallback: function (label, index, labels) {
                    return decimalToHM(label);
                  },
                },
              },
            ],
          },
        },
      });
    }, 800);
  });

  // In lead modal issue with reminder modal height
  $("body").on("shown.bs.modal", "#sync_data_proposal_data", function () {
    if ($("#sync_data_proposal_data").data("rel-type") == "lead") {
      $("#lead-modal .data")
        .eq(0)
        .css(
          "height",
          $("#sync_data_proposal_data .modal-content").height() + 80 + "px"
        )
        .css("overflow-x", "hidden");
    }
  });

  // Remove on lead modal reminder inline style
  $("body").on("hidden.bs.modal", "#sync_data_proposal_data", function () {
    if ($("#sync_data_proposal_data").data("rel-type") == "lead") {
      $("#lead-modal .data").prop("style", "");
    }
  });

  // Maybe lead ID passed from url?
  if (typeof openLeadID != "undefined" && openLeadID !== "") {
    init_lead(openLeadID, get_url_param("edit") ? true : false);
  }

  // Status color change
  $("body").on("click", ".leads-kan-ban .cpicker", function () {
    var color = $(this).data("color");
    var status_id = $(this).parents(".panel-heading").data("status-id");
    $.post(admin_url + "leads/change_status_color", {
      color: color,
      status_id: status_id,
    });
  });

  // Lead edit toggle view/edit
  $("body").on("click", "[lead-edit]", function (e) {
    e.preventDefault();
    var $leadEdit = $("body .lead-edit");
    $("body .lead-view").toggleClass("hide");
    $leadEdit.toggleClass("hide");
    if (!$leadEdit.hasClass("hide")) {
      var $address = $("#lead-modal").find("#address");
      var scrollHeight = $address[0].scrollHeight;
      if ($address.is("textarea")) {
        $address.height(0).height(scrollHeight - 15);
        $address.css("padding-top", "9px");
      }
    }
  });

  // Creates new lead with pre-selected status from leads kan ban
  $("body").on("click", ".new-lead-from-status", function (e) {
    e.preventDefault();
    var status_id = $(this).parents(".kan-ban-col").data("col-status-id");
    init_lead_modal_data(
      undefined,
      admin_url + "leads/lead?status_id=" + status_id
    );
    $('body [data-toggle="popover"]').popover("hide");
  });

  // When converting lead to customer, custom fields merging options.
  $("body").on("change", "input.include_leads_custom_fields", function () {
    var val = $(this).val();
    var fieldid = $(this).data("field-id");
    val == 2
      ? $("#merge_db_field_" + fieldid).removeClass("hide")
      : $("#merge_db_field_" + fieldid).addClass("hide");
    val == 3
      ? $("#merge_db_contact_field_" + fieldid)
      : $("#merge_db_contact_field_" + fieldid).addClass("hide");
  });

  // Check if calendar exists in the DOM and init.
  if (calendar_selector.length > 0) {
    validate_calendar_form();

    var calendar_settings = {
      customButtons: {},
      locale: app.locale,
      headerToolbar: {
        left: "prev,next today",
        center: "title",
        right: "dayGridMonth,timeGridWeek,timeGridDay",
      },
      editable: false,
      dayMaxEventRows: parseInt(app.options.calendar_events_limit) + 1,

      views: {
        day: {
          dayMaxEventRows: false,
        },
      },

      direction: isRTL == "true" ? "rtl" : "ltr",
      eventStartEditable: false,
      firstDay: parseInt(app.options.calendar_first_day),
      initialView: app.options.default_view_calendar,
      timeZone: app.options.timezone,

      loading: function (isLoading, view) {
        !isLoading
          ? $(".dt-loader").addClass("hide")
          : $(".dt-loader").removeClass("hide");
      },

      eventSources: [
        function (info, successCallback, failureCallback) {
          var params = {};
          $("#calendar_filters")
            .find("input:checkbox:checked")
            .map(function () {
              params[$(this).attr("name")] = true;
            })
            .get();

          if (!jQuery.isEmptyObject(params)) {
            params["calendar_filters"] = true;
          }

          return $.getJSON(
            admin_url + "utilities/get_calendar_data",
            $.extend({}, params, {
              start: info.startStr,
              end: info.endStr,
            })
          ).then(function (data) {
            successCallback(
              data.map(function (e) {
                return $.extend({}, e, {
                  start: e.start || e.date,
                  end: e.end || e.date,
                });
              })
            );
          });
        },
      ],

      moreLinkClick: function (info) {
        calendar.gotoDate(info.date);
        calendar.changeView("dayGridDay");

        setTimeout(function () {
          $(".fc-popover-close").click();
        }, 250);
      },

      eventDidMount: function (data) {
        var $el = $(data.el);
        $el.attr("title", data.event.extendedProps._tooltip);
        $el.attr("onclick", data.event.extendedProps.onclick);
        $el.attr("data-toggle", "tooltip");
        if (!data.event.extendedProps.url) {
          $el.on("click", function () {
            view_event(data.event.extendedProps.eventid);
          });
        }
      },

      dateClick: function (info) {
        if (info.dateStr.length <= 10) {
          // has not time
          info.dateStr += "T00:00:00";
        }

        var fmt = new DateFormatter();

        var d1 = fmt.formatDate(
          new Date(info.dateStr),
          (vformat =
            app.options.time_format == 24
              ? app.options.date_format + " H:i"
              : app.options.date_format + " g:i A")
        );

        $("input[name='start'].datetimepicker").val(d1);
        $("#newEventModal").modal("show");

        return false;
      },
    };

    if ($("body").hasClass("dashboard")) {
      calendar_settings.customButtons.viewFullCalendar = {
        text: app.lang.calendar_expand,
        click: function () {
          window.location.href = admin_url + "utilities/calendar";
        },
      };

      calendar_settings.headerToolbar.left += ",viewFullCalendar";
    }

    calendar_settings.customButtons.calendarFilter = {
      text: app.lang.filter_by.toLowerCase(),
      click: function () {
        slideToggle("#calendar_filters");
      },
    };

    calendar_settings.headerToolbar.right += ",calendarFilter";

    if (app.user_is_staff_member == 1) {
      if (app.options.google_api !== "") {
        calendar_settings.googleCalendarApiKey = app.options.google_api;
      }

      if (app.calendarIDs !== "") {
        app.calendarIDs = JSON.parse(app.calendarIDs);
        if (app.calendarIDs.length != 0) {
          if (app.options.google_api !== "") {
            for (var i = 0; i < app.calendarIDs.length; i++) {
              var _gcal = {};
              _gcal.googleCalendarId = app.calendarIDs[i];
              calendar_settings.eventSources.push(_gcal);
            }
          } else {
            console.error(
              "You have setup Google Calendar IDs but you dont have specified Google API key. To setup Google API key navigate to Setup->Settings->Google"
            );
          }
        }
      }
    }

    var calendar = new FullCalendar.Calendar(
      calendar_selector[0],
      calendar_settings
    );
    calendar.render();

    var new_event = get_url_param("new_event");

    if (new_event) {
      $("input[name='start'].datetimepicker").val(get_url_param("date"));
      $("#newEventModal").modal("show");
    }
  }

  // On select with name tax apply necessary actions if tax2 exists too
  $("body").on("change", 'select[name="tax"]', function () {
    var sp_tax_2 = $("body").find('select[name="tax2"]');
    var sp_tax_1 = $(this);
    if (sp_tax_1.val() !== "") {
      sp_tax_2.prop("disabled", false);
    } else {
      sp_tax_2.prop("disabled", true);
      if (sp_tax_2.val() !== "") {
        sp_tax_1.selectpicker("val", sp_tax_2.val());
        sp_tax_2.val("");
        sp_tax_1.selectpicker("refresh");
      }
    }
    sp_tax_2.selectpicker("refresh");
  });

  $("body").on("click", "#invoice_create_credit_note", function (e) {
    if ($(this).attr("data-status") == 2) {
      return true;
    } else {
      var $m = $("#confirm_credit_note_create_from_invoice");
      $m.modal("show");
      $m.find("#confirm-invoice-credit-note").attr(
        "href",
        $(this).attr("href")
      );
      e.preventDefault();
    }
  });

      $("body").on("click", "#invoice_create_debit_note", function (e) {
    if ($(this).attr("data-status") == 2) {
      return true;
    } else {
      var $m = $("#confirm_debit_note_create_from_invoice");
      $m.modal("show");
      $m.find("#confirm-invoice-debit-note").attr(
        "href",
        $(this).attr("href")
      );
      e.preventDefault();
    }
  });

  $("body").on(
    "change blur",
    ".apply-credits-to-invoice .apply-credits-field",
    function () {
      var $applyCredits = $("#apply_credits");
      var $amountInputs = $applyCredits.find("input.apply-credits-field");
      var total = 0;
      var creditsRemaining = $applyCredits.attr("data-credits-remaining");

      $.each($amountInputs, function () {
        if ($(this).valid() === true) {
          var amount = $(this).val();
          amount = parseFloat(amount);
          if (!isNaN(amount)) {
            total += amount;
          } else {
            $(this).val(0);
          }
        }
      });

      $applyCredits.find("#credits-alert").remove();
      $applyCredits.find(".amount-to-credit").html(format_money(total));
      if (creditsRemaining < total) {
        $(".credits-table").before(
          $("<div/>", {
            id: "credits-alert",
            class: "alert alert-danger",
          }).html(
            app.lang.credit_amount_bigger_then_credit_note_remaining_credits
          )
        );
        $applyCredits.find('[type="submit"]').prop("disabled", true);
      } else {
        $applyCredits
          .find(".credit-note-balance-due")
          .html(format_money(creditsRemaining - total));
        $applyCredits.find('[type="submit"]').prop("disabled", false);
      }
    }
  );

  $("body").on(
    "change blur",
    ".apply-credits-from-invoice .apply-credits-field",
    function () {
      var $applyCredits = $("#apply_credits");
      var $amountInputs = $applyCredits.find("input.apply-credits-field");
      var total = 0;
      var invoiceBalanceDue = $applyCredits.attr("data-balance-due");

      $.each($amountInputs, function () {
        if ($(this).valid() === true) {
          var amount = $(this).val();
          amount = parseFloat(amount);
          if (!isNaN(amount)) {
            total += amount;
          } else {
            $(this).val(0);
          }
        }
      });

      $applyCredits.find("#credits-alert").remove();
      $applyCredits.find(".amount-to-credit").html(format_money(total));
      if (total > invoiceBalanceDue) {
        $(".credits-table").before(
          $("<div/>", {
            id: "credits-alert",
            class: "alert alert-danger",
          }).html(app.lang.credit_amount_bigger_then_invoice_balance)
        );
        $applyCredits.find('[type="submit"]').prop("disabled", true);
      } else {
        $applyCredits
          .find(".invoice-balance-due")
          .html(format_money(invoiceBalanceDue - total));
        $applyCredits.find('[type="submit"]').prop("disabled", false);
      }
    }
  );
//Debit
   $("body").on(
    "change blur",
    ".apply-debits-to-invoice .apply-debits-field",
    function () {
      var $applydebits = $("#apply_debits");
      var $amountInputs = $applydebits.find("input.apply-debits-field");
      var total = 0;
      var debitsRemaining = $applydebits.attr("data-debits-remaining");

      $.each($amountInputs, function () {
        if ($(this).valid() === true) {
          var amount = $(this).val();
          amount = parseFloat(amount);
          if (!isNaN(amount)) {
            total += amount;
          } else {
            $(this).val(0);
          }
        }
      });

      $applydebits.find("#debits-alert").remove();
      $applydebits.find(".amount-to-debit").html(format_money(total));
      if (debitsRemaining < total) {
        $(".debits-table").before(
          $("<div/>", {
            id: "debits-alert",
            class: "alert alert-danger",
          }).html(
            app.lang.debit_amount_bigger_then_debit_note_remaining_debits
          )
        );
        $applydebits.find('[type="submit"]').prop("disabled", true);
      } else {
        $applydebits
          .find(".debit-note-balance-due")
          .html(format_money(debitsRemaining - total));
        $applydebits.find('[type="submit"]').prop("disabled", false);
      }
    }
  );


  //Debit Ends

  $("body").on(
    "change blur",
    ".apply-debits-from-invoice .apply-debits-field",
    function () {
      var $applyDebits = $("#apply_debits");
      var $amountInputs = $applyDebits.find("input.apply-debits-field");
      var total = 0;
      var invoiceBalanceDue = $applyDebits.attr("data-balance-due");

      $.each($amountInputs, function () {
        if ($(this).valid() === true) {
          var amount = $(this).val();
          amount = parseFloat(amount);
          if (!isNaN(amount)) {
            total += amount;
          } else {
            $(this).val(0);
          }
        }
      });

      $applyDebits.find("#debits-alert").remove();
      $applyDebits.find(".amount-to-debit").html(format_money(total));
      if (total > invoiceBalanceDue) {
        $(".debits-table").before(
          $("<div/>", {
            id: "credits-alert",
            class: "alert alert-danger",
          }).html(app.lang.debit_amount_bigger_then_invoice_balance)
        );
        $applyDebits.find('[type="submit"]').prop("disabled", true);
      } else {
        $applyDebits
          .find(".invoice-balance-due")
          .html(format_money(invoiceBalanceDue - total));
        $applyDebits.find('[type="submit"]').prop("disabled", false);
      }
    }
  );
  //Debit
 $("body").on(
    "change blur",
    ".apply-debits-from-invoice .apply-debits-field",
    function () {
      var $applydebits = $("#apply_debits");
      var $amountInputs = $applydebits.find("input.apply-debits-field");
      var total = 0;
      var invoiceBalanceDue = $applydebits.attr("data-balance-due");

      $.each($amountInputs, function () {
        if ($(this).valid() === true) {
          var amount = $(this).val();
          amount = parseFloat(amount);
          if (!isNaN(amount)) {
            total += amount;
          } else {
            $(this).val(0);
          }
        }
      });

      $applydebits.find("#debits-alert").remove();
      $applydebits.find(".amount-to-debit").html(format_money(total));
      if (total > invoiceBalanceDue) {
        $(".debits-table").before(
          $("<div/>", {
            id: "debits-alert",
            class: "alert alert-danger",
          }).html(app.lang.debit_amount_bigger_then_invoice_balance)
        );
        $applydebits.find('[type="submit"]').prop("disabled", true);
      } else {
        $applydebits
          .find(".invoice-balance-due")
          .html(format_money(invoiceBalanceDue - total));
        $applydebits.find('[type="submit"]').prop("disabled", false);
      }
    }
  );
  //Debits Ends
  // Leads integrations notify type
  $('input[name="notify_type"]').on("change", function () {
    var val = $('input[name="notify_type"]:checked').val();
    var specific_staff_notify = $("#specific_staff_notify");
    var role_notify = $("#role_notify");
    if (val == "specific_staff") {
      specific_staff_notify.removeClass("hide");
      role_notify.addClass("hide");
    } else if (val == "roles") {
      specific_staff_notify.addClass("hide");
      role_notify.removeClass("hide");
    } else if (val == "assigned") {
      specific_staff_notify.addClass("hide");
      role_notify.addClass("hide");
    }
  });

  // Auto focus the lead name if user is adding new lead
  $("body").on("shown.bs.modal", "#lead-modal", function (e) {
    custom_fields_hyperlink();
    if ($("body").find('#lead-modal input[name="leadid"]').length === 0) {
      $("body").find('#lead-modal input[name="name"]').focus();
    }
    init_tabs_scrollable();
    if ($("body").find(".lead-wrapper").hasClass("open-edit")) {
      $("body").find("a[lead-edit]").click();
    }
  });

  // Remove the more button for leads if there is no options in the dropdown
  // This is happening because the if statements are not checked
  $("body").on("show.bs.modal", "#lead-modal", function (e) {
    if ($("#lead-more-dropdown").find("li").length == 0) {
      $("#lead-more-btn").css("display", "none").css("pointer-events", "none");
    }
  });

  // On hidden lead modal some actions need to be operated here
  $("#lead-modal").on("hidden.bs.modal", function (event) {
    destroy_dynamic_scripts_in_element($(this));
    $(this).data("bs.modal", null);
    $("#lead_reminder_modal").html("");
    // clear the hash
    if (!$("#lead-modal").is(":visible")) {
      history.pushState(
        "",
        document.title,
        window.location.pathname + window.location.search
      );
    }
    $("body #lead-modal .datetimepicker").datetimepicker("destroy");
    if (typeof leadAttachmentsDropzone != "undefined") {
      leadAttachmentsDropzone.destroy();
    }
  });

  $("body").on("submit", "#lead-modal .consent-form", function () {
    var data = $(this).serialize();
    $.post($(this).attr("action"), data).done(function (response) {
      response = JSON.parse(response);
      init_lead_modal_data(response.lead_id);
    });
    return false;
  });
  // Set hash on modal tab change
  $("body").on("click", '#lead-modal a[data-toggle="tab"]', function () {
    if (
      this.hash == "#tab_lead_profile" ||
      this.hash == "#attachments" ||
      this.hash == "#lead_notes" ||
      this.hash == "#gdpr" ||
      this.hash == "#lead_activity"
    ) {
      window.location.hash = this.hash;
    } else {
      history.pushState(
        "",
        document.title,
        window.location.pathname + window.location.search
      );
    }
    // Lead modal backdrop is showing some issues with index, is fixed after triggering document resize
    $(document).resize();
  });

  // Manually add lead activity
  $("body").on("click", "#lead_enter_activity", function () {
    var message = $("#lead_activity_textarea").val();
    var aLeadId = $("#lead-modal").find('input[name="leadid"]').val();
    if (message === "") {
      return;
    }
    $.post(admin_url + "leads/add_activity", {
      leadid: aLeadId,
      activity: message,
    })
      .done(function (response) {
        response = JSON.parse(response);
        _lead_init_data(response, response.id);
      })
      .fail(function (data) {
        alert_float("danger", data.responseText);
      });
  });

  // Submit notes on lead modal do ajax not the regular request
  $("body").on("submit", "#lead-modal #lead-notes", function () {
    var form = $(this);
    var data = $(form).serialize();
    $.post(form.attr("action"), data)
      .done(function (response) {
        response = JSON.parse(response);
        _lead_init_data(response, response.id);
      })
      .fail(function (data) {
        alert_float("danger", data.responseText);
      });
    return false;
  });

  // Add additional server params $_POST
  var LeadsServerParams = {
    custom_view: "[name='custom_view']",
    assigned: "[name='view_assigned']",
    status: "[name='view_status[]']",
    source: "[name='view_source']",
  };

  // Init the table
  table_leads = $("table.table-leads");
  if (table_leads.length) {
    var tableLeadsConsentHeading = table_leads.find("#th-consent");
    var leadsTableNotSortable = [0];
    var leadsTableNotSearchable = [0, table_leads.find("#th-assigned").index()];

    if (tableLeadsConsentHeading.length > 0) {
      leadsTableNotSortable.push(tableLeadsConsentHeading.index());
      leadsTableNotSearchable.push(tableLeadsConsentHeading.index());
    }

    _table_api = initDataTable(
      table_leads,
      admin_url + "leads/table",
      leadsTableNotSearchable,
      leadsTableNotSortable,
      LeadsServerParams,
      [table_leads.find("th.date-created").index(), "desc"]
    );

    if (_table_api && tableLeadsConsentHeading.length > 0) {
      _table_api.on("draw", function () {
        var tableData = table_leads.find("tbody tr");
        $.each(tableData, function () {
          $(this).find("td:eq(3)").addClass("bg-neutral");
        });
      });
    }

    $.each(LeadsServerParams, function (i, obj) {
      $("select" + obj).on("change", function () {
        $("[name='view_status[]']")
          .prop("disabled", $(this).val() == "lost" || $(this).val() == "junk")
          .selectpicker("refresh");

        table_leads.DataTable().ajax.reload();
      });
    });
  }

  // When adding if lead is contacted today
  $("body").on("change", 'input[name="contacted_today"]', function () {
    var checked = $(this).prop("checked");
    var lsdc = $(".lead-select-date-contacted");
    checked == false ? lsdc.removeClass("hide") : lsdc.addClass("hide");
  });

  // Lead modal show contacted indicator input
  $("body").on("change", 'input[name="contacted_indicator"]', function () {
    var lsdc = $(".lead-select-date-contacted");
    $(this).val() == "yes" ? lsdc.removeClass("hide") : lsdc.addClass("hide");
  });

  // Custom close function for reminder modals in case is modal in modal
  $("body").on("click", ".close-reminder-modal", function () {
    $(
      ".reminder-modal-" +
        $(this).data("rel-type") +
        "-" +
        $(this).data("rel-id")
    ).modal("hide");
  });

  // Init are you sure on forms
  $("form")
    .not(
      "#single-ticket-form,#calendar-event-form,#proposal-form, #department-form"
    )
    .areYouSure();

  // For inline tinymce editors when content is blank a message is shown, on click this message should be hidden.
  $("body").on("click", ".editor-add-content-notice", function () {
    var that = $(this);
    setTimeout(function () {
      that.remove();
      tinymce.triggerSave();
    }, 500);
  });

  // Global on change for mass delete to hide all other elements for bulk actions
  $(".bulk_actions").on("change", 'input[name="mass_delete"]', function () {
    var $bulkChange = $("#bulk_change");
    if ($(this).prop("checked") === true) {
      $bulkChange.find("select").selectpicker("val", "");
      $bulkChange.addClass("hide");
      $(".mass_delete_separator, merge_tickets_checkbox").addClass("hide");
      $("#merge_tickets").prop("checked", false);
    } else {
      $bulkChange.removeClass("hide");
      $(".mass_delete_separator, merge_tickets_checkbox").removeClass("hide");
    }
  });

  // Fix for bigger items descriptions, the select is going out of the container
  $("body").on("change loaded.bs.select", "#item_select", function () {
    var selectWrapper = $(".items-wrapper .items-select-wrapper");
    $(".items-wrapper .bootstrap-select").css(
      "max-width",
      selectWrapper.width() + "px"
    );
    $(".items-wrapper .bootstrap-select").css("width", "100%");
  });

  // Send test sms
  $(".send-test-sms").on("click", function () {
    var id = $(this).data("id");
    var errorContainer = $('#sms_test_response[data-id="' + id + '"]');
    var message = $('textarea[data-id="' + id + '"]').val();
    var number = $('input.test-phone[data-id="' + id + '"]').val();
    var that = $(this);
    errorContainer.empty();
    message = message.trim();
    if (message != "" && number != "") {
      that.prop("disabled", true);
      $.post(window.location.href, {
        message: message,
        number: number,
        id: id,
        sms_gateway_test: true,
      })
        .done(function (response) {
          response = JSON.parse(response);
          if (response.success == true) {
            errorContainer.html(
              '<div class="alert alert-success no-mbot mtop15">SMS Sent Successfully!</div>'
            );
          } else {
            errorContainer.html(
              '<div class="alert alert-warning no-mbot mtop15">' +
                response.error +
                "</div>"
            );
          }
        })
        .always(function () {
          that.prop("disabled", false);
        });
    }
  });

  // Clear todo modal values when modal is hidden
  $("body").on("hidden.bs.modal", "#__todo", function () {
    var $toDo = $("#__todo");
    $toDo.find('input[name="todoid"]').val("");
    $toDo.find('textarea[name="description"]').val("");
    $toDo.find(".add-title").addClass("hide");
    $toDo.find(".edit-title").addClass("hide");
  });

  // Focus staff todo description
  $("body").on("shown.bs.modal", "#__todo", function () {
    var $toDo = $("#__todo");
    $toDo.find('textarea[name="description"]').focus();
    if ($toDo.find('input[name="todoid"]').val() !== "") {
      $toDo.find(".add-title").addClass("hide");
      $toDo.find(".edit-title").removeClass("hide");
    } else {
      $toDo.find(".add-title").removeClass("hide");
      $toDo.find(".edit-title").addClass("hide");
    }
  });

  // Focus search input on click
  $("#top_search_button button").on("click", function () {
    var $searchInput = $("#search_input");
    if ($(this).hasClass("search_remove")) {
      $(this).html('<i class="fa fa-search"></i>').removeClass("search_remove");
      original_top_search_val = "";
      $("#search_results").html("");
      $searchInput.val("");
    }
    $searchInput.focus();
  });

  // Fix for dropdown search to close if user click anyhere on html except on dropdown
  $("body").click(function (e) {
    if (
      !$(e.target).parents("#top_search_dropdown").hasClass("search-results")
    ) {
      $("#top_search_dropdown").remove();
    }
  });

  // Init tooltips
  $("body").tooltip({
    selector: '[data-toggle="tooltip"]',
  });

  // Init popovers
  $("body").popover({
    selector: '[data-toggle="popover"]',
  });

  // Do not close the dropdownmenu for filter when filtering
  $("body").on(
    "click",
    "._filter_data ul.dropdown-menu li a,.not-mark-as-read-inline,.not_mark_all_as_read a",
    function (e) {
      e.stopPropagation();
      e.preventDefault();
    }
  );

  // On shown for all modals
  $("body").on("shown.bs.modal", ".modal", function () {
    // Fix for all modals scroll..
    $("body").addClass("modal-open");
    // Close the top timers dropdown in case user click on some task
    $("body").find("#started-timers-top").parents("li").removeClass("open");
  });

  // On hidden for all modals
  $("body").on("hidden.bs.modal", ".modal", function (event) {
    $(".modal:visible").length && $(document.body).addClass("modal-open");
    $(this).data("bs.modal", null);
  });

  // Activity log datepicker on change
  $(".datepicker.activity-log-date").on("change", function () {
    table_activity_log.DataTable().ajax.reload();
  });

  // Import form submit
  $(".btn-import-submit").on("click", function () {
    if ($(this).hasClass("simulate")) {
      $("#import_form").append(hidden_input("simulate", true));
    }
    $("#import_form").submit();
  });

  $("body").on("change", "#unlimited_cycles", function () {
    $(this)
      .parents(".recurring-cycles")
      .find("#cycles")
      .prop("disabled", $(this).prop("checked"));
  });

  // For expenses and recurring tasks
  $("body").on(
    "change",
    '[name="repeat_every"], [name="recurring"]',
    function () {
      var val = $(this).val();
      val == "custom"
        ? $(".recurring_custom").removeClass("hide")
        : $(".recurring_custom").addClass("hide");
      if (val !== "" && val != 0) {
        $("body").find("#cycles_wrapper").removeClass("hide");
      } else {
        $("body").find("#cycles_wrapper").addClass("hide");
        $("body").find("#cycles_wrapper #cycles").val(0);
        $("#unlimited_cycles").prop("checked", true).change();
      }
    }
  );

  // On mass_select all select all the availble rows in the tables.
  $("body").on("change", "#mass_select_all", function () {
    var to, rows, checked;
    to = $(this).data("to-table");

    rows = $(".table-" + to).find("tbody tr");
    checked = $(this).prop("checked");
    $.each(rows, function () {
      $($(this).find("td").eq(0)).find("input").prop("checked", checked);
    });
  });

  // Init the editor for email templates where changing data is allowed
  $("body").on("show.bs.modal", ".modal.email-template", function () {
    init_editor($(this).data("editor-id"), {
      urlconverter_callback: merge_field_format_url,
    });
  });

  // Remove the editor inited for the email sending templates where changing the email template data is allowed
  $("body").on("hidden.bs.modal", ".modal.email-template", function () {
    tinymce.remove($(this).data("editor-id"));
  });

  // Customizer close and remove open from session
  $(".close-customizer").on("click", function (e) {
    e.preventDefault();

    setup_menu.addClass(isRTL == "true" ? "fadeOutRight" : "fadeOutLeft");
    // Clear the session for setup menu so in reload wont be closed
    requestGet("misc/set_setup_menu_closed");
  });

  // Open customizer and add that is open to session
  $(".open-customizer").on("click", function (e) {
    e.preventDefault();

    if (setup_menu.hasClass(isRTL == "true" ? "fadeOutRight" : "fadeOutLeft")) {
      setup_menu.removeClass(isRTL == "true" ? "fadeOutRight" : "fadeOutLeft");
    }

    setup_menu.addClass(
      "display-block " + (isRTL == "true" ? "fadeInRight" : "fadeInLeft")
    );
    // Set session that the setup menu is open in case of reload
    if (!is_mobile()) {
      requestGet("misc/set_setup_menu_open");
    }
    mainWrapperHeightFix();
  });

  // Change live the colors for colorpicker in kanban/pipeline
  $("body").on("click", ".cpicker", function () {
    var color = $(this).data("color");
    // Clicked on the same selected color
    if ($(this).hasClass("cpicker-big")) {
      return false;
    }

    $(this)
      .parents(".cpicker-wrapper")
      .find(".cpicker-big")
      .removeClass("cpicker-big")
      .addClass("cpicker-small");
    $(this)
      .removeClass("cpicker-small", "fast")
      .addClass("cpicker-big", "fast");
    if ($(this).hasClass("kanban-cpicker")) {
      $(this).parents(".panel-heading").css("background", color);
      $(this)
        .parents(".panel-heading")
        .css("border", "1px solid " + color);
    } else if ($(this).hasClass("calendar-cpicker")) {
      $("body").find('._event input[name="color"]').val(color);
    }
  });

  // Notification profile link click
  $("body").on("click", ".notification_link", function () {
    var link = $(this).data("link");
    var not_href;
    not_href = link.split("#");
    if (!not_href[1]) {
      window.location.href = link;
    }
  });

  /* Custom notifications links, NOTE: touchstart listener is for iOS davices */
  $("body").on(
    "click" + ("ontouchstart" in window ? " touchstart" : ""),
    ".notifications a.notification-top, .notification_link",
    function (e) {
      e.preventDefault();
      var $notLink = $(this);
      var not_href_id;

      var not_href = $notLink.hasClass("notification_link")
        ? $notLink.data("link")
        : e.currentTarget.href;

      var not_href_array = not_href.split("#");
      var notRedirect = true;
      if (not_href_array[1] && not_href_array[1].indexOf("=") > -1) {
        notRedirect = false;
        not_href_id = not_href_array[1].split("=")[1];
        if (not_href_array[1].indexOf("postid") > -1) {
          postid = not_href_id;
          if ($(window).width() > 769) {
            $(".open_newsfeed.desktop").click();
          } else {
            $(".open_newsfeed.mobile").click();
          }
        } else if (not_href_array[1].indexOf("taskid") > -1) {
          var comment_id = undefined;
          if (not_href.indexOf("#comment_") > -1) {
            var task_comment_id = not_href.split("#comment_");
            comment_id = task_comment_id[task_comment_id.length - 1];
          }
          init_task_modal(not_href_id, comment_id);
        } else if (not_href_array[1].indexOf("leadid") > -1) {
          init_lead(not_href_id);
        } else if (not_href_array[1].indexOf("eventid") > -1) {
          view_event(not_href_id);
        }
      }
      if (!$notLink.hasClass("desktopClick")) {
        $notLink.parent("li").find(".not-mark-as-read-inline").click();
      }
      if (notRedirect) {
        setTimeout(function () {
          window.location.href = not_href_array;
        }, 50);
      }
    }
  );

  // Set notifications to read when notifictions dropdown is opened
  $(".notifications-wrapper").on("show.bs.dropdown", function () {
    var total = notifications_wrapper
      .find(".notifications")
      .attr("data-total-unread");
    if (total > 0) {
      $.post(admin_url + "misc/set_notifications_read").done(function (
        response
      ) {
        response = JSON.parse(response);
        if (response.success === true || response.success == "true") {
          document.title = doc_initial_title;
          $(".icon-notifications").addClass("hide");
        }
      });
    }
  });

  // Tables
  init_table_tickets();
  init_table_announcements();
  init_table_staff_projects();

  // Ticket pipe log and system activity log
  table_activity_log = $("table.table-activity-log");
  if (table_activity_log.length) {
    var ActivityLogServerParams = [];
    ActivityLogServerParams["activity_log_date"] = '[name="activity_log_date"]';
    initDataTable(
      table_activity_log,
      window.location.href,
      "undefined",
      "undefined",
      ActivityLogServerParams,
      [1, "desc"]
    );
  }

  table_invoices = $("table.table-invoices");
  table_estimates = $("table.table-estimates");

  if (table_invoices.length > 0 || table_estimates.length > 0) {
    // Invoices additional server params
    var Sales_table_ServerParams = {};
    var Sales_table_Filter = $("._hidden_inputs._filters input");

    $.each(Sales_table_Filter, function () {
      Sales_table_ServerParams[$(this).attr("name")] =
        '[name="' + $(this).attr("name") + '"]';
    });

    if (table_invoices.length) {
      // Invoices tables
      initDataTable(
        table_invoices,
        admin_url +
          "invoices/table" +
          ($("body").hasClass("recurring") ? "?recurring=1" : ""),
        "undefined",
        "undefined",
        Sales_table_ServerParams,
        !$("body").hasClass("recurring")
          ? [
              [3, "desc"],
              [0, "desc"],
            ]
          : [table_invoices.find("th.next-recurring-date").index(), "asc"]
      );
    }

    if (table_estimates.length) {
      // Estimates table
      initDataTable(
        table_estimates,
        admin_url + "estimates/table",
        "undefined",
        "undefined",
        Sales_table_ServerParams,
        [
          [3, "desc"],
          [0, "desc"],
        ]
      );
    }
  }

  table_tasks = $(".table-tasks");
  if (table_tasks.length) {
    var TasksServerParams = {},
      Tasks_Filters;
    Tasks_Filters = $("._hidden_inputs._filters._tasks_filters input");
    $.each(Tasks_Filters, function () {
      TasksServerParams[$(this).attr("name")] =
        '[name="' + $(this).attr("name") + '"]';
    });

    // Tasks not sortable
    var tasksTableNotSortable = [0]; // bulk actions
    var tasksTableURL = admin_url + "tasks/table";

    if ($("body").hasClass("tasks-page")) {
      tasksTableURL += "?bulk_actions=true";
    }

    _table_api = initDataTable(
      table_tasks,
      tasksTableURL,
      tasksTableNotSortable,
      tasksTableNotSortable,
      TasksServerParams,
      [table_tasks.find("th.duedate").index(), "asc"]
    );

    if (_table_api && $("body").hasClass("dashboard")) {
      _table_api
        .column(5)
        .visible(false, false)
        .column(6)
        .visible(false, false)
        .columns.adjust();
    }
  }

  // Send file modal populate the hidden files when is shown
  $("#send_file").on("show.bs.modal", function (e) {
    var $sendFile = $("#send_file");
    $sendFile
      .find('input[name="filetype"]')
      .val($($(e.relatedTarget)).data("filetype"));
    $sendFile
      .find('input[name="file_path"]')
      .val($($(e.relatedTarget)).data("path"));
    $sendFile
      .find('input[name="file_name"]')
      .val($($(e.relatedTarget)).data("file-name"));
    if ($('input[name="email"]').length > 0) {
      $sendFile
        .find('input[name="send_file_email"]')
        .val($('input[name="email"]').val());
    }
  });

  $("#send_file form").on("submit", function () {
    $(this).find('button[type="submit"]').prop("disabled", true);
  });

  // Set password checkbox change
  $("body").on("change", 'input[name="send_set_password_email"]', function () {
    $("body").find(".client_password_set_wrapper").toggleClass("hide");
  });

  // Todo status change checkbox click
  $("body").on("change", '.todo input[type="checkbox"]', function () {
    var finished = $(this).prop("checked") === true ? 1 : 0;
    var id = $(this).val();
    window.location.href =
      admin_url + "todo/change_todo_status/" + id + "/" + finished;
  });

  var todos_sortable = $(".todos-sortable");
  if (todos_sortable.length > 0) {
    // Makes todos sortable
    todos_sortable = todos_sortable.sortable({
      connectWith: ".todo",
      items: "li",
      handle: ".dragger",
      appendTo: "body",
      update: function (event, ui) {
        if (this === ui.item.parent()[0]) {
          update_todo_items();
        }
      },
    });
  }

  // Newsfeed close and open
  $("body").on("click", ".open_newsfeed, .close_newsfeed", function (e) {
    e.preventDefault();
    if (typeof $(this).data("close") == "undefined") {
      requestGet("newsfeed/get_data").done(function (response) {
        $("#newsfeed").html(response);
        load_newsfeed(postid);
        init_newsfeed_form();
        init_selectpicker();
        init_lightbox();
      });
    } else if ($(this).data("close") === true) {
      newsFeedDropzone.destroy();
      $("#newsfeed").html("");
      newsfeed_posts_page = 0;
      track_load_post_likes = 0;
      track_load_comment_likes = 0;
      postid = undefined;
    }
    $("#newsfeed").toggleClass("hide");
    $("body").toggleClass("noscroll");
  });

  if ($("[data-newsfeed-auto]").length > 0) {
    if ($(window).width() > 769) {
      $(".open_newsfeed.desktop").click();
    } else {
      $(".open_newsfeed.mobile").click();
    }
  }

  // When adding comment if user press enter to submit comment too for newsfeed comments
  $("body").on("keyup", ".comment-input input", function (event) {
    if (event.keyCode == 13) {
      add_comment(this);
    }
  });

  // Showing post likes modal
  $("#modal_post_likes").on("show.bs.modal", function (e) {
    track_load_post_likes = 0;
    $("#modal_post_likes_wrapper").empty();
    $(".likes_modal .modal-footer").removeClass("hide");
    var invoker = $(e.relatedTarget);
    var postid = $(invoker).data("postid");
    post_likes_total_pages = $(invoker).data("total-pages");
    $(".load_more_post_likes").attr("data-postid", postid);
    load_post_likes(postid);
  });

  // Showing comment likes modal
  $("#modal_post_comment_likes").on("show.bs.modal", function (e) {
    $("#modal_comment_likes_wrapper").empty();
    track_load_comment_likes = 0;
    $(".likes_modal .modal-footer").removeClass("hide");
    var invoker = $(e.relatedTarget);
    var commentid = $(invoker).data("commentid");
    comment_likes_total_pages = $(invoker).data("total-pages");
    $(".load_more_post_comment_likes").attr("data-commentid", commentid);
    load_comment_likes(commentid);
  });

  // Load more post likes from modal
  $(".load_more_post_likes").on("click", function (e) {
    e.preventDefault();
    load_post_likes($(this).data("postid"));
  });

  // Load more comment likes from modal
  $(".load_more_post_comment_likes").on("click", function (e) {
    e.preventDefault();
    load_comment_likes($(this).data("commentid"));
  });

  // Add post attachment used for dropzone
  $(".add-attachments").on("click", function (e) {
    e.preventDefault();
    $("#post-attachments").toggleClass("hide");
  });

  // Init invoices top stats
  init_invoices_total();
  // Init expenses total
  init_expenses_total();
  // Make items sortable
  init_estimates_total();
  // Make items sortable
  init_items_sortable();

  $(".settings-textarea-merge-field").on("click", function (e) {
    e.preventDefault();
    var mergeField = $(this).text().trim();
    var textArea = $('textarea[name="settings[' + $(this).data("to") + ']"]');
    textArea.val(textArea.val() + "\n" + mergeField);
  });

  if ($("body").hasClass("estimates-pipeline")) {
    var estimate_id = $('input[name="estimateid"]').val();
    estimate_pipeline_open(estimate_id);
  }

  if ($("body").hasClass("proposals-pipeline")) {
    var proposal_id = $('input[name="proposalid"]').val();
    proposal_pipeline_open(proposal_id);
  }

  $("body").on("submit", "._transaction_form", function () {
    // On submit re-calculate total and reorder the items for all cases.
    calculate_total();

    $("body").find("#items-warning").remove();
    var $itemsTable = $(this).find("table.items");
    var $previewItem = $itemsTable.find(".main");

    if (
      $previewItem.find('[name="description"]').length &&
      $previewItem.find('[name="description"]').val().trim().length > 0 &&
      $previewItem.find('[name="rate"]').val().trim().length > 0
    ) {
      $itemsTable.before(
        '<div class="alert alert-warning mbot20" id="items-warning">' +
          app.lang.item_forgotten_in_preview +
          '<i class="fa fa-angle-double-down pointer pull-right fa-2x" style="margin-top:-4px;" onclick="add_item_to_table(\'undefined\',\'undefined\',undefined); return false;"></i></div>'
      );

      $("html,body").animate({
        scrollTop: $("#items-warning").offset().top,
      });

      return false;
    } else {
      if ($itemsTable.length && $itemsTable.find(".item").length === 0) {
        $itemsTable.before(
          '<div class="alert alert-warning mbot20" id="items-warning">' +
            app.lang.no_items_warning +
            "</div>"
        );
        $("html,body").animate({
          scrollTop: $("#items-warning").offset().top,
        });
        return false;
      }
    }

    reorder_items();

    // Remove the disabled attribute from the disabled fields becuase if they are disabled won't be sent with the request.
    $('select[name="currency"]').prop("disabled", false);
    $('select[name="project_id"]').prop("disabled", false);
    $('input[name="date"]').prop("disabled", false);

    // Add disabled to submit buttons
    $(this).find(".transaction-submit").prop("disabled", true);

    return true;
  });

  $("body").on("click", ".transaction-submit", function () {
    var that = $(this);
    var form = that.parents("form._transaction_form");
    if (form.valid()) {
      if (that.hasClass("save-as-draft")) {
        form.append(hidden_input("save_as_draft", "true"));
      } else if (that.hasClass("save-and-send")) {
        form.append(hidden_input("save_and_send", "true"));
      } else if (that.hasClass("save-and-record-payment")) {
        form.append(hidden_input("save_and_record_payment", "true"));
      } else if (that.hasClass("save-and-send-later")) {
        form.append(hidden_input("save_and_send_later", "true"));
      }
    }
    form.submit();
  });

  // add invoice/estimate note
  $("body").on("submit", "#sales-notes", function () {
    var form = $(this);
    if (form.find('textarea[name="description"]').val() === "") {
      return;
    }

    $.post(form.attr("action"), $(form).serialize()).done(function (rel_id) {
      // Reset the note textarea value
      form.find('textarea[name="description"]').val("");
      // Reload the notes
      if (form.hasClass("estimate-notes-form")) {
        get_sales_notes(rel_id, "estimates");
      } else if (form.hasClass("invoice-notes-form")) {
        get_sales_notes(rel_id, "invoices");
      } else if (form.hasClass("proposal-notes-form")) {
        get_sales_notes(rel_id, "proposals");
      } else if (form.hasClass("contract-notes-form")) {
        get_sales_notes(rel_id, "contracts");
      }
    });
    return false;
  });

  // Show quantity as change we need to change on the table QTY heading for better user experience
  $("body").on("change", 'input[name="show_quantity_as"]', function () {
    $("body").find("th.qty").html($(this).data("text"));
  });

  // No duedate for credit note, separate event
  $("body").on("change", 'div.credit_note input[name="date"]', function () {
    do_prefix_year($(this).val());
  });

    //Debit
   $("body").on("change", 'div.debit_note input[name="date"]', function () {
    do_prefix_year($(this).val());
  });

  $("body").on(
    "change",
    'div.invoice input[name="date"], div.estimate input[name="date"], div.proposal input[name="date"]',
    function () {
      var date = $(this).val();
      do_prefix_year(date);

      // This function not work on edit
      if ($('input[name="isedit"]').length > 0) {
        return;
      }

      var due_date_input_name = "duedate";
      var due_calc_url = admin_url + "invoices/get_due_date";

      if ($("body").find("div.estimate").length > 0) {
        due_calc_url = admin_url + "estimates/get_due_date";
        due_date_input_name = "expirydate";
      } else if ($("body").find("div.proposal").length > 0) {
        due_calc_url = admin_url + "proposals/get_due_date";
        due_date_input_name = "open_till";
      }

      if (date === "") {
        $('input[name="' + due_date_input_name + '"]').val("");
      }

      if (date !== "") {
        $.post(due_calc_url, {
          date: date,
        }).done(function (formatted) {
          if (formatted) {
            $('input[name="' + due_date_input_name + '"]').val(formatted);
          }
        });
      }
    }
  );

  $("#sales_attach_file").on("hidden.bs.modal", function (e) {
    $("#sales_uploaded_files_preview").empty();
    $(".dz-file-preview").empty();
  });

  if (typeof Dropbox != "undefined") {
    if ($("#dropbox-chooser-sales").length > 0) {
      document.getElementById("dropbox-chooser-sales").appendChild(
        Dropbox.createChooseButton({
          success: function (files) {
            salesExtenalFileUpload(files, "dropbox");
          },
          linkType: "preview",
          extensions: app.options.allowed_files.split(","),
        })
      );
    }
  }

  if ($("#sales-upload").length > 0) {
    new Dropzone(
      "#sales-upload",
      appCreateDropzoneOptions({
        sending: function (file, xhr, formData) {
          formData.append(
            "rel_id",
            $("body").find('input[name="_attachment_sale_id"]').val()
          );
          formData.append(
            "type",
            $("body").find('input[name="_attachment_sale_type"]').val()
          );
        },
        success: function (files, response) {
          response = JSON.parse(response);
          var type = $("body")
            .find('input[name="_attachment_sale_type"]')
            .val();
          var dl_url, delete_function;
          dl_url = "download/file/sales_attachment/";
          delete_function = "delete_" + type + "_attachment";
          if (type == "estimate") {
            $("body").hasClass("estimates-pipeline")
              ? estimate_pipeline_open(response.rel_id)
              : init_estimate(response.rel_id);
          } else if (type == "proposal") {
            $("body").hasClass("proposals-pipeline")
              ? proposal_pipeline_open(response.rel_id)
              : init_proposal(response.rel_id);
          } else {
            if (typeof window["init_" + type] == "function") {
              window["init_" + type](response.rel_id);
            }
          }
          var data = "";
          if (response.success === true || response.success == "true") {
            data +=
              '<div class="display-block sales-attach-file-preview" data-attachment-id="' +
              response.attachment_id +
              '">';
            data += '<div class="col-md-10">';
            data +=
              '<div class="pull-left"><i class="attachment-icon-preview fa-regular fa-file"></i></div>';
            data +=
              '<a href="' +
              site_url +
              dl_url +
              response.key +
              '" target="_blank">' +
              response.file_name +
              "</a>";
            data += '<p class="text-muted">' + response.filetype + "</p>";
            data += "</div>";
            data += '<div class="col-md-2 text-right">';
            data +=
              '<a href="#" class="text-danger" onclick="' +
              delete_function +
              "(" +
              response.attachment_id +
              '); return false;"><i class="fa fa-times"></i></a>';
            data += "</div>";
            data += '<div class="clearfix"></div><hr/>';
            data += "</div>";
            $("#sales_uploaded_files_preview").append(data);
          }
        },
      })
    );
  }

  // Show send to email invoice modal
  $("body").on("click", ".invoice-send-to-client", function (e) {
    e.preventDefault();
    $("#invoice_send_to_client_modal").modal("show");
  });

  // Show send to email estimate modal
  $("body").on("click", ".estimate-send-to-client", function (e) {
    e.preventDefault();
    $("#estimate_send_to_client_modal").modal("show");
  });

  // Send templaate modal custom close function causing problems if is on pipeline view
  $("body").on("click", ".close-send-template-modal", function () {
    $("#estimate_send_to_client_modal").modal("hide");
    $("#proposal_send_to_customer").modal("hide");
  });

  // Include shipping show/hide details
  $("body").on("change", "#include_shipping", function () {
    var $sd = $("#shipping_details");
    $(this).prop("checked") === true
      ? $sd.removeClass("hide")
      : $sd.addClass("hide");
  });

  // Init the billing and shipping details in the field - estimates and invoices
  $("body").on("click", ".save-shipping-billing", function (e) {
    init_billing_and_shipping_details();
  });

  // On change currency recalculate price and change symbol
  $("body").on("change", 'select[name="currency"]', function () {
    init_currency();
  });

  // Recaulciate total on these changes
  $("body").on("change", 'input[name="adjustment"],select.tax', function () {
    calculate_total();
  });

  $("body").on("click", ".discount-total-type", function (e) {
    e.preventDefault();
    $("#discount-total-type-dropdown")
      .find(".discount-total-type")
      .removeClass("selected");
    $(this).addClass("selected");
    $(".discount-total-type-selected").html($(this).text());
    if ($(this).hasClass("discount-type-percent")) {
      $(".input-discount-fixed").addClass("hide").val(0);
      $(".input-discount-percent").removeClass("hide");
    } else {
      $(".input-discount-fixed").removeClass("hide");
      $(".input-discount-percent").addClass("hide").val(0);
      $("#discount_percent-error").remove();
    }
    calculate_total();
  });

  // Discount type for estimate/invoice
  $("body").on("change", 'select[name="discount_type"]', function () {
    // if discount_type == ''
    if ($(this).val() === "") {
      $('input[name="discount_percent"]').val(0);
    }
    // Recalculate the total
    calculate_total();
  });

  // In case user enter discount percent but there is no discount type set
  $("body").on(
    "change",
    'input[name="discount_percent"],input[name="discount_total"]',
    function () {
      if (
        $('select[name="discount_type"]').val() === "" &&
        $(this).val() != 0
      ) {
        if ($("td[id^='tax_id_']").length === 0) {
          return;
        }
        alert("You need to select discount type");
        $("html,body").animate(
          {
            scrollTop: 0,
          },
          "slow"
        );
        $("#wrapper").highlight($('label[for="discount_type"]').text());
        setTimeout(function () {
          $("#wrapper").unhighlight();
        }, 3000);
        return false;
      }
      if ($(this).valid() === true) {
        calculate_total();
      }
    }
  );

  $("body").on("change", ".invoice #project_id", function () {
    var project_id = $(this).selectpicker("val");
    if (project_id !== "") {
      requestGetJSON("tasks/get_billable_tasks_by_project/" + project_id).done(
        function (tasks) {
          _init_tasks_billable_select(tasks, project_id);
        }
      );
    } else {
      var client_id = $("#clientid").selectpicker("val");
      if (client_id !== "") {
        requestGetJSON(
          "tasks/get_billable_tasks_by_customer_id/" + client_id
        ).done(function (tasks) {
          _init_tasks_billable_select(tasks);
        });
      } else {
        // Empty dropdown
        _init_tasks_billable_select([], "");
      }
    }
  });

  // Add task data to preview from the dropdown for invoiecs
  $("body").on("change", 'select[name="task_select"]', function () {
    $(this).selectpicker("val") !== ""
      ? add_task_to_preview_as_item($(this).selectpicker("val"))
      : "";
  });

  // When user record payment check if is online mode
  $("body").on("change", 'select[name="paymentmode"]', function () {
    var $notRedirect = $(".do_not_redirect");
    !$.isNumeric($(this).val())
      ? $notRedirect.removeClass("hide")
      : $notRedirect.addClass("hide");
  });

  $("body").on("change", ".f_client_id #clientid", function () {
    var val = $(this).val();
    var projectAjax = $('select[name="project_id"]');
    var clonedProjectsAjaxSearchSelect = projectAjax.html("").clone();
    var projectsWrapper = $(".projects-wrapper");
    projectAjax.selectpicker("destroy").remove();
    projectAjax = clonedProjectsAjaxSearchSelect;
    $("#project_ajax_search_wrapper").append(clonedProjectsAjaxSearchSelect);
    init_ajax_project_search_by_customer_id();
    clear_billing_and_shipping_details();
    if (!val) {
      $("#merge").empty();
      $("#expenses_to_bill").empty();
      $("#invoice_top_info").addClass("hide");
      projectsWrapper.addClass("hide");
      return false;
    }

    var currentInvoiceID = $("body")
      .find('input[name="merge_current_invoice"]')
      .val();
    currentInvoiceID =
      typeof currentInvoiceID == "undefined" ? "" : currentInvoiceID;

    requestGetJSON(
      "invoices/client_change_data/" + val + "/" + currentInvoiceID
    ).done(function (response) {
      $("#merge").html(response.merge_info);
      var $billExpenses = $("#expenses_to_bill");
      // Invoice from project, in invoice_template this is not shown
      $billExpenses.length === 0
        ? (response.expenses_bill_info = "")
        : $billExpenses.html(response.expenses_bill_info);
      response.merge_info !== "" || response.expenses_bill_info !== ""
        ? $("#invoice_top_info").removeClass("hide")
        : $("#invoice_top_info").addClass("hide");

      for (var f in billingAndShippingFields) {
        if (billingAndShippingFields[f].indexOf("billing") > -1) {
          if (billingAndShippingFields[f].indexOf("country") > -1) {
            $(
              'select[name="' + billingAndShippingFields[f] + '"]'
            ).selectpicker(
              "val",
              response["billing_shipping"][0][billingAndShippingFields[f]]
            );
          } else {
            if (billingAndShippingFields[f].indexOf("billing_street") > -1) {
              $('textarea[name="' + billingAndShippingFields[f] + '"]').val(
                response["billing_shipping"][0][billingAndShippingFields[f]]
              );
            } else {
              $('input[name="' + billingAndShippingFields[f] + '"]').val(
                response["billing_shipping"][0][billingAndShippingFields[f]]
              );
            }
          }
        }
      }

      if (!empty(response["billing_shipping"][0]["shipping_street"])) {
        $('input[name="include_shipping"]').prop("checked", true).change();
      }

      for (var fsd in billingAndShippingFields) {
        if (billingAndShippingFields[fsd].indexOf("shipping") > -1) {
          if (billingAndShippingFields[fsd].indexOf("country") > -1) {
            $(
              'select[name="' + billingAndShippingFields[fsd] + '"]'
            ).selectpicker(
              "val",
              response["billing_shipping"][0][billingAndShippingFields[fsd]]
            );
          } else {
            if (billingAndShippingFields[fsd].indexOf("shipping_street") > -1) {
              $('textarea[name="' + billingAndShippingFields[fsd] + '"]').val(
                response["billing_shipping"][0][billingAndShippingFields[fsd]]
              );
            } else {
              $('input[name="' + billingAndShippingFields[fsd] + '"]').val(
                response["billing_shipping"][0][billingAndShippingFields[fsd]]
              );
            }
          }
        }
      }

      init_billing_and_shipping_details();

      var client_currency = response["client_currency"];
      var s_currency = $("body").find(
        '.accounting-template select[name="currency"]'
      );
      client_currency = parseInt(client_currency);
      client_currency != 0
        ? s_currency.val(client_currency)
        : s_currency.val(s_currency.data("base"));
      _init_tasks_billable_select(
        response["billable_tasks"],
        projectAjax.selectpicker("val")
      );
      response.customer_has_projects === true
        ? projectsWrapper.removeClass("hide")
        : projectsWrapper.addClass("hide");
      s_currency.selectpicker("refresh");
      init_currency();
    });
  });

  // When customer_id is passed init the data
  if ($("body").find('input[name="isedit"]').length === 0) {
    $('.f_client_id select[name="clientid"]').change();
  }

  $("body").on("click", "#get_shipping_from_customer_profile", function (e) {
    e.preventDefault();
    var include_shipping = $("#include_shipping");
    if (include_shipping.prop("checked") === false) {
      include_shipping.prop("checked", true);
      $("#shipping_details").removeClass("hide");
    }
    var clientid = $("#clientid").val();
    if (clientid === "") {
      return;
    }
    requestGetJSON(
      "clients/get_customer_billing_and_shipping_details/" + clientid
    ).done(function (response) {
      $('textarea[name="shipping_street"]').val(response[0]["shipping_street"]);
      $('input[name="shipping_city"]').val(response[0]["shipping_city"]);
      $('input[name="shipping_state"]').val(response[0]["shipping_state"]);
      $('input[name="shipping_zip"]').val(response[0]["shipping_zip"]);
      $('select[name="shipping_country"]').selectpicker(
        "val",
        response[0]["shipping_country"]
      );
    });
  });

  if (typeof accounting != "undefined") {
    // For currency
    accounting.settings.currency.precision = app.options.decimal_places;

    // Used for numbers
    accounting.settings.number.thousand = app.options.thousand_separator;
    accounting.settings.number.decimal = app.options.decimal_separator;
    accounting.settings.number.precision = app.options.decimal_places;

    calculate_total();
  }

  // Invoices to merge
  $("body").on("change", 'input[name="invoices_to_merge[]"]', function () {
    var checked = $(this).prop("checked");
    var _id = $(this).val();
    if (checked === true) {
      requestGetJSON("invoices/get_merge_data/" + _id).done(function (
        response
      ) {
        $.each(response.items, function (i, obj) {
          if (obj.rel_type !== "") {
            if (obj.rel_type == "task") {
              $('input[name="task_id"]').val(
                obj.item_related_formatted_for_input
              );
            } else if (obj.rel_type == "expense") {
              $('input[name="expense_id"]').val(
                obj.item_related_formatted_for_input
              );
            }
          }
          _set_item_preview_custom_fields_array(obj.custom_fields);
          add_item_to_table(obj, "undefined", _id);
        });
      });
    } else {
      // Remove the appended invoice to merge
      $("body")
        .find('[data-merge-invoice="' + _id + '"]')
        .remove();
    }
  });

  // Bill expenses to invooice on top
  $("body").on("change", 'input[name="bill_expenses[]"]', function () {
    var checked = $(this).prop("checked");
    var _id = $(this).val();
    if (checked === true) {
      requestGetJSON("invoices/get_bill_expense_data/" + _id).done(function (
        response
      ) {
        $('input[name="expense_id"]').val(_id);
        add_item_to_table(response, "undefined", "undefined", _id);
      });
    } else {
      // Remove the appended expenses
      $("body")
        .find('[data-bill-expense="' + _id + '"]')
        .remove();
      $("body")
        .find('#billed-expenses input[value="' + _id + '"]')
        .remove();
    }
  });

  // Expense bill to popover data
  $("body").on(
    "change",
    ".invoice_inc_expense_additional_info input",
    function () {
      var _data_content = $(this).attr("data-content"),
        new_desc_value,
        desc_selector = $(
          "[data-bill-expense=" +
            $(this).attr("data-id") +
            "] .item_long_description"
        );
      current_desc_val = desc_selector.val();
      current_desc_val = current_desc_val.trim();
      if (_data_content !== "") {
        if ($(this).prop("checked") === true) {
          new_desc_value = current_desc_val + "\n" + _data_content;
          desc_selector.val(new_desc_value.trim());
        } else {
          desc_selector.val(current_desc_val.replace("\n" + _data_content, ""));
          // IN case there is no new line
          desc_selector.val(current_desc_val.replace(_data_content, ""));
        }
      }
    }
  );
});

// For manually modals where no close is defined
$(document).keyup(function (e) {
  if (e.keyCode == 27) {
    // escape key maps to keycode `27`

    if ($(".popup-wrapper").is(":visible")) {
      $(".popup-wrapper").find(".system-popup-close").click();
    }

    if ($("#search-history").is(":visible")) {
      $("#search-history").removeClass("display-block");
    }
  }
});

function _make_task_checklist_items_deletable() {
  if (app.options.has_permission_tasks_checklist_items_delete == "1") {
    var itemsHtml = $("body")
      .find(".checklist-templates-wrapper ul.dropdown-menu li")
      .not(":first-child");
    var itemsSelect = $("body")
      .find(".checklist-templates-wrapper select option")
      .not(":first-child");
    $.each(itemsSelect, function (i, item) {
      var $item = $(item);
      if (
        $(itemsHtml[i]).find(".checklist-item-template-remove").length === 0
      ) {
        $(itemsHtml[i])
          .find("a > span.text")
          .after(
            '<small class="checklist-item-template-remove" onclick="remove_checklist_item_template(' +
              $item.attr("value") +
              '); event.stopPropagation();"><i class="fa fa-remove"></i></small>'
          );
      }
    });
  }
}

function _init_tasks_billable_select(tasks, project_id) {
  var billable_tasks_area = $("#task_select");
  if (billable_tasks_area.length > 0) {
    var option_data;
    billable_tasks_area
      .find("option")
      .filter(function () {
        return (
          this.value ||
          $.trim(this.value).length > 0 ||
          $.trim(this.text).length > 0
        );
      })
      .remove();

    $.each(tasks, function (i, obj) {
      option_data = " ";
      if (obj.started_timers === true) {
        option_data +=
          'disabled class="text-danger" data-subtext="' +
          app.lang.invoice_task_billable_timers_found +
          '"';
      } else if (obj.started_timers === false && obj.rel_type != "project") {
        option_data += 'data-subtext="' + obj.rel_name + '"';
      }
      billable_tasks_area.append(
        '<option value="' +
          obj.id +
          '"' +
          option_data +
          ">" +
          obj.name +
          "</option>"
      );
    });

    var tasks_help_wrapper = $(".input-group-addon-bill-tasks-help");
    tasks_help_wrapper.find(".popover-invoker").popover("destroy");
    tasks_help_wrapper.empty();

    var help_tooltip = "";

    if (!empty(project_id)) {
      help_tooltip =
        app.lang["showing_billable_tasks_from_project"] +
        " " +
        $("#project_id option:selected").text().trim();
    } else {
      help_tooltip = app.lang["invoice_task_item_project_tasks_not_included"];
    }

    tasks_help_wrapper.html(
      '<span class="pointer popover-invoker" data-container=".form-group-select-task_select" data-trigger="click" data-placement="top" data-toggle="popover" data-content="' +
        help_tooltip +
        '"><i class="fa-regular fa-circle-question"></i></span>'
    );

    delay(function () {
      if (
        (tasks_help_wrapper.attr("info-shown-count") < 3 ||
          typeof tasks_help_wrapper.attr("info-shown-count") == "undefined") &&
        $(".projects-wrapper").is(":visible") &&
        tasks.length > 0
      ) {
        tasks_help_wrapper.attr(
          "info-shown-count",
          typeof tasks_help_wrapper.attr("info-shown-count") == "undefined"
            ? 1
            : parseInt(tasks_help_wrapper.attr("info-shown-count")) + 1
        );
        tasks_help_wrapper.find(".popover-invoker").click();
      }
    }, 3500);
  }

  billable_tasks_area.selectpicker("refresh");
}

// Fix for height on the wrapper
function mainWrapperHeightFix() {
  // Get and set current height
  var headerH = 57;
  var navigationH = side_bar.height();
  var contentH = $("#wrapper").find(".content").height();
  setup_menu.css(
    "min-height",
    $(document).outerHeight(true) - headerH * 2 + "px"
  );
  $("#menu").css("min-height", $(document).outerHeight(true) + "px");

  content_wrapper.css(
    "min-height",
    $(document).outerHeight(true) - headerH + "px"
  );
  content_wrapper.css("height", '100%')
  // Set new height when content height is less then navigation
  if (contentH < navigationH) {
    content_wrapper.css("min-height", navigationH + "px");
  }

  // Set new height when content height is less then navigation and navigation is less then window
  if (contentH < navigationH && navigationH < $(window).height()) {
    content_wrapper.css("min-height", $(window).height() - headerH + "px");
  }
  // Set new height when content is higher then navigation but less then window
  if (contentH > navigationH && contentH < $(window).height()) {
    content_wrapper.css("min-height", $(window).height() - headerH + "px");
  }
  // Fix for RTL main admin menu height
  if (is_mobile() && isRTL == "true") {
    side_bar.css("min-height", $(document).outerHeight(true) - headerH + "px");
  }
}

// Set body small based on device width
function set_body_small() {
  var isIpad = navigator.userAgent.match(/iPad/i) != null;

  if ($(this).width() < 769 || isIpad || is_mobile()) {
    $("body").addClass("page-small");
  } else {
    $("body").removeClass("page-small show-sidebar");
  }
}

// Switch field make request
function switch_field(field) {
  var status, url, id;
  status = 0;
  if ($(field).prop("checked") === true) {
    status = 1;
  }
  url = $(field).data("switch-url");
  id = $(field).data("id");
  requestGet(url + "/" + id + "/" + status);
}

// General validate form function
// This should not be used too, but it's added for readibility
// @deprecated 2.3.
function _validate_form(form, form_rules, submithandler, overwriteMessages) {
  appValidateForm(form, form_rules, submithandler, overwriteMessages);
}

// Delete option from database AJAX
// Not tested, do not use this function
// Not used?
function delete_option(child, id) {
  if (confirm_delete()) {
    requestGetJSON("settings/delete_option/" + id).done(function (response) {
      if (response.success === true || response.success == "true") {
        $(child).parents(".option").remove();
      }
    });
  }
}

// Initing relation tasks tables
function init_rel_tasks_table(rel_id, rel_type, selector) {
  if (typeof selector == "undefined") {
    selector = ".table-rel-tasks";
  }
  var $selector = $("body").find(selector);
  if ($selector.length === 0) {
    return;
  }

  var TasksServerParams = {},
    tasksRelationTableNotSortable = [0], // bulk actions
    TasksFilters;

  TasksFilters = $("body").find(
    "._hidden_inputs._filters._tasks_filters input"
  );

  $.each(TasksFilters, function () {
    TasksServerParams[$(this).attr("name")] =
      '[name="' + $(this).attr("name") + '"]';
  });

  // Related task filter - used in customer profile
  TasksServerParams['tasks_related_to'] = '[name="tasks_related_to"]'

  var url = admin_url + "tasks/init_relation_tasks/" + rel_id + "/" + rel_type;

  if ($selector.attr("data-new-rel-type") == "project") {
    url += "?bulk_actions=true";
  }

  initDataTable(
    $selector,
    url,
    tasksRelationTableNotSortable,
    tasksRelationTableNotSortable,
    TasksServerParams,
    [$selector.find("th.duedate").index(), "asc"]
  );
}

// Datatbles inline/offline - no serverside
function initDataTableInline(dt_table) {
  appDataTableInline(dt_table, {
    supportsButtons: true,
    supportsLoading: true,
    autoWidth: false,
  });
}

// General function for all datatables serverside
function initDataTable(
  selector,
  url,
  notsearchable,
  notsortable,
  fnserverparams,
  defaultorder
) {
  var table =
    typeof selector == "string" ? $("body").find("table" + selector) : selector;

  if (table.length === 0) {
    return false;
  }

  fnserverparams =
    fnserverparams == "undefined" || typeof fnserverparams == "undefined"
      ? []
      : fnserverparams;

  // If not order is passed order by the first column
  if (typeof defaultorder == "undefined") {
    defaultorder = [[0, "asc"]];
  } else {
    if (defaultorder.length === 1) {
      defaultorder = [defaultorder];
    }
  }

  var user_table_default_order = table.attr("data-default-order");

  if (!empty(user_table_default_order)) {
    var tmp_new_default_order = JSON.parse(user_table_default_order);
    var new_defaultorder = [];
    for (var i in tmp_new_default_order) {
      // If the order index do not exists will throw errors
      if (
        table.find("thead th:eq(" + tmp_new_default_order[i][0] + ")").length >
        0
      ) {
        new_defaultorder.push(tmp_new_default_order[i]);
      }
    }
    if (new_defaultorder.length > 0) {
      defaultorder = new_defaultorder;
    }
  }

  var length_options = [10, 25, 50, 100];
  var length_options_names = [10, 25, 50, 100];

  app.options.tables_pagination_limit = parseFloat(
    app.options.tables_pagination_limit
  );

  if ($.inArray(app.options.tables_pagination_limit, length_options) == -1) {
    length_options.push(app.options.tables_pagination_limit);
    length_options_names.push(app.options.tables_pagination_limit);
  }

  length_options.sort(function (a, b) {
    return a - b;
  });
  length_options_names.sort(function (a, b) {
    return a - b;
  });

  length_options.push(-1);
  length_options_names.push(app.lang.dt_length_menu_all);

  var dtSettings = {
    language: app.lang.datatables,
    processing: true,
    retrieve: true,
    serverSide: true,
    paginate: true,
    searchDelay: 750,
    bDeferRender: true,
    autoWidth: false,
    dom: "<'row'><'row'<'col-md-7'lB><'col-md-5'f>>rt<'row'<'col-md-4'i><'col-md-8 dataTables_paging'<'#colvis'><'.dt-page-jump'>p>>",
    pageLength: app.options.tables_pagination_limit,
    lengthMenu: [length_options, length_options_names],
    columnDefs: [
      {
        searchable: false,
        targets: notsearchable,
      },
      {
        sortable: false,
        targets: notsortable,
      },
    ],
    fnDrawCallback: function (oSettings) {
      _table_jump_to_page(this, oSettings);
      if (oSettings.aoData.length === 0) {
        $(oSettings.nTableWrapper).addClass("app_dt_empty");
      } else {
        $(oSettings.nTableWrapper).removeClass("app_dt_empty");
      }
    },
    fnCreatedRow: function (nRow, aData, iDataIndex) {
      // If tooltips found
      $(nRow).attr("data-title", aData.Data_Title);
      $(nRow).attr("data-toggle", aData.Data_Toggle);
    },
    initComplete: function (settings, json) {
      var t = this;
      var $btnReload = $(".btn-dt-reload");
      $btnReload.attr("data-toggle", "tooltip");
      $btnReload.attr("title", app.lang.dt_button_reload);

      var $btnColVis = $(".dt-column-visibility");
      $btnColVis.attr("data-toggle", "tooltip");
      $btnColVis.attr("title", app.lang.dt_button_column_visibility);

      t.wrap('<div class="table-responsive"></div>');

      var dtEmpty = t.find(".dataTables_empty");
      if (dtEmpty.length) {
        dtEmpty.attr("colspan", t.find("thead th").length);
      }

      // Hide mass selection because causing issue on small devices
      if (
        is_mobile() &&
        $(window).width() < 400 &&
        t.find('tbody td:first-child input[type="checkbox"]').length > 0
      ) {
        t.DataTable().column(0).visible(false, false).columns.adjust();
        $("a[data-target*='bulk_actions']").addClass("hide");
      }

      t.parents(".table-loading").removeClass("table-loading");
      t.removeClass("dt-table-loading");
      var th_last_child = t.find("thead th:last-child");
      var th_first_child = t.find("thead th:first-child");
      if (th_last_child.text().trim() == app.lang.options) {
        th_last_child.addClass("not-export");
      }
      if (th_first_child.find('input[type="checkbox"]').length > 0) {
        th_first_child.addClass("not-export");
      }
      mainWrapperHeightFix();
    },
    order: defaultorder,
    ajax: {
      url: url,
      type: "POST",
      data: function (d) {
        if (Array.isArray(d.order)) {

          d.order = d.order.map(function (order) {
            var tHead = table.find("thead th:eq(" + order.column + ")");
            if (tHead.length > 0) {
              if (tHead[0].dataset.customField == 1) {
                order.type = tHead[0].dataset.type;
              }
            }
            return order;
          });
        }

        if (typeof csrfData !== "undefined") {
          d[csrfData["token_name"]] = csrfData["hash"];
        }

        for (var key in fnserverparams) {
          d[key] = $(fnserverparams[key]).val();
        }

        if (table.attr("data-last-order-identifier")) {
          d["last_order_identifier"] = table.attr("data-last-order-identifier");
        }

        var tId = table[0].getAttribute('id');

        if(tId && Object.hasOwn(app.dtFilters, tId)) {
          d['filters'] = app.dtFilters[tId]
        }
      },
    },
    buttons: get_datatable_buttons(table),
  };

  table = table.dataTable(dtSettings);
  var tableApi = table.DataTable();

  var hiddenHeadings = table.find("th.not_visible");
  var hiddenIndexes = [];

  $.each(hiddenHeadings, function () {
    hiddenIndexes.push(this.cellIndex);
  });

  setTimeout(function () {
    for (var i in hiddenIndexes) {
      tableApi.columns(hiddenIndexes[i]).visible(false, false).columns.adjust();
    }
  }, 10);

  if (table.hasClass("customizable-table")) {
    var tableToggleAbleHeadings = table.find("th.toggleable");
    var invisible = $("#hidden-columns-" + table.attr("id"));
    try {
      invisible = JSON.parse(invisible.text());
    } catch (err) {
      invisible = [];
    }

    $.each(tableToggleAbleHeadings, function () {
      var cID = $(this).attr("id");
      if ($.inArray(cID, invisible) > -1) {
        tableApi.column("#" + cID).visible(false);
      }
    });

    // For for not blurring out when clicked on the link
    // Causing issues hidden column still to be shown as not hidden because the link is focused
    /* $('body').on('click', '.buttons-columnVisibility a', function() {
             $(this).blur();
         });*/
    /*
                table.on('column-visibility.dt', function(e, settings, column, state) {
                    var hidden = [];
                    $.each(tableApi.columns()[0], function() {
                        var visible = tableApi.column($(this)).visible();
                        var columnHeader = $(tableApi.column($(this)).header());
                        if (columnHeader.hasClass('toggleable')) {
                            if (!visible) {
                                hidden.push(columnHeader.attr('id'))
                            }
                        }
                    });
                    var data = {};
                    data.id = table.attr('id');
                    data.hidden = hidden;
                    if (data.id) {
                        $.post(admin_url + 'staff/save_hidden_table_columns', data).fail(function(data) {
                            // Demo usage, prevent multiple alerts
                            if ($('body').find('.float-alert').length === 0) {
                                alert_float('danger', data.responseText);
                            }
                        });
                    } else {
                        console.error('Table that have ability to show/hide columns must have an ID');
                    }
                });*/
  }

  // Fix for hidden tables colspan not correct if the table is empty
  if (table.is(":hidden")) {
    table
      .find(".dataTables_empty")
      .attr("colspan", table.find("thead th").length);
  }

  table.on("preXhr.dt", function (e, settings, data) {
    if (settings.jqXHR) settings.jqXHR.abort();
  });

  return tableApi;
}

// Update tags in task single modal
function task_single_update_tags() {
  var taskTags = $("#taskTags");
  $.post(admin_url + "tasks/update_tags", {
    tags: taskTags.tagit("assignedTags"),
    task_id: taskTags.attr("data-taskid"),
  });
}

// By default only 2 attachments for tasks are shown the other are hidden and there is button show more, this will show all the attachments
function task_attachments_toggle() {
  var $taskModal = $("#task-modal");
  $taskModal
    .find(".task_attachments_wrapper .task-attachments-more")
    .toggleClass("hide");
  $taskModal
    .find(".task_attachments_wrapper .task-attachments-less")
    .toggleClass("hide");
}

// Update todo items when drop happen
function update_todo_items() {
  var unfinished_items = $(".unfinished-todos li:not(.no-todos)");
  var finished = $(".finished-todos li:not(.no-todos)");
  var i = 1;
  // Refresh orders
  $.each(unfinished_items, function () {
    $(this).find('input[name="todo_order"]').val(i);
    $(this).find('input[name="finished"]').val(0);
    i++;
  });
  if (unfinished_items.length === 0) {
    $(".nav-total-todos").addClass("hide");
    $(".unfinished-todos li.no-todos").removeClass("hide");
  } else if (unfinished_items.length > 0) {
    if (!$(".unfinished-todos li.no-todos").hasClass("hide")) {
      $(".unfinished-todos li.no-todos").addClass("hide");
    }
    $(".nav-total-todos").removeClass("hide").html(unfinished_items.length);
  }
  x = 1;
  $.each(finished, function () {
    $(this).find('input[name="todo_order"]').val(x);
    $(this).find('input[name="finished"]').val(1);
    $(this).find('input[type="checkbox"]').prop("checked", true);
    i++;
    x++;
  });
  if (finished.length === 0) {
    $(".finished-todos li.no-todos").removeClass("hide");
  } else if (finished.length > 0) {
    if (!$(".finished-todos li.no-todos").hasClass("hide")) {
      $(".finished-todos li.no-todos").addClass("hide");
    }
  }
  var update = [];
  $.each(unfinished_items, function () {
    var description = $(this).find(".todo-description");
    if (description.hasClass("line-throught")) {
      description.removeClass("line-throught");
    }
    $(this).find('input[type="checkbox"]').prop("checked", false);
    update.push([
      $(this).find('input[name="todo_id"]').val(),
      $(this).find('input[name="todo_order"]').val(),
      $(this).find('input[name="finished"]').val(),
    ]);
  });
  $.each(finished, function () {
    var description = $(this).find(".todo-description");
    if (!description.hasClass("line-throught")) {
      description.addClass("line-throught");
    }
    update.push([
      $(this).find('input[name="todo_id"]').val(),
      $(this).find('input[name="todo_order"]').val(),
      $(this).find('input[name="finished"]').val(),
    ]);
  });
  data = {};
  data.data = update;
  $.post(admin_url + "todo/update_todo_items_order", data);
}

// Delete single todo item
function delete_todo_item(list, id) {
  requestGetJSON("todo/delete_todo_item/" + id).done(function (response) {
    if (response.success === true || response.success == "true") {
      $(list).parents("li").remove();
      update_todo_items();
    }
  });
}

// Edit todo item
function edit_todo_item(id) {
  requestGetJSON("todo/get_by_id/" + id).done(function (response) {
    var todo_modal = $("#__todo");
    todo_modal.find('input[name="todoid"]').val(response.todoid);
    todo_modal.find('textarea[name="description"]').val(response.description);
    todo_modal.modal("show");
  });
}

// Date picker init with selected timeformat from settings
function init_datepicker(element_date, element_time) {
  appDatepicker({
    element_date: element_date,
    element_time: element_time,
  });
}

// Init color pickers
function init_color_pickers() {
  appColorPicker();
}

// Init select picker
function init_selectpicker() {
  appSelectPicker();
}

// Init light box
function init_lightbox() {
  appLightbox();
}

// Init progress bars
function init_progress_bars() {
  appProgressBar();
}

// All inputs used for tags
function init_tags_inputs() {
  appTagsInput();
}

// Datatables custom view will fill input with the value
function dt_custom_view(value, table, custom_input_name, clear_other_filters) {
  var name =
    typeof custom_input_name == "undefined" ? "custom_view" : custom_input_name;
  if (typeof clear_other_filters != "undefined") {
    var filters = $("._filter_data li.active").not(".clear-all-prevent");
    filters.removeClass("active");
    $.each(filters, function () {
      var input_name = $(this).find("a").attr("data-cview");
      $('._filters input[name="' + input_name + '"]').val("");
    });
  }
  var _cinput = do_filter_active(name);
  if (_cinput != name) {
    value = "";
  }
  $('input[name="' + name + '"]').val(value);
  $(table).DataTable().ajax.reload();
}

// Sets table filters dropdown to active
function do_filter_active(value, parent_selector) {
  if (value !== "" && typeof value != "undefined") {
    $('[data-cview="all"]').parents("li").removeClass("active");
    var selector = $('[data-cview="' + value + '"]');
    if (typeof parent_selector != "undefined") {
      selector = $(parent_selector + ' [data-cview="' + value + '"]');
    }
    var parent = selector.parents("li");
    if (parent.hasClass("filter-group")) {
      var group = parent.data("filter-group");
      $('[data-filter-group="' + group + '"]')
        .not(parent)
        .removeClass("active");
      $.each($('[data-filter-group="' + group + '"]').not(parent), function () {
        $('input[name="' + $(this).find("a").attr("data-cview") + '"]').val("");
      });
      //   $('input[name="' + value + '"]').val('');
    }
    if (!parent.not(".dropdown-submenu").hasClass("active")) {
      parent.addClass("active");
    } else {
      parent.not(".dropdown-submenu").removeClass("active");
      parent.find("a").blur();
      // Remove active class from the parent dropdown if nothing selected in the child dropdown
      var parents_sub = selector.parents("li.dropdown-submenu");
      if (parents_sub.length > 0) {
        if (parents_sub.find("li.active").length === 0) {
          parents_sub.removeClass("active");
        }
      }
      value = "";
    }
    return value;
  } else {
    $("._filters input").val("");
    $("._filter_data li.active").removeClass("active");
    $('[data-cview="all"]').parents("li").addClass("active");
    return "";
  }
}

// Called when editing member profile
function init_roles_permissions(roleid, user_changed) {
  roleid =
    typeof roleid == "undefined" ? $('select[name="role"]').val() : roleid;
  var isedit = $('.member > input[name="isedit"]');

  // Check if user is edit view and user has changed the dropdown permission if not only return
  if (
    isedit.length > 0 &&
    typeof roleid !== "undefined" &&
    typeof user_changed == "undefined"
  ) {
    return;
  }

  // Administrators does not have permissions
  if ($('input[name="administrator"]').prop("checked") === true) {
    return;
  }

  // Last if the roleid is blank return
  if (roleid === "") {
    return;
  }

  // Get all permissions
  var permissions = $("table.roles").find("tr");
  requestGetJSON("staff/role_changed/" + roleid).done(function (response) {
    permissions
      .find(".capability")
      .not('[data-not-applicable="true"]')
      .prop("checked", false)
      .trigger("change");

    $.each(permissions, function () {
      var row = $(this);
      $.each(response, function (feature, obj) {
        if (row.data("name") == feature) {
          $.each(obj, function (i, capability) {
            row
              .find('input[id="' + feature + "_" + capability + '"]')
              .prop("checked", true);
            if (capability == "view") {
              row.find("[data-can-view]").change();
            } else if (capability == "view_own") {
              row.find("[data-can-view-own]").change();
            }
          });
        }
      });
    });
  });
}

// Show/hide full table
function toggle_small_view(table, main_data) {
  if (
    !is_mobile() &&
    $("#small-table").hasClass("hide") &&
    $(".small-table-right-col").hasClass("col-md-12")
  ) {
    $("#small-table").toggleClass("hide");
    $(".small-table-right-col").toggleClass("col-md-12 col-md-7");
    $(window).trigger("resize");
    return;
  }
  $("body").toggleClass("small-table");
  var tablewrap = $("#small-table");
  if (tablewrap.length === 0) {
    return;
  }
  var _visible = false;
  if (tablewrap.hasClass("col-md-5")) {
    tablewrap.removeClass("col-md-5").addClass("col-md-12");
    _visible = true;
    $(".toggle-small-view")
      .find("i")
      .removeClass("fa fa-angle-double-right")
      .addClass("fa fa-angle-double-left");
  } else {
    tablewrap.addClass("col-md-5").removeClass("col-md-12");
    $(".toggle-small-view")
      .find("i")
      .removeClass("fa fa-angle-double-left")
      .addClass("fa fa-angle-double-right");
  }
  var _table = $(table).DataTable();
  // Show hide hidden columns
  _table.columns(hidden_columns).visible(_visible, false);
  _table.columns.adjust();
  $(main_data).toggleClass("hide");
  $(window).trigger("resize");
}

// Main logout function check if timers found to show the warning
function logout() {
  var started_timers = $(".started-timers-top").find("li.timer").length;
  if (started_timers > 0) {
    var warning = $("#timers-logout-template-warning").html();
    var $p = system_popup({
      message: " ",
      content: warning,
    });
    $p.find(".popup-message").addClass("hide");
    return false;
  } else {
    // No timer logout free
    window.location.href = admin_url + "authentication/logout";
  }
}

// Init the media elfinder for tinymce browser
function elFinderBrowser(callback, value, meta) {
  tinymce.activeEditor.windowManager.elfinderCallback = callback
  
  tinymce.activeEditor.windowManager.openUrl({
      url: admin_url + "misc/tinymce_file_browser",
      title: app.lang.media_files,
      width: 900,
      height: 450,
  });
  
  return false;
}

// Function to init the tinymce editor
function init_editor(selector, settings) {
  selector = typeof selector == "undefined" ? ".tinymce" : selector;
  var _editor_selector_check = $(selector);

  if (_editor_selector_check.length === 0) {
    return;
  }

  $.each(_editor_selector_check, function () {
    if ($(this).hasClass("tinymce-manual")) {
      $(this).removeClass("tinymce");
    }
  });

  // Original settings
  var _settings = {
    branding: false,
    promotion: false,
    selector: selector,
    browser_spellcheck: true,
    cache_suffix: '?v='+app.version,
    height: 250,
    min_height: 250,
    statusbar: false,
    theme: "silver",
    paste_block_drop: true,
    language: app.tinymce_lang || 'en',
    relative_urls: false,
    entity_encoding: "raw",
    autoresize_bottom_margin: 25,
    valid_elements: "+*[*]",
    valid_children: "+body[style], +style[type]",
    remove_script_host: false,
    removed_menuitems: "newdocument restoredraft",
    forced_root_block: "p",
    autosave_restore_when_empty: false,
    font_size_formats: "8pt 10pt 12pt 14pt 18pt 24pt 36pt",
    table_default_styles: {
      width: "100%",
    },
    plugins: [
      "advlist", "autoresize", "autosave", "lists", "link", "image", "codesample",
      "visualblocks", "code", "fullscreen",
      "media", "save", "table",
    ],
    toolbar: "fontfamily fontsize | forecolor backcolor | bold italic | alignleft aligncenter alignright alignjustify | image link | bullist numlist | restoredraft",
    contextmenu: "link image | paste copy",
    file_picker_callback : elFinderBrowser,
    setup: function (ed) {
      // Default fontsize is 12
      ed.on("init", function () {
        this.getDoc().body.style.fontSize = "12pt";
      });
    },
  };

  // Add the rtl to the settings if is true
  if(isRTL == "true") {
    _settings.directionality = "rtl"
    _settings.plugins.push('directionality')
  }

  // Possible settings passed to be overwrited or added
  if (typeof settings != "undefined") {
    for (var key in settings) {
      if (key != "append_plugins") {
        _settings[key] = settings[key];
      } else {
        _settings.plugins.push(settings[key]);
      }
    }
  }

  // Init the editor
  var editor = tinymce.init(_settings);

  $(document).trigger("app.editor.initialized");

  return editor;
}

// Function used to add custom bootstrap menu for setup and main menu and to add fa on front like fa fa-question
function _formatMenuIconInput(e) {
  if (typeof e == "undefined") {
    return;
  }
  var _input = $(e.target);
  if (!_input.val().match(/^fa /)) {
    _input.val("fa " + _input.val());
  }
}

// This is used for mobile where tooltip on _buttons class wrapper is found
// Will show all buttons tooltips as regular button with text
function init_btn_with_tooltips() {
  if (is_mobile()) {
    var is_iPad = navigator.userAgent.match(/iPad/i) != null;
    if (is_iPad) {
      return false;
    }
    var tooltips_href_btn = $("._buttons").find(".btn-with-tooltip");
    $.each(tooltips_href_btn, function () {
      var title = $(this).attr("title");
      if (typeof title == "undefined") {
        title = $(this).attr("data-title");
      }
      if (typeof title != "undefined") {
        $(this).append(" " + title);
        $(this).removeClass("btn-with-tooltip");
      }
    });
    var tooltips_group = $("._buttons").find(".btn-with-tooltip-group");
    $.each(tooltips_group, function () {
      var title = $(this).attr("title");
      if (typeof title == "undefined") {
        title = $(this).attr("data-title");
      }
      if (typeof title != "undefined") {
        $(this)
          .find(".btn")
          .eq(0)
          .append(" " + title);
        $(this).removeClass("btn-with-tooltip-group");
      }
    });
  }
}

// Helper hash id for estimates,invoices,proposals,expenses, credit notes
function do_hash_helper(hash) {
  if (typeof history.pushState != "undefined") {
    var url = window.location.href;
    var obj = {
      Url: url,
    };
    history.pushState(obj, "", obj.Url);
    window.location.hash = hash;
  }
}

// Validate the form reminder
function init_form_reminder(rel_type) {
  var forms = !rel_type
    ? $('[id^="form-reminder-"]')
    : $("#form-reminder-" + rel_type);

  $.each(forms, function (i, form) {
    $(form).appFormValidator({
      rules: {
        date: "required",
        staff: "required",
        description: "required",
      },
      submitHandler: reminderFormHandler,
    });
  });
}

// New task reminder custom function
function new_task_reminder(id) {
  var $container = $("#newTaskReminderToggle");
  if (
    !$container.is(":visible") ||
    ($container.is(":visible") && $container.attr("data-edit") != undefined)
  ) {
    $container.slideDown(400, function () {
      fix_task_modal_left_col_height();
    });

    $("#taskReminderFormSubmit").html(app.lang.create_reminder);
    $container
      .find("form")
      .attr("action", admin_url + "tasks/add_reminder/" + id);

    $container.find("#description").val("");
    $container.find("#date").val("");
    $container
      .find("#staff")
      .selectpicker(
        "val",
        $container.find("#staff").attr("data-current-staff")
      );
    $container.find("#notify_by_email").prop("checked", false);
    if ($container.attr("data-edit") != undefined) {
      $container.removeAttr("data-edit");
    }
    if (!$container.isInViewport()) {
      $("#task-modal").animate(
        {
          scrollTop: $container.offset().top + "px",
        },
        "fast"
      );
    }
  } else {
    $container.slideUp();
  }
}

// Edit reminder function
function edit_reminder(id, e) {
  requestGetJSON("misc/get_reminder/" + id).done(function (response) {
    var $container = $(
      ".reminder-modal-" + response.rel_type + "-" + response.rel_id
    );
    var actionURL = admin_url + "misc/edit_reminder/" + id;
    if ($container.length === 0 && $("body").hasClass("all-reminders")) {
      // maybe from view all reminders?
      $container = $(".reminder-modal--");
      $container.find('input[name="rel_type"]').val(response.rel_type);
      $container.find('input[name="rel_id"]').val(response.rel_id);
    } else if ($("#task-modal").is(":visible")) {
      $container = $("#newTaskReminderToggle");

      if ($container.attr("data-edit") && $container.attr("data-edit") == id) {
        $container.slideUp();
        $container.removeAttr("data-edit");
      } else {
        $container.slideDown(400, function () {
          fix_task_modal_left_col_height();
        });
        $container.attr("data-edit", id);
        if (!$container.isInViewport()) {
          $("#task-modal").animate(
            {
              scrollTop: $container.offset().top + "px",
            },
            "fast"
          );
        }
      }
      actionURL = admin_url + "tasks/edit_reminder/" + id;
      $("#taskReminderFormSubmit").html(app.lang.save);
    }

    $container.find("form").attr("action", actionURL);
    // For focusing the date field
    $container.find("form").attr("data-edit", true);
    $container.find("#description").val(response.description);
    $container.find("#date").val(response.date);
    $container.find("#staff").selectpicker("val", response.staff);
    $container
      .find("#notify_by_email")
      .prop("checked", response.notify_by_email == 1 ? true : false);
    if ($container.hasClass("modal")) {
      $container.modal("show");
    }
  });
}

// Handles reminder modal form
function reminderFormHandler(form) {
  form = $(form);
  var data = form.serialize();
  $.post(form.attr("action"), data).done(function (data) {
    data = JSON.parse(data);
    if (data.message !== "") {
      alert_float(data.alert_type, data.message);
    }
    form.trigger("reinitialize.areYouSure");
    if ($("#task-modal").is(":visible")) {
      _task_append_html(data.taskHtml);
    }
    reload_reminders_tables();
  });

  if ($("body").hasClass("all-reminders")) {
    $(".reminder-modal--").modal("hide");
  } else {
    $(
      ".reminder-modal-" +
        form.find('[name="rel_type"]').val() +
        "-" +
        form.find('[name="rel_id"]').val()
    ).modal("hide");
  }

  return false;
}

// Reloads reminders table eq when reminder is deleted
function reload_reminders_tables() {
  var available_reminders_table = [
    ".table-reminders",
    ".table-reminders-leads",
    ".table-my-reminders",
  ];

  $.each(available_reminders_table, function (i, table) {
    if ($.fn.DataTable.isDataTable(table)) {
      $("body").find(table).DataTable().ajax.reload();
    }
  });
}

/* Global function for editing notes */
function toggle_edit_note(id) {
  $("body")
    .find('[data-note-edit-textarea="' + id + '"]')
    .toggleClass("hide");
  $("body")
    .find('[data-note-description="' + id + '"]')
    .toggleClass("hide");
}

// Global function to edit note
function edit_note(id) {
  var description = $("body")
    .find('[data-note-edit-textarea="' + id + '"] textarea')
    .val();
  if (description !== "") {
    $.post(admin_url + "misc/edit_note/" + id, {
      description: description,
    }).done(function (response) {
      response = JSON.parse(response);
      if (response.success === true || response.success == "true") {
        alert_float("success", response.message);
        $("body")
          .find('[data-note-description="' + id + '"]')
          .html(response.description);
      }
    });
    toggle_edit_note(id);
  }
}

// Toggles sales file visibility for customer eq for invoices, estimates, proposals
function toggle_file_visibility(attachment_id, rel_id, invoker) {
  requestGet("misc/toggle_file_visibility/" + attachment_id).done(function (
    response
  ) {
    if (response == 1) {
      $(invoker)
        .find("i")
        .removeClass("fa fa-toggle-off")
        .addClass("fa fa-toggle-on");
    } else {
      $(invoker)
        .find("i")
        .removeClass("fa fa-toggle-on")
        .addClass("fa fa-toggle-off");
    }
  });
}

// Fixes kanban height to be compatible with content and screen height
function fix_kanban_height(col_px, container_px) {
  // Set the width of the kanban container
  $("body").find("div.dt-loader").remove();
  var kanbanCol = $(".kan-ban-content-wrapper");
  kanbanCol.css("max-height", window.innerHeight - col_px + "px");
  $(".kan-ban-content").css("min-height", window.innerHeight - col_px + "px");
  var kanbanColCount = parseInt(kanbanCol.length);
  $(".container-fluid").css("min-width", kanbanColCount * container_px + "px");
}

// Kanban load more
function kanban_load_more(status_id, e, url, column_px, container_px) {
  var LoadMoreParameters = [];
  var search = $('input[name="search"]').val();
  var _kanban_param_val;
  var page = $(e).attr("data-page");
  var $column = $('[data-col-status-id="' + status_id + '"]');
  var total_pages = $column.data("total-pages");

  if (page <= total_pages) {
    var sort_type = $('input[name="sort_type"]');
    var sort = $('input[name="sort"]').val();
    if (sort_type.length != 0 && sort_type.val() !== "") {
      LoadMoreParameters["sort_by"] = sort_type.val();
      LoadMoreParameters["sort"] = sort;
    }

    if (typeof search != "undefined" && search !== "") {
      LoadMoreParameters["search"] = search;
    }

    $.each($("#kanban-params input"), function () {
      if ($(this).attr("type") == "checkbox") {
        _kanban_param_val =
          $(this).prop("checked") === true ? $(this).val() : "";
      } else {
        _kanban_param_val = $(this).val();
      }
      if (_kanban_param_val !== "") {
        LoadMoreParameters[$(this).attr("name")] = _kanban_param_val;
      }
    });

    LoadMoreParameters["status"] = status_id;
    LoadMoreParameters["page"] = page;
    LoadMoreParameters["page"]++;
    requestGet(buildUrl(admin_url + url, LoadMoreParameters))
      .done(function (response) {
        page++;
        $('[data-load-status="' + status_id + '"]').before(response);
        $('[data-col-status-id="' + status_id + '"]').attr(
          "data-total",
          parseInt(
            $('[data-col-status-id="' + status_id + '"]').attr("data-total")
          ) + $("<ul></ul>").append(response).find("li").length
        );
        $(e).attr("data-page", page);
        fix_kanban_height(column_px, container_px);
      })
      .fail(function (error) {
        alert_float("danger", error.responseText);
      });
    if (page >= total_pages - 1) {
      $(e).addClass("disabled");
    }
  }
}

// Check if kanban col is empty and perform necessary actions
function check_kanban_empty_col(selector) {
  var statuses = $("[data-col-status-id]");
  $.each(statuses, function (i, obj) {
    var total = $(obj).find(selector).length;
    if (total == 0) {
      $(obj).find(".kanban-empty").removeClass("hide");
      $(obj).find(".kanban-load-more").addClass("hide");
    } else {
      $(obj).find(".kanban-empty").addClass("hide");
    }
  });
}

// General function to init kan ban based on settings
function init_kanban(
  url,
  callbackUpdate,
  connect_with,
  column_px,
  container_px,
  callback_after_load
) {
  if ($("#kan-ban").length === 0) {
    return;
  }

  var parameters = [];
  var _kanban_param_val;

  $.each($("#kanban-params input"), function () {
    if ($(this).attr("type") == "checkbox") {
      _kanban_param_val = $(this).prop("checked") === true ? $(this).val() : "";
    } else {
      _kanban_param_val = $(this).val();
    }
    if (_kanban_param_val !== "") {
      parameters[$(this).attr("name")] = _kanban_param_val;
    }
  });

  var search = $('input[name="search"]').val();
  if (typeof search != "undefined" && search !== "") {
    parameters["search"] = search;
  }

  var sort_type = $('input[name="sort_type"]');
  var sort = $('input[name="sort"]').val();
  if (sort_type.length != 0 && sort_type.val() !== "") {
    parameters["sort_by"] = sort_type.val();
    parameters["sort"] = sort;
  }

  parameters["kanban"] = true;

  url = admin_url + url;
  url = buildUrl(url, parameters);
  var $kanBanCols = $(".kan-ban-col");
  if ($kanBanCols.length > 0) {
    var refreshParams = [];
    $kanBanCols.each(function (index, col) {
      refreshParams.push({
        status: $(col).data("col-status-id"),
        total: parseInt($(col).attr("data-total")),
      });
    });
    url +=
      "&" +
      refreshParams
        .map(function (el, idx) {
          return "refresh[" + el.status + "]=" + el.total;
        })
        .join("&");
  }

  delay(function () {
    $("body").append('<div class="dt-loader"></div>');
    $("#kan-ban").load(url, function () {
      fix_kanban_height(column_px, container_px);
      var scrollingSensitivity = 20,
        scrollingSpeed = 60;

      if (typeof callback_after_load != "undefined") {
        callback_after_load();
      }

      $(".status").sortable({
        connectWith: connect_with,
        helper: "clone",
        appendTo: "#kan-ban",
        placeholder: "ui-state-highlight-card",
        revert: "invalid",
        scrollingSensitivity: 50,
        scrollingSpeed: 70,
        sort: function (event, uiHash) {
          var scrollContainer = uiHash.placeholder[0].parentNode;
          // Get the scrolling parent container
          scrollContainer = $(scrollContainer).parents(
            ".kan-ban-content-wrapper"
          )[0];
          var overflowOffset = $(scrollContainer).offset();
          if (
            overflowOffset.top + scrollContainer.offsetHeight - event.pageY <
            scrollingSensitivity
          ) {
            scrollContainer.scrollTop =
              scrollContainer.scrollTop + scrollingSpeed;
          } else if (event.pageY - overflowOffset.top < scrollingSensitivity) {
            scrollContainer.scrollTop =
              scrollContainer.scrollTop - scrollingSpeed;
          }
          if (
            overflowOffset.left + scrollContainer.offsetWidth - event.pageX <
            scrollingSensitivity
          ) {
            scrollContainer.scrollLeft =
              scrollContainer.scrollLeft + scrollingSpeed;
          } else if (event.pageX - overflowOffset.left < scrollingSensitivity) {
            scrollContainer.scrollLeft =
              scrollContainer.scrollLeft - scrollingSpeed;
          }
        },
        change: function () {
          var list = $(this).closest("ul");
          var KanbanLoadMore = $(list).find(".kanban-load-more");
          $(list).append($(KanbanLoadMore).detach());
        },
        start: function (event, ui) {
          $("body").css("overflow", "hidden");

          $(ui.helper).addClass("tilt");
          $(ui.helper).find(".panel-body").css("background", "#fbfbfb");
          // Start monitoring tilt direction
          tilt_direction($(ui.helper));
        },
        stop: function (event, ui) {
          $("body").removeAttr("style");
          $(ui.helper).removeClass("tilt");
          // Unbind temporary handlers and excess data
          $("html").off("mousemove", $(ui.helper).data("move_handler"));
          $(ui.helper).removeData("move_handler");
        },
        update: function (event, ui) {
          callbackUpdate(ui, this);
        },
      });

      $(".status").sortable({
        cancel: ".not-sortable",
      });
    });
  }, 200);
}

function kan_ban_sort(type, callback) {
  var sort_type = $('input[name="sort_type"]');
  sort_type.val(type);
  var sort = $('input[name="sort"]');
  var val = sort.val().toLowerCase();
  sort.val(val == "asc" ? "DESC" : "ASC");
  init_kan_ban_sort_icon(sort.val(), type);
  callback();
}

function init_kan_ban_sort_icon(sort, type) {
  $("body").find(".kanban-sort-icon").remove();
  $("body")
    .find("." + type)
    .prepend(
      " <i class='kanban-sort-icon fa fa-sort-amount-" +
        sort.toLowerCase() +
        "'></i>"
    );
}

// When window scroll to down load more posts
$("#newsfeed").scroll(function (e) {
  var elem = $(e.currentTarget);
  if (elem[0].scrollHeight - elem.scrollTop() == elem.outerHeight()) {
    load_newsfeed();
  }
  $("#newsfeed .close_newsfeed").css("top", $(this).scrollTop() + 20 + "px");
});

// Newsfeed form after newfeed href is clicked
function init_newsfeed_form() {
  // Configure dropzone
  if (typeof newsFeedDropzone == "undefined") {
    // Init new post form
    $("body").on("submit", "#new-post-form", function () {
      $.post(this.action, $(this).serialize()).done(function (response) {
        response = JSON.parse(response);
        if (response.postid) {
          if (newsFeedDropzone.getQueuedFiles().length > 0) {
            newsFeedDropzone.options.url =
              admin_url + "newsfeed/add_post_attachments/" + response.postid;
            newsFeedDropzone.processQueue();
            return;
          }
          newsfeed_new_post(response.postid);
          clear_newsfeed_post_area();
        }
      });
      return false;
    });
  }

  newsFeedDropzone = new Dropzone(
    "#new-post-form",
    appCreateDropzoneOptions({
      clickable: ".add-post-attachments",
      autoProcessQueue: false,
      addRemoveLinks: true,
      parallelUploads: app.options.newsfeed_maximum_files_upload,
      maxFiles: app.options.newsfeed_maximum_files_upload,
      dragover: function (file) {
        $("#new-post-form").addClass("dropzone-active");
      },
      complete: function (file) {},
      drop: function (file) {
        $("#new-post-form").removeClass("dropzone-active");
      },
      success: function (files, response) {
        if (
          this.getUploadingFiles().length === 0 &&
          this.getQueuedFiles().length === 0
        ) {
          response = JSON.parse(response);
          newsfeed_new_post(response.postid);
          clear_newsfeed_post_area();
          this.removeAllFiles();
        }
      },
    })
  );
}

// Clear newsfeed new post area
function clear_newsfeed_post_area() {
  $("#new-post-form textarea").val("");
  $("#post-visibility").selectpicker("deselectAll");
}

// Load post likes modal
function load_post_likes(postid) {
  if (track_load_post_likes <= post_likes_total_pages) {
    $.post(admin_url + "newsfeed/load_likes_modal", {
      page: track_load_post_likes,
      postid: postid,
    }).done(function (response) {
      track_load_post_likes++;
      $("#modal_post_likes_wrapper").append(response);
    });

    if (track_load_post_likes >= post_likes_total_pages - 1) {
      $(".likes_modal .modal-footer").addClass("hide");
    }
  }
}

// Load comment likes modal
function load_comment_likes(commentid) {
  if (track_load_comment_likes <= comment_likes_total_pages) {
    $.post(admin_url + "newsfeed/load_comment_likes_model", {
      page: track_load_comment_likes,
      commentid: commentid,
    }).done(function (response) {
      track_load_comment_likes++;
      $("#modal_comment_likes_wrapper").append(response);
    });

    if (track_load_comment_likes >= comment_likes_total_pages - 1) {
      $(".likes_modal .modal-footer").addClass("hide");
    }
  }
}

// On click href load more comments from single post
function load_more_comments(link) {
  var postid = $(link).data("postid");
  var page = $(link).find('input[name="page"]').val();
  var total_pages = $(link).data("total-pages");

  if (page <= total_pages) {
    $.post(admin_url + "newsfeed/init_post_comments/" + postid, {
      page: page,
    }).done(function (response) {
      $(link).data("track-load-comments", page);
      $('[data-comments-postid="' + postid + '"] .load-more-comments').before(
        response
      );
    });
    page++;
    $(link).find('input[name="page"]').val(page);
    if (page >= total_pages - 1) {
      $(link).addClass("hide");
      $(link).removeClass("display-block");
    }
  }
}

// New post added append data
function newsfeed_new_post(postid) {
  var data = {};
  data.postid = postid;
  $.post(admin_url + "newsfeed/load_newsfeed", data).done(function (response) {
    var pinned = $("#newsfeed_data").find(".pinned");
    var pinned_length = pinned.length;
    if (pinned_length === 0) {
      $("#newsfeed_data").prepend(response);
    } else {
      var last_pinned = $("#newsfeed_data")
        .find(".pinned")
        .eq(pinned_length - 1);
      $(last_pinned).after(response);
    }
  });
}

// Init newsfeed data
function load_newsfeed(postid) {
  var data = {};
  data.page = newsfeed_posts_page;
  if (typeof postid != "undefined" && postid != 0) {
    data.postid = postid;
  }
  var total_pages = $('input[name="total_pages_newsfeed"]').val();
  if (newsfeed_posts_page <= total_pages) {
    $.post(admin_url + "newsfeed/load_newsfeed", data).done(function (
      response
    ) {
      newsfeed_posts_page++;
      $("#newsfeed_data").append(response);
    });
    if (newsfeed_posts_page >= total_pages - 1) {
      return;
    }
  }
}

// When user click heart button
function like_post(postid) {
  requestGetJSON("newsfeed/like_post/" + postid).done(function (response) {
    if (response.success === true || response.success == "true") {
      refresh_post_likes(postid);
    }
  });
}

// Unlikes post
function unlike_post(postid) {
  requestGetJSON("newsfeed/unlike_post/" + postid).done(function (response) {
    if (response.success === true || response.success == "true") {
      refresh_post_likes(postid);
    }
  });
}

// Like post comment
function like_comment(commentid, postid) {
  requestGetJSON("newsfeed/like_comment/" + commentid + "/" + postid).done(
    function (response) {
      if (response.success === true || response.success == "true") {
        $('[data-commentid="' + commentid + '"]').replaceWith(response.comment);
      }
    }
  );
}

// Unlike post comment
function unlike_comment(commentid, postid) {
  requestGetJSON("newsfeed/unlike_comment/" + commentid + "/" + postid).done(
    function (response) {
      if (response.success === true || response.success == "true") {
        $('[data-commentid="' + commentid + '"]').replaceWith(response.comment);
      }
    }
  );
}

// Add new comment to post
function add_comment(input) {
  var postid = $(input).data("postid");
  $.post(admin_url + "newsfeed/add_comment", {
    content: $(input).val(),
    postid: postid,
  }).done(function (response) {
    response = JSON.parse(response);
    if (response.success === true || response.success == "true") {
      $(input).val("");
      if (
        $("body").find('[data-comments-postid="' + postid + '"] .post-comment')
          .length > 0
      ) {
        $("body")
          .find('[data-comments-postid="' + postid + '"] .post-comment')
          .prepend(response.comment);
      } else {
        refresh_post_comments(postid);
      }
    }
  });
}

// Removes post comment
function remove_post_comment(id, postid) {
  requestGetJSON("newsfeed/remove_post_comment/" + id + "/" + postid).done(
    function (response) {
      if (response.success === true || response.success == "true") {
        $('.comment[data-commentid="' + id + '"]').remove();
      }
    }
  );
}

// Refreshing only post likes
function refresh_post_likes(postid) {
  requestGet(
    "newsfeed/init_post_likes/" + postid + "?refresh_post_likes=true"
  ).done(function (response) {
    $('[data-likes-postid="' + postid + '"]').html(response);
  });
}

// Refreshing only post comments
function refresh_post_comments(postid) {
  $.post(
    admin_url +
      "newsfeed/init_post_comments/" +
      postid +
      "?refresh_post_comments=true"
  ).done(function (response) {
    $('[data-comments-postid="' + postid + '"]').html(response);
  });
}

// Delete post from database
function delete_post(postid) {
  if (confirm_delete()) {
    $.post(
      admin_url + "newsfeed/delete_post/" + postid,
      function (response) {
        if (response.success === true || response.success == "true") {
          $('[data-main-postid="' + postid + '"]').remove();
        }
      },
      "json"
    );
  }
}

// Pin post to top
function pin_post(id) {
  requestGetJSON("newsfeed/pin_newsfeed_post/" + id).done(function (response) {
    if (response.success === true || response.success == "true") {
      window.location.reload();
    }
  });
}

// Unpin post from top
function unpin_post(id) {
  requestGetJSON("newsfeed/unpin_newsfeed_post/" + id).done(function (
    response
  ) {
    if (response.success === true || response.success == "true") {
      window.location.reload();
    }
  });
}

function _gen_lead_add_inline_on_select_field(type) {
  var html = "";
  if (
    $("body").hasClass("leads-email-integration") ||
    $("body").hasClass("web-to-lead-form")
  ) {
    type = "lead_" + type;
  }
  html =
    '<div id="new_lead_' +
    type +
    '_inline" class="form-group"><label for="new_' +
    type +
    '_name">' +
    $('label[for="' + type + '"]')
      .html()
      .trim() +
    '</label><div class="input-group"><input type="text" id="new_' +
    type +
    '_name" name="new_' +
    type +
    '_name" class="form-control"><div class="input-group-addon"><a href="#" onclick="lead_add_inline_select_submit(\'' +
    type +
    '\'); return false;" class="lead-add-inline-submit-' +
    type +
    '"><i class="fa fa-check"></i></a></div></div></div>';
  $(".form-group-select-input-" + type).after(html);
  $("body")
    .find("#new_" + type + "_name")
    .focus();
  $(
    '.lead-save-btn,#form_info button[type="submit"],#leads-email-integration button[type="submit"],.btn-import-submit'
  ).prop("disabled", true);
  $(".inline-field-new").addClass("disabled").css("opacity", 0.5);
  $(".form-group-select-input-" + type).addClass("hide");
}

function new_lead_status_inline() {
  _gen_lead_add_inline_on_select_field("status");
}

function new_lead_source_inline() {
  _gen_lead_add_inline_on_select_field("source");
}

function lead_add_inline_select_submit(type) {
  var val = $("#new_" + type + "_name")
    .val()
    .trim();
  if (val !== "") {
    var requestURI = type;
    if (type.indexOf("lead_") > -1) {
      requestURI = requestURI.replace("lead_", "");
    }

    var data = {};
    data.name = val;
    data.inline = true;
    $.post(admin_url + "leads/" + requestURI, data).done(function (response) {
      response = JSON.parse(response);
      if (response.success === true || response.success == "true") {
        var select = $("body").find("select#" + type);
        select.append(
          '<option value="' + response.id + '">' + val + "</option>"
        );
        select.selectpicker("val", response.id);
        select.selectpicker("refresh");
        select.parents(".form-group").removeClass("has-error");
      }
    });
  }

  $("#new_lead_" + type + "_inline").remove();
  $(".form-group-select-input-" + type).removeClass("hide");
  $(
    '.lead-save-btn,#form_info button[type="submit"],#leads-email-integration button[type="submit"],.btn-import-submit'
  ).prop("disabled", false);
  $(".inline-field-new").removeClass("disabled").removeAttr("style");
}

// Init lead for add/edit/view or refresh data
function init_lead(id, isEdit) {
  if ($("#task-modal").is(":visible")) {
    $("#task-modal").modal("hide");
  }
  // In case header error
  if (init_lead_modal_data(id, undefined, isEdit)) {
    $("#lead-modal").modal("show");
  }
}

// Lead form validation
function validate_lead_form() {
  var validationObject = {
    name: "required",
    source: "required",
    status: {
      required: {
        depends: function (element) {
          if ($("[lead-is-junk-or-lost]").length > 0) {
            return false;
          } else {
            return true;
          }
        },
      },
    },
  };

  var messages = {};
  $.each(leadUniqueValidationFields, function (key, field) {
    validationObject[field] = {};

    if (field == "email") {
      validationObject[field].email = true;
    }

    validationObject[field].remote = {
      url: admin_url + "leads/validate_unique_field",
      type: "post",
      data: {
        field: field,
        lead_id: function () {
          return $("#lead-modal").find('input[name="leadid"]').val();
        },
      },
    };

    if (typeof app.lang[field + "_exists"] != "undefined") {
      messages[field] = {
        remote: app.lang[field + "_exists"],
      };
    }
  });

  appValidateForm(
    $("#lead_form"),
    validationObject,
    lead_profile_form_handler,
    messages
  );
}

// Lead conver to customer form validation
function validate_lead_convert_to_client_form() {
  var rules_convert_lead = {
    firstname: "required",
    lastname: "required",
    password: {
      required: {
        depends: function (element) {
          var sent_set_password = $('input[name="send_set_password_email"]');
          if (sent_set_password.prop("checked") === false) {
            return true;
          }
        },
      },
    },
    email: {
      required: true,
      email: true,
      remote: {
        url: admin_url + "misc/contact_email_exists",
        type: "post",
        data: {
          email: function () {
            return $('#lead_to_client_form input[name="email"]').val();
          },
          userid: "",
        },
      },
    },
  };
  if (app.options.company_is_required == 1) {
    rules_convert_lead.company = "required";
  }
  appValidateForm($("#lead_to_client_form"), rules_convert_lead);
}

// Lead profile data function form handler
function lead_profile_form_handler(form) {
  form = $(form);
  var data = form.serialize();
  var leadid = $("#lead-modal").find('input[name="leadid"]').val();
  $(".lead-save-btn").addClass("disabled").attr('disabled', true);
  $.post(form.attr("action"), data)
    .done(function (response) {
      response = JSON.parse(response);
      if (response.message !== "") {
        alert_float("success", response.message);
      }
      if (response.proposal_warning && response.proposal_warning != false) {
        $("body").find("#lead_proposal_warning").removeClass("hide");
        $("body").find("#lead-modal").animate(
          {
            scrollTop: 0,
          },
          800
        );
      } else {
        _lead_init_data(response, response.id);
      }
      if ($.fn.DataTable.isDataTable(".table-leads")) {
        table_leads.DataTable().ajax.reload(null, false);
      } else if ($("body").hasClass("kan-ban-body")) {
        leads_kanban();
      }
    })
    .fail(function (data) {
      alert_float("danger", data.responseText);
      return false;
    });
  return false;
}

// Updates all proposals emails linked to lead, this wil be executed when eq lead email is changed
function update_all_proposal_emails_linked_to_lead(id) {
  $.post(admin_url + "leads/update_all_proposal_emails_linked_to_lead/" + id, {
    update: true,
  }).done(function (response) {
    response = JSON.parse(response);
    if (response.success) {
      alert_float("success", response.message);
    }
    init_lead_modal_data(id);
  });
}

// Add lead data returned from server to the lead modal
function _lead_init_data(data, id) {
  var hash = window.location.hash;

  var $leadModal = $("#lead-modal");
  $("#lead_reminder_modal").html(data.leadView.reminder_data);

  $leadModal.find(".data").html(data.leadView.data);

  $leadModal.modal({
    show: true,
    backdrop: "static",
  });

  init_tags_inputs();
  init_selectpicker();
  init_form_reminder();
  init_datepicker();
  init_color_pickers();
  custom_fields_hyperlink();
  validate_lead_form();

  var hashes = [
    "#tab_lead_profile",
    "#attachments",
    "#lead_notes",
    "#lead_activity",
    "#gdpr",
  ];

  if (hashes.indexOf(hash) > -1) {
    window.location.hash = hash;
  }

  initDataTableInline($("#consentHistoryTable"));

  $("#lead-modal")
    .find(".gpicker")
    .googleDrivePicker({
      onPick: function (pickData) {
        leadExternalFileUpload(pickData, "gdrive", id);
      },
    });

  if (id !== "" && typeof id != "undefined") {
    if (typeof Dropbox != "undefined") {
      document.getElementById("dropbox-chooser-lead").appendChild(
        Dropbox.createChooseButton({
          success: function (files) {
            leadExternalFileUpload(files, "dropbox", id);
          },
          linkType: "preview",
          extensions: app.options.allowed_files.split(","),
        })
      );
    }

    if (typeof leadAttachmentsDropzone != "undefined") {
      leadAttachmentsDropzone.destroy();
    }

    leadAttachmentsDropzone = new Dropzone(
      "#lead-attachment-upload",
      appCreateDropzoneOptions({
        sending: function (file, xhr, formData) {
          formData.append("id", id);
          if (this.getQueuedFiles().length === 0) {
            formData.append("last_file", true);
          }
        },
        success: function (file, response) {
          response = JSON.parse(response);
          if (
            this.getUploadingFiles().length === 0 &&
            this.getQueuedFiles().length === 0
          ) {
            _lead_init_data(response, response.id);
          }
        },
      })
    );

    $leadModal
      .find('.nav-tabs a[href="' + window.location.hash + '"]')
      .tab("show");
    var latest_lead_activity = $leadModal
      .find("#lead_activity .feed-item:last-child .text")
      .html();
    if (typeof latest_lead_activity != "undefined") {
      $leadModal.find("#lead-latest-activity").html(latest_lead_activity);
    } else {
      $leadModal
        .find(".lead-latest-activity > .lead-info-heading")
        .addClass("hide");
    }

    // The status is not required when lead is lost or junk
    // Remove the * required mark
    if ($("[lead-is-junk-or-lost]").length > 0) {
      $(".form-group-select-input-status").find(".req").remove();
    }
  }
}

// Fetches lead modal data, can be edit/add/view
function init_lead_modal_data(id, url, isEdit) {
  var requestURL =
    (typeof url != "undefined" ? url : "leads/lead/") +
    (typeof id != "undefined" ? id : "");

  if (isEdit === true) {
    var concat = "?";
    if (requestURL.indexOf("?") > -1) {
      concat += "&";
    }
    requestURL += concat + "edit=true";
  }

  requestGetJSON(requestURL)
    .done(function (response) {
      _lead_init_data(response, id);
    })
    .fail(function (data) {
      alert_float("danger", data.responseText);
    });
}

function print_lead_information() {
  var $leadViewWrapper = $("#leadViewWrapper").clone();
  var name = $leadViewWrapper.find(".lead-name").text().trim();

  $leadViewWrapper
    .find("p")
    .css("font-size", "100%")
    .css("font", "inherit")
    .css("vertical-align", "baseline")
    .css("margin", "0px");

  $leadViewWrapper.find("h4").css("font-size", "100%");

  $leadViewWrapper.find("dt").each(function() {
      $(this).replaceWith("<p style='margin-bottom:5px; color:#777'><strong>" + $(this).text() + "</strong></p>");
  });

  $leadViewWrapper.find("dd").each(function() {
      $(this).replaceWith("<div='margin-bottom:10px;'>" + $(this).text() + "</div>");
  });
  
  $leadViewWrapper.find(".lead-field-heading + p").css("margin-bottom", "15px");

  var mywindow = _create_print_window(name);

  mywindow.document.write("<html><head><title>" + app.lang.lead + "</title>");
  _add_print_window_default_styles(mywindow);
  mywindow.document.write("<style>");
  mywindow.document.write(
    ".lead-information-col { " + "float: left; width: 33.33333333%;" + "}" + ""
  );
  mywindow.document.write("</style>");

  mywindow.document.write("</head><body>");
  mywindow.document.write("<h1>" + name + "</h1>");
  mywindow.document.write(
    '<div id="#leadViewWrapper">' + $leadViewWrapper.html() + "</div>"
  );
  mywindow.document.write("</body></html>");

  mywindow.document.close(); // necessary for IE >= 10
  mywindow.focus(); // necessary for IE >= 10*/

  mywindow.print();
  setTimeout(function () {
    mywindow.close();
  }, 1000);
}

function print_expense_information() {
  var $expenseViewWrapper = $("#tab_expense").clone();
  var $headings = $("#expenseHeadings");
  var name =
    $headings.find("#expenseCategory").text().trim() +
    "<h4>" +
    $headings.find("#expenseName").text().trim() +
    "</h4>";

  $expenseViewWrapper.find("#expenseReceipt").remove();

  $expenseViewWrapper.find("#amountWrapper").css("margin-bottom", "15px");

  var mywindow = _create_print_window(name);

  mywindow.document.write(
    "<html><head><title>" + app.lang.expense + "</title>"
  );

  _add_print_window_default_styles(mywindow);

  mywindow.document.write("</head><body>");
  mywindow.document.write("<h1>" + name + "</h1>");
  mywindow.document.write(
    '<div id="#tab_expense">' + $expenseViewWrapper.html() + "</div>"
  );
  mywindow.document.write("</body></html>");

  mywindow.document.close(); // necessary for IE >= 10
  mywindow.focus(); // necessary for IE >= 10*/

  mywindow.print();
  setTimeout(function () {
    mywindow.close();
  }, 1000);
}

function print_ticket_message(id, type) {
  var printMessage = $("[data-" + type + '-id="' + id + '"]').html();
  var printSubject = $("#ticket_subject").text().trim();
  var mywindow = _create_print_window(printSubject);

  mywindow.document.write("<html><head><title>" + app.lang.ticket + "</title>");

  _add_print_window_default_styles(mywindow);

  mywindow.document.write("</head><body>");
  mywindow.document.write("<h1>" + printSubject + "</h1>");
  mywindow.document.write(printMessage);
  mywindow.document.write("</body></html>");

  mywindow.document.close(); // necessary for IE >= 10
  mywindow.focus(); // necessary for IE >= 10*/

  mywindow.print();
  setTimeout(function () {
    mywindow.close();
  }, 1000);
}

// Kan ban leads sorting
function leads_kanban_sort(type) {
  kan_ban_sort(type, leads_kanban);
}

// Update lead when action is performed from leads kan ban eq order or status change
function leads_kanban_update(ui, object) {
  if (object !== ui.item.parent()[0]) {
    return;
  }

  var data = {
    status: $(ui.item.parent()[0]).attr("data-lead-status-id"),
    leadid: $(ui.item).attr("data-lead-id"),
    order: [],
  };

  $.each($(ui.item).parents(".leads-status").find("li"), function (idx, el) {
    var id = $(el).attr("data-lead-id");
    if (id) {
      data.order.push([id, idx + 1]);
    }
  });

  setTimeout(function () {
    $.post(admin_url + "leads/update_lead_status", data).done(function (
      response
    ) {
      update_kan_ban_total_when_moving(ui, data.status);
      leads_kanban();
    });
  }, 200);
}

function update_kan_ban_total_when_moving(ui, newStatus) {
  if (ui.sender) {
    var oldStatusCol = $(ui.sender.closest(".kan-ban-col"));
    if (oldStatusCol.data("status-id") != newStatus) {
      var newStatusCol = $('[data-col-status-id="' + newStatus + '"]');
      newStatusCol.attr(
        "data-total",
        parseInt(newStatusCol.attr("data-total")) + 1
      );
      var oldStatusCol = $(ui.sender.closest(".kan-ban-col"));
      oldStatusCol.attr(
        "data-total",
        parseInt(oldStatusCol.attr("data-total")) - 1
      );
    }
  }
}

// Leads statuses kanban sortable
function init_leads_status_sortable() {
  $("#kan-ban").sortable({
    helper: "clone",
    item: ".kan-ban-col",
    update: function (event, ui) {
      data = {
        order: [],
      };

      $.each($(".kan-ban-col"), function (idx, el) {
        data.order.push([$(el).attr("data-col-status-id"), idx + 1]);
      });

      $.post(admin_url + "leads/update_status_order", data);
    },
  });
}

// Init the leads kanban
function leads_kanban(search) {
  init_kanban(
    "leads/kanban",
    leads_kanban_update,
    ".leads-status",
    290,
    360,
    init_leads_status_sortable
  );
}

// Deleting lead attachments
function delete_lead_attachment(wrapper, id, lead_id) {
  if (confirm_delete()) {
    requestGetJSON("leads/delete_attachment/" + id + "/" + lead_id)
      .done(function (response) {
        if (response.success === true || response.success == "true") {
          $(wrapper).parents(".lead-attachment-wrapper").remove();
          _lead_init_data(response, response.id);
        }
      })
      .fail(function (data) {
        alert_float("danger", data.responseText);
      });
  }
}

// Delete lead note
function delete_lead_note(wrapper, id, lead_id) {
  if (confirm_delete()) {
    requestGetJSON("leads/delete_note/" + id + "/" + lead_id)
      .done(function (response) {
        if (response.success === true || response.success == "true") {
          $(wrapper).parents(".lead-note").remove();
          _lead_init_data(response, response.id);
        }
      })
      .fail(function (data) {
        alert_float("danger", data.responseText);
      });
  }
}

// Mark lead as lost function
function lead_mark_as_lost(id) {
  requestGetJSON("leads/mark_as_lost/" + id)
    .done(function (response) {
      if (response.success === true || response.success == "true") {
        alert_float("success", response.message);
        $("body")
          .find("tr#lead_" + id)
          .remove();
        $("body")
          .find('#kan-ban li[data-lead-id="' + id + '"]')
          .remove();
      }
      _lead_init_data(response, response.id);
    })
    .fail(function (error) {
      alert_float("danger", error.responseText);
    });
}

// Unmark lead as lost function
function lead_unmark_as_lost(id) {
  requestGetJSON("leads/unmark_as_lost/" + id)
    .done(function (response) {
      if (response.success === true || response.success == "true") {
        alert_float("success", response.message);
      }
      _lead_init_data(response, response.id);
    })
    .fail(function (error) {
      alert_float("danger", error.responseText);
    });
}

// Mark lead as junk function
function lead_mark_as_junk(id) {
  requestGetJSON("leads/mark_as_junk/" + id)
    .done(function (response) {
      if (response.success === true || response.success == "true") {
        alert_float("success", response.message);
        $("body")
          .find("tr#lead_" + id)
          .remove();
        $("body")
          .find('#kan-ban li[data-lead-id="' + id + '"]')
          .remove();
      }
      _lead_init_data(response, response.id);
    })
    .fail(function (error) {
      alert_float("danger", error.responseText);
    });
}
// From lead table mark as
function lead_mark_as(status_id, lead_id) {
  var data = {};
  data.status = status_id;
  data.leadid = lead_id;
  $.post(admin_url + "leads/update_lead_status", data).done(function (
    response
  ) {
    table_leads.DataTable().ajax.reload(null, false);
  });
}

// Unmark lead as junk function
function lead_unmark_as_junk(id) {
  requestGetJSON("leads/unmark_as_junk/" + id)
    .done(function (response) {
      if (response.success === true || response.success == "true") {
        alert_float("success", response.message);
      }
      _lead_init_data(response, response.id);
    })
    .fail(function (error) {
      alert_float("danger", error.responseText);
    });
}

// Convert lead to customer
function convert_lead_to_customer(id) {
  var $leadModal = $("#lead-modal");
  var eventNamespace = "hidden.bs.modal.convert";

  $leadModal.on(eventNamespace, function () {
    $leadModal.find(".data").html("");

    requestGet("leads/get_convert_data/" + id)
      .done(function (response) {
        $("#lead_convert_to_customer").html(response);

        $("#convert_lead_to_client_modal").modal({
          show: true,
          backdrop: "static",
          keyboard: false,
        });
      })
      .fail(function (data) {
        alert_float("danger", data.responseText);
      })
      .always(function () {
        $leadModal.off(eventNamespace);
      });
  });

  $leadModal.modal("hide");
}

// Leads bulk action
function leads_bulk_action(event) {
  if (confirm_delete()) {
    var mass_delete = $("#mass_delete").prop("checked");
    var ids = [];
    var data = {};
    if (mass_delete == false || typeof mass_delete == "undefined") {
      data.lost = $("#leads_bulk_mark_lost").prop("checked");
      data.status = $("#move_to_status_leads_bulk").val();
      data.assigned = $("#assign_to_leads_bulk").val();
      data.source = $("#move_to_source_leads_bulk").val();
      data.last_contact = $("#leads_bulk_last_contact").val();
      data.tags = $("#tags_bulk").tagit("assignedTags");
      data.visibility = $('input[name="leads_bulk_visibility"]:checked').val();

      data.assigned = typeof data.assigned == "undefined" ? "" : data.assigned;
      data.visibility =
        typeof data.visibility == "undefined" ? "" : data.visibility;

      if (
        data.status === "" &&
        data.lost === false &&
        data.assigned === "" &&
        data.source === "" &&
        data.last_contact === "" &&
        data.tags.length == 0 &&
        data.visibility === ""
      ) {
        return;
      }
    } else {
      data.mass_delete = true;
    }
    var rows = table_leads.find("tbody tr");
    $.each(rows, function () {
      var checkbox = $($(this).find("td").eq(0)).find("input");
      if (checkbox.prop("checked") === true) {
        ids.push(checkbox.val());
      }
    });
    data.ids = ids;
    $(event).addClass("disabled");
    setTimeout(function () {
      $.post(admin_url + "leads/bulk_action", data)
        .done(function () {
          window.location.reload();
        })
        .fail(function (data) {
          $("#lead-modal").modal("hide");
          alert_float("danger", data.responseText);
        });
    }, 200);
  }
}

function init_proposal_editor() {
  init_tinymce_inline_editor({
    saveUsing: save_proposal_content,
    onSetup: function(editor) {
      editor.on("MouseDown ContextMenu", function () {
        if (!is_mobile() && 
          !$("#small-table").hasClass("hide")) {
          small_table_full_view();
        }
      });
    }
  })
}

function update_comments_count() {
  var count = $(".comment-item").length;
  $(".total_comments").text(count);
  if (count === 0) {
    $(".total_comments").addClass("hide");
  } else {
    $(".total_comments").removeClass("hide");
  }
}

function add_proposal_comment() {
  var comment = $("#comment").val();
  if (comment == "") {
    return;
  }
  var data = {};
  data.content = comment;
  data.proposalid = proposal_id;
  $("body").append('<div class="dt-loader"></div>');
  $.post(admin_url + "proposals/add_proposal_comment", data).done(function (
    response
  ) {
    response = JSON.parse(response);
    $("body").find(".dt-loader").remove();
    if (response.success == true) {
      $("#comment").val("");
      get_proposal_comments();
    }
  });
}

function get_proposal_comments() {
  if (typeof proposal_id == "undefined") {
    return;
  }
  requestGet("proposals/get_proposal_comments/" + proposal_id).done(function (
    response
  ) {
    $("body").find("#proposal-comments").html(response);
    update_comments_count("proposal");
  });
}

function remove_proposal_comment(commentid) {
  if (confirm_delete()) {
    requestGetJSON("proposals/remove_comment/" + commentid).done(function (
      response
    ) {
      if (response.success == true) {
        $('[data-commentid="' + commentid + '"]').remove();
        update_comments_count("proposal");
      }
    });
  }
}

function edit_proposal_comment(id) {
  var content = $("body")
    .find('[data-proposal-comment-edit-textarea="' + id + '"] textarea')
    .val();
  if (content != "") {
    $.post(admin_url + "proposals/edit_comment/" + id, {
      content: content,
    }).done(function (response) {
      response = JSON.parse(response);
      if (response.success == true) {
        alert_float("success", response.message);
        $("body")
          .find('[data-proposal-comment="' + id + '"]')
          .html(nl2br(content));
      }
    });
    toggle_proposal_comment_edit(id);
  }
}

function toggle_proposal_comment_edit(id) {
  $("body")
    .find('[data-proposal-comment="' + id + '"]')
    .toggleClass("hide");
  $("body")
    .find('[data-proposal-comment-edit-textarea="' + id + '"]')
    .toggleClass("hide");
}

function proposal_convert_template(invoker) {
  var template = $(invoker).data("template");
  var html_helper_selector;
  if (template == "estimate") {
    html_helper_selector = "estimate";
  } else if (template == "invoice") {
    html_helper_selector = "invoice";
  } else {
    return false;
  }

  requestGet(
    "proposals/get_" + html_helper_selector + "_convert_data/" + proposal_id
  ).done(function (data) {
    if ($(".proposal-pipeline-modal").is(":visible")) {
      $(".proposal-pipeline-modal").modal("hide");
    }
    $("#convert_helper").html(data);
    $("#convert_to_" + html_helper_selector).modal({
      show: true,
      backdrop: "static",
    });
    reorder_items();
  });
}

function save_proposal_content(manual) {
  var editor = tinyMCE.activeEditor;
  var data = {};
  data.proposal_id = proposal_id;
  data.content = editor.getContent();
  $.post(admin_url + "proposals/save_proposal_data", data)
    .done(function (response) {
      response = JSON.parse(response);
      if (typeof manual != "undefined") {
        // Show some message to the user if saved via CTRL + S
        alert_float("success", response.message);
      }
      // Invokes to set dirty to false
      editor.save();
    })
    .fail(function (error) {
      var response = JSON.parse(error.responseText);
      alert_float("danger", response.message);
    });
}

// Proposal sync data in case eq mail is changed, shown for lead and customers.
function sync_proposals_data(rel_id, rel_type) {
  var data = {};
  var modal_sync = $("#sync_data_proposal_data");
  data.country = modal_sync.find('select[name="country"]').val();
  data.zip = modal_sync.find('input[name="zip"]').val();
  data.state = modal_sync.find('input[name="state"]').val();
  data.city = modal_sync.find('input[name="city"]').val();
  data.address = modal_sync.find('textarea[name="address"]').val();
  data.phone = modal_sync.find('input[name="phone"]').val();
  data.rel_id = rel_id;
  data.rel_type = rel_type;
  $.post(admin_url + "proposals/sync_data", data).done(function (response) {
    response = JSON.parse(response);
    alert_float("success", response.message);
    modal_sync.modal("hide");
  });
}

// Table announcements
function init_table_announcements(manual) {
  if (typeof manual == "undefined" && $("body").hasClass("dashboard")) {
    return false;
  }
  initDataTable(
    ".table-announcements",
    admin_url + "announcements",
    undefined,
    undefined,
    "undefined",
    [1, "desc"]
  );
}

// Table tickets
function init_table_tickets(manual) {
  // Single ticket is for other tickets from user
  if (
    typeof manual == "undefined" &&
    ($("body").hasClass("dashboard") || $("body").hasClass("single-ticket"))
  ) {
    return false;
  }

  if ($("body").find(".tickets-table").length === 0) {
    return;
  }

  var TicketServerParams = {},
    Tickets_Filters = $("._hidden_inputs._filters.tickets_filters input");
  var tickets_date_created_index = $(
    "table.tickets-table thead .ticket_created_column"
  ).index();
  $.each(Tickets_Filters, function () {
    TicketServerParams[$(this).attr("name")] =
      '[name="' + $(this).attr("name") + '"]';
  });

  TicketServerParams["project_id"] = '[name="project_id"]';

  var ticketsTableNotSortable = [0]; // bulk actions
  var _tickets_table_url = admin_url + "tickets";

  if ($("body").hasClass("tickets-page")) {
    _tickets_table_url += "?bulk_actions=true";
  }

  _table_api = initDataTable(
    ".tickets-table",
    _tickets_table_url,
    ticketsTableNotSortable,
    ticketsTableNotSortable,
    TicketServerParams,
    [tickets_date_created_index, "desc"]
  );

  if (_table_api && $("body").hasClass("dashboard")) {
    var notVisibleDashboardDefault = [4, tickets_date_created_index, 5, 6];
    for (var i in notVisibleDashboardDefault) {
      _table_api.column(notVisibleDashboardDefault[i]).visible(false, false);
    }
    _table_api.columns.adjust();
  }
}

// Staff projects table in staff profile
function init_table_staff_projects(manual) {
  if (typeof manual == "undefined" && $("body").hasClass("dashboard")) {
    return false;
  }
  if ($("body").find(".table-staff-projects").length === 0) {
    return;
  }

  var staffProjectsParams = {},
    Staff_Projects_Filters = $(
      "._hidden_inputs._filters.staff_projects_filter input"
    );

  $.each(Staff_Projects_Filters, function () {
    staffProjectsParams[$(this).attr("name")] =
      '[name="' + $(this).attr("name") + '"]';
  });

  initDataTable(
    ".table-staff-projects",
    admin_url + "projects/staff_projects",
    "undefined",
    "undefined",
    staffProjectsParams,
    [2, "asc"]
  );
}

// Fix task checklist content textarea height
function do_task_checklist_items_height(task_checklist_items) {
  if (typeof task_checklist_items == "undefined") {
    task_checklist_items = $("body").find(
      "textarea[name='checklist-description']"
    );
  }

  $.each(task_checklist_items, function () {
    var val = $(this).val();
    if (
      $(this).outerHeight() <
      this.scrollHeight +
        parseFloat($(this).css("borderTopWidth")) +
        parseFloat($(this).css("borderBottomWidth"))
    ) {
      $(this).height(0).height(this.scrollHeight);
    }
    if (val === "") {
      $(this).removeAttr("style");
    }
  });
}

// Recalculate task checklist items progress, this progress is shown only if there is more then 2 checklist items
function recalculate_checklist_items_progress() {
  var total_finished = $('input[name="checklist-box"]:checked').length;
  var total_checklist_items = $('input[name="checklist-box"]').length;
  var percent = 0,
    task_progress_bar = $(".task-progress-bar");
  $(".task-total-checklist-completed").text(total_finished);
  if (total_checklist_items == 0) {
    // remove the heading for checklist items
    // $("body").find(".chk-heading").remove();
    $("#task-no-checklist-items").removeClass("hide");
  } else {
    $("#task-no-checklist-items").addClass("hide");
  }
  if (total_checklist_items >= 2) {
    task_progress_bar.parents(".progress").removeClass("hide");
    percent = (total_finished * 100) / total_checklist_items;
    if (percent == 0) {
      $(".task-progress-bar").addClass("text-dark");
    } else {
      $(".task-progress-bar").removeClass("text-dark");
    }
  } else {
    task_progress_bar.parents(".progress").addClass("hide");
    if (total_finished > 0) {
      $(".chk-toggle-buttons").removeClass("hide");
    } else {
      $(".chk-toggle-buttons").addClass("hide");
    }
    return false;
  }
  task_progress_bar.css("width", percent.toFixed(2) + "%");
  task_progress_bar.text(percent.toFixed(2) + "%");

  if (total_finished > 0) {
    $(".chk-toggle-buttons").removeClass("hide");
  } else {
    $(".chk-toggle-buttons").addClass("hide");
  }

  if (percent == 100) {
    task_progress_bar
      .removeClass("progress-bar-default")
      .addClass("progress-bar-success");
  } else {
    task_progress_bar
      .removeClass("progress-bar-success")
      .addClass("progress-bar-default");
  }
}

// Remove task checklist items template
function remove_checklist_item_template(id) {
  requestGetJSON("tasks/remove_checklist_item_template/" + id).done(function (
    response
  ) {
    if (response.success === true || response.success == "true") {
      var itemsTemplateSelect = $("body").find(
        "select.checklist-items-template-select"
      );
      var deletedItemDescription = itemsTemplateSelect
        .find('option[value="' + id + '"]')
        .html()
        .trim();
      var currentChecklists = $("#task-modal .checklist");
      $.each(currentChecklists, function (i, area) {
        var checkList = $(area);
        if (
          checkList
            .find('textarea[name="checklist-description"]')
            .val()
            .trim() == deletedItemDescription
        ) {
          checkList.find(".save-checklist-template").removeClass("hide");
        }
      });
      itemsTemplateSelect.find('option[value="' + id + '"]').remove();
      itemsTemplateSelect.selectpicker("refresh");
      if (itemsTemplateSelect.find("option").length === 1) {
        itemsTemplateSelect.selectpicker("destroy");
        $(".checklist-templates-wrapper").addClass("hide");
      }
    }
  });
}

// New task checklist items template
function save_checklist_item_template(id, field) {
  var description = $(
    '.checklist[data-checklist-id="' + id + '"] textarea'
  ).val();
  $.post(admin_url + "tasks/save_checklist_item_template", {
    description: description,
  }).done(function (response) {
    response = JSON.parse(response);
    $(field).addClass("hide");
    var singleChecklistTemplate = $(".checklist-templates-wrapper");
    singleChecklistTemplate
      .find('select option[value=""]')
      .after(
        '<option value="' +
          response.id +
          '">' +
          description.trim() +
          "</option>"
      );
    singleChecklistTemplate.removeClass("hide");
    singleChecklistTemplate.find("select").selectpicker("refresh");
  });
}

// Updates task checklist items order
function update_checklist_order() {
  var order = [];
  var items = $("body").find(".checklist");
  if (items.length === 0) {
    return;
  }
  var i = 1;
  $.each(items, function () {
    order.push([$(this).data("checklist-id"), i]);
    i++;
  });
  var data = {};
  data.order = order;
  $.post(admin_url + "tasks/update_checklist_order", data);
}

// New task checklist item
function add_task_checklist_item(task_id, description, e) {
  if (e) {
    $(e).addClass("disabled");
  }

  description = typeof description == "undefined" ? "" : description;
  var order = $("#checklist-items").find(".checklist").length;

  $.post(admin_url + "tasks/add_checklist_item", {
    taskid: task_id,
    description: description,
    list_order: order,
  })
    .done(function () {
      init_tasks_checklist_items(true, task_id);
    })
    .always(function () {
      if (e) {
        $(e).removeClass("disabled");
      }
    });
}

function update_task_checklist_item(textArea) {
  var deferred = $.Deferred();
  setTimeout(function () {
    var description = textArea.val();
    description = description.trim();
    var listid = textArea.parents(".checklist").data("checklist-id");

    $.post(admin_url + "tasks/update_checklist_item", {
      description: description,
      listid: listid,
    }).done(function (response) {
      deferred.resolve();
      response = JSON.parse(response);
      if (response.can_be_template === true) {
        textArea
          .parents(".checklist")
          .find(".save-checklist-template")
          .removeClass("hide");
      }
      if (description === "") {
        $("#checklist-items")
          .find('.checklist[data-checklist-id="' + listid + '"]')
          .remove();
      }
    });
  }, 300);
  return deferred.promise();
}

// Remove task checklist item from the task
function delete_checklist_item(id, field) {
  requestGetJSON("tasks/delete_checklist_item/" + id).done(function (response) {
    if (response.success === true || response.success == "true") {
      $(field).parents(".checklist").remove();
      recalculate_checklist_items_progress();
    }
  });
}

// Fetches task checklist items.
function init_tasks_checklist_items(is_new, task_id) {
  $.post(admin_url + "tasks/init_checklist_items", {
    taskid: task_id,
  }).done(function (data) {
    $("#checklist-items").html(data);
    if (typeof is_new != "undefined") {
      var last = $("#checklist-items").find(".checklist textarea").eq(-1);
      if (last.val() === "") {
        last.focus();
      }
    }
    recalculate_checklist_items_progress();
    update_checklist_order();
  });
}

function _task_attachments_more_and_less_checks() {
  var att_wrap = $("body").find(".task_attachments_wrapper");
  var attachments = att_wrap.find(".task-attachment-col");
  var taskAttachmentsMore = $("body").find(
    "#show-more-less-task-attachments-col .task-attachments-more"
  );
  if (attachments.length === 0) {
    att_wrap.remove();
  } else if (attachments.length == 2 && taskAttachmentsMore.hasClass("hide")) {
    $("body").find("#show-more-less-task-attachments-col").remove();
  } else if (
    $(".task_attachments_wrapper .task-attachment-col:visible").length === 0 &&
    !taskAttachmentsMore.hasClass("hide")
  ) {
    taskAttachmentsMore.click();
  }

  $.each($("#task-modal .comment-content"), function () {
    if ($(this).find(".task-attachment-col").length === 0) {
      $(this).find(".download-all").remove();
    }
  });
}

// Removes task single attachment
function remove_task_attachment(link, id) {
  if (confirm_delete()) {
    requestGetJSON("tasks/remove_task_attachment/" + id).done(function (
      response
    ) {
      if (response.success === true || response.success == "true") {
        $('[data-task-attachment-id="' + id + '"]').remove();
      }
      _task_attachments_more_and_less_checks();
      if (response.comment_removed) {
        $("#comment_" + response.comment_removed).remove();
      }
    });
  }
}

// Add new task comment from the modal
function add_task_comment(task_id) {
  var data = {};

  if (taskCommentAttachmentDropzone.files.length > 0) {
    taskCommentAttachmentDropzone.processQueue(task_id);
    return;
  }
  if (tinymce.activeEditor) {
    data.content = tinyMCE.activeEditor.getContent();
  } else {
    data.content = $("#task_comment").val();
    data.no_editor = true;
  }
  data.taskid = task_id;
  $.post(admin_url + "tasks/add_task_comment", data).done(function (response) {
    response = JSON.parse(response);
    _task_append_html(response.taskHtml);
    // Remove task comment editor instance
    // Causing error because of are you sure you want to leave this page, the plugin still sees as active and dirty.
    tinymce.remove("#task_comment");
  });
}

// Deletes task comment from database
function remove_task_comment(commentid) {
  if (confirm_delete()) {
    requestGetJSON("tasks/remove_comment/" + commentid).done(function (
      response
    ) {
      if (response.success === true || response.success == "true") {
        $('[data-commentid="' + commentid + '"]').remove();
        $('[data-comment-attachment="' + commentid + '"]').remove();
        _task_attachments_more_and_less_checks();
      }
    });
  }
}

// Remove task assignee
function remove_assignee(id, task_id) {
  if (confirm_delete()) {
    requestGetJSON("tasks/remove_assignee/" + id + "/" + task_id).done(
      function (response) {
        if (response.success === true || response.success == "true") {
          alert_float("success", response.message);
          _task_append_html(response.taskHtml);
        }
      }
    );
  }
}

// Remove task follower
function remove_follower(id, task_id) {
  if (confirm_delete()) {
    requestGetJSON("tasks/remove_follower/" + id + "/" + task_id).done(
      function (response) {
        if (response.success === true || response.success == "true") {
          alert_float("success", response.message);
          _task_append_html(response.taskHtml);
        }
      }
    );
  }
}

// Marking task as complete
function mark_complete(task_id) {
  task_mark_as(5, task_id);
}

// Unmarking task as complete
function unmark_complete(task_id) {
  task_mark_as(4, task_id, "tasks/unmark_complete/" + task_id);
}

// Mark task status
function task_mark_as(status, task_id, url) {
  url =
    typeof url == "undefined" ? "tasks/mark_as/" + status + "/" + task_id : url;
  var taskModalVisible = $("#task-modal").is(":visible");
  url += "?single_task=" + taskModalVisible;
  $("body").append('<div class="dt-loader"></div>');
  requestGetJSON(url).done(function (response) {
    $("body").find(".dt-loader").remove();
    if (response.success === true || response.success == "true") {
      reload_tasks_tables();
      if (taskModalVisible) {
        _task_append_html(response.taskHtml);
      }
      if (
        status == 5 &&
        typeof _maybe_remove_task_from_project_milestone == "function"
      ) {
        _maybe_remove_task_from_project_milestone(task_id);
      }
      if ($(".tasks-kanban").length === 0) {
        alert_float("success", response.message);
      }
    }
  });
}

// Change task priority from sigle modal
function task_change_priority(priority_id, task_id) {
  url = "tasks/change_priority/" + priority_id + "/" + task_id;
  var taskModalVisible = $("#task-modal").is(":visible");
  url += "?single_task=" + taskModalVisible;
  requestGetJSON(url).done(function (response) {
    if (response.success === true || response.success == "true") {
      reload_tasks_tables();
      if (taskModalVisible) {
        _task_append_html(response.taskHtml);
      }
    }
  });
}

// Change task milestone from single modal
function task_change_milestone(milestone_id, task_id) {
  url = "tasks/change_milestone/" + milestone_id + "/" + task_id;
  var taskModalVisible = $("#task-modal").is(":visible");
  url += "?single_task=" + taskModalVisible;
  requestGetJSON(url).done(function (response) {
    if (response.success === true || response.success == "true") {
      reload_tasks_tables();
      if (taskModalVisible) {
        _task_append_html(response.taskHtml);
      }
    }
  });
}

// Non finished timesheet delete, this is available for all staff
function delete_user_unfinished_timesheet(id) {
  if (confirm_delete()) {
    requestGetJSON("tasks/delete_user_unfinished_timesheet/" + id).done(
      function (response) {
        _init_timers_top_html(JSON.parse(response.timers));
        reload_tasks_tables();
      }
    );
  }
}

// Reload all tasks possible table where the table data needs to be refreshed after an action is performed on task.
function reload_tasks_tables() {
  var av_tasks_tables = [
    ".table-tasks",
    ".table-rel-tasks",
    ".table-rel-tasks-leads",
    ".table-timesheets",
    ".table-timesheets-report",
  ];
  $.each(av_tasks_tables, function (i, selector) {
    if ($.fn.DataTable.isDataTable(selector)) {
      $(selector).DataTable().ajax.reload(null, false);
    }
  });
}

// Makes task public with AJAX request
function make_task_public(task_id) {
  requestGetJSON("tasks/make_public/" + task_id).done(function (response) {
    if (response.success === true || response.success == "true") {
      reload_tasks_tables();
      _task_append_html(response.taskHtml);
    }
  });
}

// New task function, various actions performed
function new_task(url, timer_id) {
  url = typeof url != "undefined" ? url : admin_url + "tasks/task";

  var $leadModal = $("#lead-modal");
  if ($leadModal.is(":visible")) {
    url +=
      "&opened_from_lead_id=" + $leadModal.find('input[name="leadid"]').val();
    if (url.indexOf("?") === -1) {
      url = url.replace("&", "?");
    }
    $leadModal.modal("hide");
  }

  var $taskSingleModal = $("#task-modal");
  if ($taskSingleModal.is(":visible")) {
    $taskSingleModal.modal("hide");
  }

  var $taskEditModal = $("#_task_modal");
  if ($taskEditModal.is(":visible")) {
    $taskEditModal.modal("hide");
  }

  requestGet(url)
    .done(function (response) {
      $("#_task").html(response);
      $("body").find("#_task_modal").modal({
        show: true,
        backdrop: "static",
      });

      var stopTimerPopover = $("#timer-select-task");
      if (stopTimerPopover.is(":visible")) {
        $(".system-popup-close").click();
        window._timer_id = timer_id;
      }
    })
    .fail(function (error) {
      alert_float("danger", error.responseText);
    });
}

// Show/hide tags placeholder
function showHideTagsPlaceholder($tagit) {
  var $input = $tagit.data("ui-tagit").tagInput,
    placeholderText = $tagit.data("ui-tagit").options.placeholderText;
  $tagit.tagit("assignedTags").length > 0
    ? $input.removeAttr("placeholder")
    : $input.attr("placeholder", placeholderText);
}

// Create new task directly from relation, related options selected after modal is shown
function new_task_from_relation(table, rel_type, rel_id) {
  if (typeof rel_type == "undefined" && typeof rel_id == "undefined") {
    rel_id = $(table).data("new-rel-id");
    rel_type = $(table).data("new-rel-type");
  }
  var url = admin_url + "tasks/task?rel_id=" + rel_id + "&rel_type=" + rel_type;
  new_task(url);
}

// Go to edit view
function edit_task(task_id) {
  requestGet("tasks/task/" + task_id).done(function (response) {
    $("#_task").html(response);
    $("#task-modal").modal("hide");
    $("body").find("#_task_modal").modal({
      show: true,
      backdrop: "static",
    });
  });
}

// Handles task add/edit form modal.
function task_form_handler(form) {
  tinymce.triggerSave();

  $("#_task_modal").find('input[name="startdate"]').prop("disabled", false);
  // Disable the save button in cases od duplicate clicks
  $("#_task_modal").find('button[type="submit"]').prop("disabled", true);

  $("#_task_modal input[type=file]").each(function () {
    if ($(this).val() === "") {
      $(this).prop("disabled", true);
    }
  });

  var formURL = form.action;
  var formData = new FormData($(form)[0]);

  $.ajax({
    type: $(form).attr("method"),
    data: formData,
    mimeType: $(form).attr("enctype"),
    contentType: false,
    cache: false,
    processData: false,
    url: formURL,
  })
    .done(function (response) {
      response = JSON.parse(response);
      if (response.success === true || response.success == "true") {
        alert_float("success", response.message);
      }

      if (window._timer_id) {
        requestGet(admin_url + "/tasks/get_task_by_id/" + response.id).done(
          function (response) {
            $('[data-timer-id="' + window._timer_id + '"').click();
            response = JSON.parse(response);
            var option =
              '<option value="' +
              response.id +
              '" title="' +
              response.name +
              '" selected>' +
              response.name +
              "</option>";
            $("#timer_add_task_id").append(option);
            $("#timer_add_task_id")
              .trigger("change")
              .data("AjaxBootstrapSelect").list.cache = {};
            $("#timer_add_task_id").selectpicker("refresh");
            delete window._timer_id;
          }
        );
        $("#_task_modal").modal("hide");
        $("#task-modal").modal("hide");
        return false;
      }

      if (!$("body").hasClass("project")) {
        $("#_task_modal").attr("data-task-created", true);
        $("#_task_modal").modal("hide");
        init_task_modal(response.id);
        reload_tasks_tables();
        if ($("body").hasClass("kan-ban-body") && $("body").hasClass("tasks")) {
          tasks_kanban();
        }
      } else {
        // reload page on project area
        var location = window.location.href;
        var params = [];
        location = location.split("?");
        var group = get_url_param("group");
        var excludeCompletedTasks = get_url_param("exclude_completed");
        if (group) {
          params["group"] = group;
        }
        if (excludeCompletedTasks) {
          params["exclude_completed"] = excludeCompletedTasks;
        }
        params["taskid"] = response.id;
        window.location.href = buildUrl(location[0], params);
      }
    })
    .fail(function (error) {
      alert_float("danger", JSON.parse(error.responseText));
    });

  return false;
}

// Full screen white popup
function system_popup(data) {
  data.content = typeof data.content == "undefined" ? "" : data.content;

  var $popupHTML = $("<div/>", {
    id: "system-popup",
    class: "system-popup",
  }).appendTo("body");

  var overlayHTML = "";
  overlayHTML += '<div class="popup-wrapper fadeIn animated">';
  overlayHTML += '<h2 class="popup-message">';
  overlayHTML += data.message;
  overlayHTML += "</h2>";
  overlayHTML += '<div class="popup-content">';
  overlayHTML += data.content;
  overlayHTML += '<button type="button" class="system-popup-close"> </button>';
  overlayHTML += "</div>";
  overlayHTML += "</div>";

  $popupHTML.html(overlayHTML).removeClass("hide");
  $("body").addClass("system-popup");
  $popupHTML.find(".system-popup-close").on("click", function () {
    var that = this;
    requestGet("misc/clear_system_popup").done(function (response) {
      setTimeout(function () {
        $("body").removeClass("system-popup");
        $popupHTML.fadeOut(400, function () {
          $popupHTML.remove();
        });
        $(that).off("click");
      }, 50);
    });
  });

  return $popupHTML;
}

// Action for task timer start/stop
function timer_action(e, task_id, timer_id, adminStop) {
  timer_id = typeof timer_id == "undefined" ? "" : timer_id;

  var $timerSelectTask = $("#timer-select-task");
  if (task_id === "" && $timerSelectTask.is(":visible")) {
    return;
  }
  if (timer_id !== "" && task_id == "0") {
    var popupData = {};
    popupData.content = "";
    popupData.content += '<div class="row">';
    popupData.content += '<div class="form-group">';
    if (app.options.has_permission_create_task == "1") {
      popupData.content +=
        '<div class="input-group" style="margin:0 auto;width:60%;">';
    }
    popupData.content +=
      '<select id="timer_add_task_id" data-empty-title="' +
      app.lang.search_tasks +
      '" data-width="60%" class="ajax-search" data-live-search="true">';
    popupData.content += "</select>";
    if (app.options.has_permission_create_task == "1") {
      popupData.content +=
        '<div class="input-group-addon" style="opacity: 1;">';
      popupData.content +=
        '<a href="#" onclick="new_task(\'tasks/task\',' +
        timer_id +
        '); return false;"><i class="fa fa-plus"></i></a>';
      popupData.content += "</div>";
    }
    popupData.content += "</div></div>";
    popupData.content += '<div class="form-group">';
    popupData.content +=
      '<textarea id="timesheet_note" placeholder="' +
      app.lang.note +
      '" style="margin:0 auto;width:60%;" rows="4" class="form-control"></textarea>';
    popupData.content += "</div>";
    popupData.content +=
      "<button type='button' onclick='timer_action(this,document.getElementById(\"timer_add_task_id\").value," +
      timer_id +
      ");return false;' class='btn btn-primary'>" +
      app.lang.confirm +
      "</button>";
    popupData.message = app.lang.task_stop_timer;
    var $popupHTML = system_popup(popupData);
    $popupHTML.attr("id", "timer-select-task");
    init_ajax_search(
      "tasks",
      "#timer_add_task_id",
      undefined,
      admin_url + "tasks/ajax_search_assign_task_to_timer"
    );
    return false;
  }

  $(e).addClass("disabled");

  var data = {};
  data.task_id = task_id;
  data.timer_id = timer_id;
  data.note = $("body").find("#timesheet_note").val();
  if (!data.note) {
    data.note = "";
  }
  var taskModalVisible = $("#task-modal").is(":visible");
  var reqUrl =
    admin_url + "tasks/timer_tracking?single_task=" + taskModalVisible;
  if (adminStop) {
    reqUrl += "&admin_stop=" + adminStop;
  }
  $.post(reqUrl, data).done(function (response) {
    response = JSON.parse(response);

    // Timer action, stopping from staff/member/id
    if ($("body").hasClass("member")) {
      window.location.reload();
    }

    if (taskModalVisible) {
      _task_append_html(response.taskHtml);
    }

    if ($timerSelectTask.is(":visible")) {
      $timerSelectTask.find(".system-popup-close").click();
    }

    _init_timers_top_html(JSON.parse(response.timers));

    $(".popover-top-timer-note").popover("hide");
    reload_tasks_tables();
  });
}

// Init task modal and get data from server
function init_task_modal(task_id, comment_id) {
  var queryStr = "";
  var $leadModal = $("#lead-modal");
  var $taskAddEditModal = $("#_task_modal");
  if ($leadModal.is(":visible")) {
    queryStr +=
      "?opened_from_lead_id=" + $leadModal.find('input[name="leadid"]').val();
    $leadModal.modal("hide");
  } else if ($taskAddEditModal.attr("data-lead-id") != undefined) {
    queryStr +=
      "?opened_from_lead_id=" + $taskAddEditModal.attr("data-lead-id");
  }

  requestGet("tasks/get_task_data/" + task_id + queryStr)
    .done(function (response) {
      _task_append_html(response);
      if (typeof comment_id != "undefined") {
        setTimeout(function () {
          $('[data-task-comment-href-id="' + comment_id + '"]').click();
        }, 1000);
      }
    })
    .fail(function (data) {
      $("#task-modal").modal("hide");
      alert_float("danger", data.responseText);
    });
}

// General function to append task html returned from request
function _task_append_html(html) {
  var $taskModal = $("#task-modal");

  $taskModal.find(".data").html(html);
  //init_tasks_checklist_items(false, task_id);
  recalculate_checklist_items_progress();
  do_task_checklist_items_height();

  setTimeout(function () {
    $taskModal.modal("show");
    // Init_tags_input is trigged too when task modal is shown
    // This line prevents triggering twice.
    if ($taskModal.is(":visible")) {
      init_tags_inputs();
    }
    init_form_reminder("task");
    fix_task_modal_left_col_height();

    // Show the comment area on mobile when task modal is opened
    // Because the user may want only to upload file, but if the comment textarea is not focused the dropzone won't be shown

    if (is_mobile()) {
      init_new_task_comment(true);
    }
  }, 150);
}

// Tracking stats modal from task single
function task_tracking_stats(id) {
  requestGet("tasks/task_tracking_stats/" + id).done(function (response) {
    $("<div/>", {
      id: "tracking-stats",
    })
      .appendTo("body")
      .html(response);
    $("#task-tracking-stats-modal").modal("toggle");
  });
}

// Fetches all staff timers and append to DOM
function init_timers() {
  requestGetJSON("tasks/get_staff_started_timers").done(function (response) {
    _init_timers_top_html(response);
  });
}

// Top started timers dropdown init html data with class
function _init_timers_top_html(data) {
  var $tt = $("#top-timers");
  var $ttIcon = $("#top-timers").find(".icon-started-timers");
  data.total_timers > 0
    ? $ttIcon.removeClass("hide").html(data.total_timers)
    : $ttIcon.addClass("hide");

  data.total_timers > 0
    ? $("#top-timers").find("i").addClass("tw-animate-spin-slow")
    : $("#top-timers").find("i").removeClass("tw-animate-spin-slow");

  $("#started-timers-top").html(data.html);
}

// Init task edit comment
function edit_task_comment(id) {
  var edit_wrapper = $('[data-edit-comment="' + id + '"]');
  edit_wrapper.next().addClass("hide");
  edit_wrapper.removeClass("hide");

  tinymce.remove("#task_comment_" + id);
  var editorConfig = _simple_editor_config();
  editorConfig.auto_focus = "task_comment_" + id;
  editorConfig.toolbar_sticky  = true;
  init_editor("#task_comment_" + id, editorConfig);
  tinymce.triggerSave();
}

// Cancel editing commment after clicked on edit href
function cancel_edit_comment(id) {
  var edit_wrapper = $('[data-edit-comment="' + id + '"]');
  tinymce.remove('[data-edit-comment="' + id + '"] textarea');
  edit_wrapper.addClass("hide");
  edit_wrapper.next().removeClass("hide");
}

// Save task edited comment
function save_edited_comment(id, task_id) {
  tinymce.triggerSave();
  var data = {};
  data.id = id;
  data.task_id = task_id;
  data.content = $('[data-edit-comment="' + id + '"]')
    .find("textarea")
    .val();
  if (is_ios()) {
    data.no_editor = true;
  }
  $.post(admin_url + "tasks/edit_comment", data).done(function (response) {
    response = JSON.parse(response);
    if (response.success === true || response.success == "true") {
      alert_float("success", response.message);
      _task_append_html(response.taskHtml);
    } else {
      cancel_edit_comment(id);
    }
    tinymce.remove('[data-edit-comment="' + id + '"] textarea');
  });
}

// Fix task single modal height to be on both sides the same
function fix_task_modal_left_col_height() {
  if (!is_mobile()) {
    $("body")
      .find(".task-single-col-left")
      .css(
        "min-height",
        $("body").find(".task-single-col-right").outerHeight(true) + "px"
      );
  }
}

// Updates task when action performed form kan ban area eq status changed.
function tasks_kanban_update(ui, object) {
  if (object === ui.item.parent()[0]) {
    var status = $(ui.item.parent()[0]).attr("data-task-status-id");

    var data = {
      order: [],
      status: status,
    };

    $.each($(ui.item.parent()[0]).find("[data-task-id]"), function (idx, el) {
      var id = $(el).attr("data-task-id");
      if (id) {
        data.order.push([id, idx + 1]);
      }
    });

    task_mark_as(status, $(ui.item).attr("data-task-id"));

    check_kanban_empty_col("[data-task-id]");

    setTimeout(function () {
      $.post(admin_url + "tasks/update_order", data).done(function (response) {
        update_kan_ban_total_when_moving(ui, data.status);
        tasks_kanban();
      });
    }, 200);
  }
}

// Init tasks kan ban
function tasks_kanban() {
  init_kanban("tasks/kanban", tasks_kanban_update, ".tasks-status", 240, 360);
}

// Task single edit description with inline editor, used from task single modal
function edit_task_inline_description(e, id) {
  tinyMCE.remove("#task_view_description");

  if ($(e).hasClass("editor-initiated")) {
    $(e).removeClass("editor-initiated");
    return;
  }

  $(e).addClass("editor-initiated");

  $.Shortcuts.stop();

  tinymce.init({
    branding: false,
    toolbar: false,
    menubar: false,
    inline: true,
    cache_suffix: '?v='+app.version,
    selector: "#task_view_description",
    theme: "silver",
    directionality: isRTL == "true" ? "rtl" : "",
    auto_focus: "task_view_description",
    plugins: ['quickbars', 'link', 'table', (isRTL == "true" ? " directionality" : "")],
    contextmenu: "link table paste pastetext",
    quickbars_insert_toolbar: "quicktable",
    quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote",
    table_default_styles: {
      width: "100%",
    },
    setup: function (editor) {
      editor.on("blur", function (e) {
        if (editor.isDirty()) {
          $.post(admin_url + "tasks/update_task_description/" + id, {
            description: editor.getContent(),
          });
        }

        setTimeout(function () {
          editor.remove();
          $.Shortcuts.start();
        }, 500);
      });
    },
  });
}

// Tasks bulk actions action
function tasks_bulk_action(event) {
  if (confirm_delete()) {
    var ids = [],
      data = {},
      mass_delete = $("#mass_delete").prop("checked");
    if (mass_delete == false || typeof mass_delete == "undefined") {
      data.status = $("#move_to_status_tasks_bulk_action").val();

      var assignees = $("#task_bulk_assignees");
      data.assignees = assignees.length ? assignees.selectpicker("val") : "";

      var tags_bulk = $("#tags_bulk");
      data.tags = tags_bulk.length ? tags_bulk.tagit("assignedTags") : "";

      var milestone = $("#task_bulk_milestone");
      data.milestone = milestone.length ? milestone.selectpicker("val") : "";

      data.billable = $("#task_bulk_billable").val();
      data.billable = typeof data.billable == "undefined" ? "" : data.billable;

      data.priority = $("#task_bulk_priority").val();
      data.priority = typeof data.priority == "undefined" ? "" : data.priority;

      if (
        data.status === "" &&
        data.priority === "" &&
        data.tags === "" &&
        data.assignees === "" &&
        data.milestone === "" &&
        data.billable === ""
      ) {
        return;
      }
    } else {
      data.mass_delete = true;
    }
    var rows = $($("#tasks_bulk_actions").attr("data-table")).find("tbody tr");
    $.each(rows, function () {
      var checkbox = $($(this).find("td").eq(0)).find("input");
      if (checkbox.prop("checked") === true) {
        ids.push(checkbox.val());
      }
    });
    data.ids = ids;
    $(event).addClass("disabled");
    setTimeout(function () {
      $.post(admin_url + "tasks/bulk_action", data).done(function () {
        window.location.reload();
      });
    }, 200);
  }
}

function load_small_table_item(id, selector, input_name, url, table) {
  var _tmpID = $('input[name="' + input_name + '"]').val();
  // Check if id passed from url, hash is prioritized becuase is last
  if (_tmpID !== "" && !window.location.hash) {
    id = _tmpID;
    // Clear the current id value in case user click on the left sidebar credit_note_ids
    $('input[name="' + input_name + '"]').val("");
  } else {
    // check first if hash exists and not id is passed, becuase id is prioritized
    if (window.location.hash && !id) {
      id = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
    }
  }
  if (typeof id == "undefined" || id === "") {
    return;
  }
  destroy_dynamic_scripts_in_element($(selector));
  if (!$("body").hasClass("small-table")) {
    toggle_small_view(table, selector);
  }
  $('input[name="' + input_name + '"]').val(id);
  do_hash_helper(id);
  $(selector).load(admin_url + url + "/" + id)

  $("html, body").animate(
    {
      scrollTop: $(selector).offset().top + (is_mobile() ? 150 : 0),
    },
    600
  );
}

// Init single invoice
function init_invoice(id) {
  load_small_table_item(
    id,
    "#invoice",
    "invoiceid",
    "invoices/get_invoice_data_ajax",
    ".table-invoices"
  );
}

// Init single credit note
function init_credit_note(id) {
  load_small_table_item(
    id,
    "#credit_note",
    "credit_note_id",
    "credit_notes/get_credit_note_data_ajax",
    ".table-credit-notes"
  );
}

//Init single debit note
function init_debit_note(id) {
  load_small_table_item(
    id,
    "#debit_note",
    "debit_note_id",
    "debit_notes/get_debit_note_data_ajax",
    ".table-debit-notes"
  );
}

// Init single estimate
function init_estimate(id) {
  load_small_table_item(
    id,
    "#estimate",
    "estimateid",
    "estimates/get_estimate_data_ajax",
    ".table-estimates"
  );
}

// Init single proposal
function init_proposal(id) {
  load_small_table_item(
    id,
    "#proposal",
    "proposal_id",
    "proposals/get_proposal_data_ajax",
    ".table-proposals"
  );
}

function init_expense(id) {
  load_small_table_item(
    id,
    "#expense",
    "expenseid",
    "expenses/get_expense_data_ajax",
    ".table-expenses"
  );
}

// Clear billing and shipping inputs for invoice,estimate etc...
function clear_billing_and_shipping_details() {
  for (var f in billingAndShippingFields) {
    if (billingAndShippingFields[f].indexOf("country") > -1) {
      $('select[name="' + billingAndShippingFields[f] + '"]').selectpicker(
        "val",
        ""
      );
    } else {
      $('input[name="' + billingAndShippingFields[f] + '"]').val("");
      $('textarea[name="' + billingAndShippingFields[f] + '"]').val("");
    }
    if (billingAndShippingFields[f] == "billing_country") {
      $('input[name="include_shipping"]').prop("checked", false);
      $('input[name="include_shipping"]').change();
    }
  }

  init_billing_and_shipping_details();
}

// Init billing and shipping details for invoice, estimate etc...
function init_billing_and_shipping_details() {
  var _f;
  var include_shipping = $('input[name="include_shipping"]').prop("checked");

  for (var f in billingAndShippingFields) {
    _f = "";
    if (billingAndShippingFields[f].indexOf("country") > -1) {
      _f = $("#" + billingAndShippingFields[f] + " option:selected").data(
        "subtext"
      );
    } else if (
      billingAndShippingFields[f].indexOf("shipping_street") > -1 ||
      billingAndShippingFields[f].indexOf("billing_street") > -1
    ) {
      if ($('textarea[name="' + billingAndShippingFields[f] + '"]').length) {
        _f = $('textarea[name="' + billingAndShippingFields[f] + '"]')
          .val()
          .replace(/(?:\r\n|\r|\n)/g, "<br />");
      }
    } else {
      _f = $('input[name="' + billingAndShippingFields[f] + '"]').val();
    }
    if (billingAndShippingFields[f].indexOf("shipping") > -1) {
      if (!include_shipping) {
        _f = "";
      }
    }
    if (typeof _f == "undefined") {
      _f = "";
    }
    _f = _f !== "" ? _f : "--";
    $("." + billingAndShippingFields[f]).html(_f);
  }
  $("#billing_and_shipping_details").modal("hide");
}

// Record payment function
function record_payment(id) {
  if (typeof id == "undefined" || id === "") {
    return;
  }
  $("#invoice").load(admin_url + "invoices/record_invoice_payment_ajax/" + id);
}

function schedule_invoice_send(id) {
  $("#invoice").load(admin_url + "email_schedule_invoice/create/" + id);
}

function schedule_estimate_send(id) {
  $("#estimate").load(admin_url + "email_schedule_estimate/create/" + id);
}

function edit_invoice_scheduled_email(schedule_id) {
  $("#invoice").load(admin_url + "email_schedule_invoice/edit/" + schedule_id);
}

function edit_estimate_scheduled_email(schedule_id) {
  $("#estimate").load(
    admin_url + "email_schedule_estimate/edit/" + schedule_id
  );
}

// Add item to preview
function add_item_to_preview(id) {
  requestGetJSON("invoice_items/get_item_by_id/" + id).done(function (
    response
  ) {
    clear_item_preview_values();

    $('.main textarea[name="description"]').val(response.description);
    $('.main textarea[name="long_description"]').val(
      response.long_description.replace(/(<|&lt;)br\s*\/*(>|&gt;)/g, " ")
    );

    _set_item_preview_custom_fields_array(response.custom_fields);

    $('.main input[name="quantity"]').val(1);

    var taxSelectedArray = [];
    if (response.taxname && response.taxrate) {
      taxSelectedArray.push(response.taxname + "|" + response.taxrate);
    }
    if (response.taxname_2 && response.taxrate_2) {
      taxSelectedArray.push(response.taxname_2 + "|" + response.taxrate_2);
    }

    $(".main select.tax").selectpicker("val", taxSelectedArray);
    $('.main input[name="unit"]').val(response.unit);

    var $currency = $("body").find(
      '.accounting-template select[name="currency"]'
    );
    var baseCurency = $currency.attr("data-base");
    var selectedCurrency = $currency.find("option:selected").val();
    var $rateInputPreview = $('.main input[name="rate"]');

    if (baseCurency == selectedCurrency) {
      $rateInputPreview.val(response.rate);
    } else {
      var itemCurrencyRate = response["rate_currency_" + selectedCurrency];
      if (!itemCurrencyRate || parseFloat(itemCurrencyRate) === 0) {
        $rateInputPreview.val(response.rate);
      } else {
        $rateInputPreview.val(itemCurrencyRate);
      }
    }

    $(document).trigger({
      type: "item-added-to-preview",
      item: response,
      item_type: "item",
    });
  });
}

function _set_item_preview_custom_fields_array(custom_fields) {
  var cf_act_as_inputs = [
    "input",
    "number",
    "date_picker",
    "date_picker_time",
    "colorpicker",
  ];

  for (var i = 0; i < custom_fields.length; i++) {
    var cf = custom_fields[i];
    if ($.inArray(cf.type, cf_act_as_inputs) > -1) {
      var f = $('tr.main td[data-id="' + cf.id + '"] input');
      // trigger change eq. for colorpicker
      f.val(cf.value).trigger("change");
    } else if (cf.type == "textarea") {
      $('tr.main td[data-id="' + cf.id + '"] textarea').val(cf.value);
    } else if (cf.type == "select" || cf.type == "multiselect") {
      if (!empty(cf.value)) {
        var selected = cf.value.split(",");
        selected = selected.map(function (e) {
          return e.trim();
        });
        $('tr.main td[data-id="' + cf.id + '"] select').selectpicker(
          "val",
          selected
        );
      }
    } else if (cf.type == "checkbox") {
      if (!empty(cf.value)) {
        var selected = cf.value.split(",");
        selected = selected.map(function (e) {
          return e.trim();
        });
        $.each(selected, function (i, e) {
          $(
            'tr.main td[data-id="' +
              cf.id +
              '"] input[type="checkbox"][value="' +
              e +
              '"]'
          ).prop("checked", true);
        });
      }
    }
  }
}
// Add task to preview
function add_task_to_preview_as_item(id) {
  requestGetJSON("tasks/get_billable_task_data/" + id).done(function (
    response
  ) {
    response.taxname = $("select.main-tax").selectpicker("val");
    var previewArea = $(".main");
    previewArea.find('textarea[name="description"]').val(response.name);
    previewArea
      .find('textarea[name="long_description"]')
      .val(response.description);
    previewArea.find('input[name="quantity"]').val(response.total_hours);
    previewArea.find('input[name="rate"]').val(response.hourly_rate);
    previewArea.find('input[name="unit"]').val("");
    $('input[name="task_id"]').val(id);
    $(document).trigger({
      type: "item-added-to-preview",
      item: response,
      item_type: "task",
    });
  });
}

// Clear the items added to preview
function clear_item_preview_values(default_taxes) {
  // Get the last taxes applied to be available for the next item
  var last_taxes_applied = $("table.items tbody")
    .find("tr:last-child")
    .find("select")
    .selectpicker("val");
  var previewArea = $(".main");

  previewArea.find("textarea").val(""); // includes cf
  previewArea
    .find('td.custom_field input[type="checkbox"]')
    .prop("checked", false); // cf
  previewArea.find("td.custom_field input:not(:checkbox):not(:hidden)").val(""); // cf // not hidden for chkbox hidden helpers
  previewArea.find("td.custom_field select").selectpicker("val", ""); // cf
  previewArea.find('input[name="quantity"]').val(1);
  previewArea.find("select.tax").selectpicker("val", last_taxes_applied);
  previewArea.find('input[name="rate"]').val("");
  previewArea.find('input[name="unit"]').val("");

  $('input[name="task_id"]').val("");
  $('input[name="expense_id"]').val("");
}

// Append the added items to the preview to the table as items
function add_item_to_table(data, itemid, merge_invoice, bill_expense) {
  // If not custom data passed get from the preview
  data =
    typeof data == "undefined" || data == "undefined"
      ? get_item_preview_values()
      : data;
  if (
    data.description === "" &&
    data.long_description === "" &&
    data.rate === ""
  ) {
    return;
  }

  var table_row = "";
  var item_key = lastAddedItemKey
    ? (lastAddedItemKey += 1)
    : $("body").find("tbody .item").length + 1;
  lastAddedItemKey = item_key;

  table_row +=
    '<tr class="sortable item" data-merge-invoice="' +
    merge_invoice +
    '" data-bill-expense="' +
    bill_expense +
    '">';

  table_row += '<td class="dragger">';

  // Check if quantity is number
  if (isNaN(data.qty)) {
    data.qty = 1;
  }

  // Check if rate is number
  if (data.rate === "" || isNaN(data.rate)) {
    data.rate = 0;
  }

  var amount = data.rate * data.qty;

  var tax_name = "newitems[" + item_key + "][taxname][]";
  $("body").append('<div class="dt-loader"></div>');
  var regex = /<br[^>]*>/gi;
  get_taxes_dropdown_template(tax_name, data.taxname).done(function (
    tax_dropdown
  ) {
    // order input
    table_row +=
      '<input type="hidden" class="order" name="newitems[' +
      item_key +
      '][order]">';

    table_row += "</td>";

    table_row +=
      '<td class="bold description"><textarea name="newitems[' +
      item_key +
      '][description]" class="form-control" rows="5">' +
      data.description +
      "</textarea></td>";

    table_row +=
      '<td><textarea name="newitems[' +
      item_key +
      '][long_description]" class="form-control item_long_description" rows="5">' +
      data.long_description.replace(regex, "\n") +
      "</textarea></td>";

    var custom_fields = $("tr.main td.custom_field");
    var cf_has_required = false;

    if (custom_fields.length > 0) {
      $.each(custom_fields, function () {
        var cf = $(this).clone();
        var cf_html = "";
        var cf_field = $(this).find("[data-fieldid]");
        var cf_name =
          "newitems[" +
          item_key +
          "][custom_fields][items][" +
          cf_field.attr("data-fieldid") +
          "]";

        if (cf_field.is(":checkbox")) {
          var checked = $(this).find('input[type="checkbox"]:checked');
          var checkboxes = cf.find('input[type="checkbox"]');

          $.each(checkboxes, function (i, e) {
            var random_key = Math.random().toString(20).slice(2);
            $(this)
              .attr("id", random_key)
              .attr("name", cf_name)
              .next("label")
              .attr("for", random_key);
            if ($(this).attr("data-custom-field-required") == "1") {
              cf_has_required = true;
            }
          });

          $.each(checked, function (i, e) {
            cf.find('input[value="' + $(e).val() + '"]').attr("checked", true);
          });

          cf_html = cf.html();
        } else if (cf_field.is("input") || cf_field.is("textarea")) {
          if (cf_field.is("input")) {
            cf.find("[data-fieldid]").attr("value", cf_field.val());
          } else {
            cf.find("[data-fieldid]").html(cf_field.val());
          }
          cf.find("[data-fieldid]").attr("name", cf_name);
          if (
            cf.find("[data-fieldid]").attr("data-custom-field-required") == "1"
          ) {
            cf_has_required = true;
          }
          cf_html = cf.html();
        } else if (cf_field.is("select")) {
          if ($(cf_field).attr("data-custom-field-required") == "1") {
            cf_has_required = true;
          }

          var selected = $(this)
            .find("select[data-fieldid]")
            .selectpicker("val");
          selected = typeof (selected != "array")
            ? new Array(selected)
            : selected;

          // Check if is multidimensional by multi-select customfield
          selected = selected[0].constructor === Array ? selected[0] : selected;

          var selectNow = cf.find("select");
          var $wrapper = $("<div/>");
          selectNow.attr("name", cf_name);

          var $select = selectNow.clone();
          $select.prop('required', 1);
          $wrapper.append($select);
          $.each(selected, function (i, e) {
            $wrapper
              .find('select option[value="' + e + '"]')
              .attr("selected", true);
          });

          cf_html = $wrapper.html();
        }
        table_row += '<td class="custom_field">' + cf_html + "</td>";
      });
    }

    table_row +=
      '<td><input type="number" min="0" onblur="calculate_total();" onchange="calculate_total();" data-quantity name="newitems[' +
      item_key +
      '][qty]" value="' +
      data.qty +
      '" class="form-control">';

    if (!data.unit || typeof data.unit == "undefined") {
      data.unit = "";
    }

    table_row +=
      '<input type="text" placeholder="' +
      app.lang.unit +
      '" name="newitems[' +
      item_key +
      '][unit]" class="form-control input-transparent text-right" value="' +
      data.unit +
      '">';

    table_row += "</td>";

    table_row +=
      '<td class="rate"><input type="number" data-toggle="tooltip" title="' +
      app.lang.item_field_not_formatted +
      '" onblur="calculate_total();" onchange="calculate_total();" name="newitems[' +
      item_key +
      '][rate]" value="' +
      data.rate +
      '" class="form-control"></td>';

    table_row += '<td class="taxrate">' + tax_dropdown + "</td>";

    table_row +=
      '<td class="amount" align="right">' +
      format_money(amount, true) +
      "</td>";

    table_row +=
      '<td><a href="#" class="btn btn-danger pull-left !tw-px-3" onclick="delete_item(this,' +
      itemid +
      '); return false;"><i class="fa fa-trash"></i></a></td>';

    table_row += "</tr>";

    $("table.items tbody").append(table_row);

    $(document).trigger({
      type: "item-added-to-table",
      data: data,
      row: table_row,
    });

    setTimeout(function () {
      calculate_total();
    }, 15);

    var billed_task = $('input[name="task_id"]').val();
    var billed_expense = $('input[name="expense_id"]').val();

    if (billed_task !== "" && typeof billed_task != "undefined") {
      billed_tasks = billed_task.split(",");
      $.each(billed_tasks, function (i, obj) {
        $("#billed-tasks").append(
          hidden_input("billed_tasks[" + item_key + "][]", obj)
        );
      });
    }

    if (billed_expense !== "" && typeof billed_expense != "undefined") {
      billed_expenses = billed_expense.split(",");
      $.each(billed_expenses, function (i, obj) {
        $("#billed-expenses").append(
          hidden_input("billed_expenses[" + item_key + "][]", obj)
        );
      });
    }

    if (
      $("#item_select").hasClass("ajax-search") &&
      $("#item_select").selectpicker("val") !== ""
    ) {
      $("#item_select").prepend("<option></option>");
    }

    init_selectpicker();
    init_datepicker();
    init_color_pickers();
    clear_item_preview_values();
    reorder_items();

    $("body").find("#items-warning").remove();
    $("body").find(".dt-loader").remove();
    $("#item_select").selectpicker("val", "");

    if (cf_has_required && $(".invoice-form").length) {
      validate_invoice_form();
    } else if (cf_has_required && $(".estimate-form").length) {
      validate_estimate_form();
    } else if (cf_has_required && $(".proposal-form").length) {
      validate_proposal_form();
    } else if (cf_has_required && $(".credit-note-form").length) {
      validate_credit_note_form();
    }else if (cf_has_required && $(".debit-note-form").length) {
      validate_debit_note_form();
    }

    if (bill_expense == "undefined" || !bill_expense) {
      $('select[name="task_select"]')
        .find('[value="' + billed_task + '"]')
        .remove();
      $('select[name="task_select"]').selectpicker("refresh");
    }
    return true;
  });

  return false;
}

// Get taxes dropdown selectpicker template
function get_taxes_dropdown_template(name, taxname) {
  return $.post(admin_url + "misc/get_taxes_dropdown_template", {
    name: name,
    taxname: taxname,
  });
}

// Custom function for deselecting selected value from ajax dropdown
function deselect_ajax_search(e) {
  var $elm = $("select#" + $(e).attr("data-id"));
  $elm.data("AjaxBootstrapSelect").list.cache = {};
  var $elmWrapper = $elm.parents(".bootstrap-select");
  $elm
    .html("")
    .append('<option value=""></option>')
    .selectpicker("val", $elm.attr("multiple") == "multiple" ? [] : "");
  $elmWrapper
    .removeClass("ajax-remove-values-option")
    .find(".ajax-clear-values")
    .remove();
  setTimeout(function () {
    $elm.trigger("selected.cleared.ajax.bootstrap.select", e);
    $elm.trigger("change").data("AjaxBootstrapSelect").list.cache = {};
  }, 50);
}

// Ajax project search but only for specific customer
function init_ajax_project_search_by_customer_id(selector) {
  selector =
    typeof selector == "undefined" ? "#project_id.ajax-search" : selector;
  init_ajax_search("project", selector, {
    customer_id: function () {
      return $("#clientid").val();
    },
  });
}

// Ajax project search select
function init_ajax_projects_search(selector) {
  selector =
    typeof selector == "undefined" ? "#project_id.ajax-search" : selector;
  init_ajax_search("project", selector);
}

// Make items sortable with jquery sort plugin
function init_items_sortable(preview_table) {
  var _items_sortable = $("#wrapper").find(".items tbody");

  if (_items_sortable.length === 0) {
    return;
  }
  _items_sortable.sortable({
    helper: fixHelperTableHelperSortable,
    handle: ".dragger",
    placeholder: "ui-placeholder",
    itemPath: "> tbody",
    itemSelector: "tr.sortable",
    items: "tr.sortable",
    update: function () {
      if (typeof preview_table == "undefined") {
        reorder_items();
      } else {
        // If passed from the admin preview there is other function for re-ordering
        save_ei_items_order();
      }
    },
    sort: function (event, ui) {
      // Firefox fixer when dragging
      var $target = $(event.target);
      if (!/html|body/i.test($target.offsetParent()[0].tagName)) {
        var top =
          event.pageY -
          $target.offsetParent().offset().top -
          ui.helper.outerHeight(true) / 2;
        ui.helper.css({
          top: top + "px",
        });
      }
    },
  });
}

// Save the items from order from the admin preview
function save_ei_items_order() {
  var table = $(".table.items-preview");
  var rows = table.find("tbody tr");
  var i = 1,
    type = table.attr("data-type"),
    order = [],
    _order_id,
    item_id;

  if (!type) {
    return false;
  }

  $.each(rows, function () {
    order.push([$(this).data("item-id"), i]);
    // update item number when reordering
    $(this).find("td.item_no").html(i);
    i++;
  });

  setTimeout(function () {
    $.post(admin_url + "misc/update_ei_items_order/" + type, {
      data: order,
    });
  }, 200);
}

// Reoder the items in table edit for estimate and invoices
function reorder_items() {
  var rows = $(".table.has-calculations tbody tr.item");
  var i = 1;
  $.each(rows, function () {
    $(this).find("input.order").val(i);
    i++;
  });
}

// Get the preview main values
function get_item_preview_values() {
  var response = {};
  response.description = $('.main textarea[name="description"]').val();
  response.long_description = $(
    '.main textarea[name="long_description"]'
  ).val();
  response.qty = $('.main input[name="quantity"]').val();
  response.taxname = $(".main select.tax").selectpicker("val");
  response.rate = $('.main input[name="rate"]').val();
  response.unit = $('.main input[name="unit"]').val();
  return response;
}

// Calculate invoice total - NOT RECOMENDING EDIT THIS FUNCTION BECUASE IS VERY SENSITIVE
function calculate_total() {
  if ($("body").hasClass("no-calculate-total")) {
    return false;
  }

  var calculated_tax,
    taxrate,
    item_taxes,
    row,
    _amount,
    _tax_name,
    taxes = {},
    taxes_rows = [],
    subtotal = 0,
    total = 0,
    quantity = 1,
    total_discount_calculated = 0,
    rows = $(".table.has-calculations tbody tr.item"),
    discount_area = $("#discount_area"),
    adjustment = $('input[name="adjustment"]').val(),
    discount_percent = $('input[name="discount_percent"]').val(),
    discount_fixed = $('input[name="discount_total"]').val(),
    discount_total_type = $(".discount-total-type.selected"),
    discount_type = $('select[name="discount_type"]').val();

  $(".tax-area").remove();

  $.each(rows, function () {
    quantity = $(this).find("[data-quantity]").val();
    if (quantity === "") {
      quantity = 1;
      $(this).find("[data-quantity]").val(1);
    }

    _amount = accounting.toFixed(
      $(this).find("td.rate input").val() * quantity,
      app.options.decimal_places
    );
    _amount = parseFloat(_amount);

    $(this).find("td.amount").html(format_money(_amount, true));
    subtotal += _amount;
    row = $(this);
    item_taxes = $(this).find("select.tax").selectpicker("val");

    if (item_taxes) {
      $.each(item_taxes, function (i, taxname) {
        taxrate = row
          .find('select.tax [value="' + taxname + '"]')
          .data("taxrate");
        calculated_tax = (_amount / 100) * taxrate;
        if (!taxes.hasOwnProperty(taxname)) {
          if (taxrate != 0) {
            _tax_name = taxname.split("|");
            tax_row =
              '<tr class="tax-area"><td>' +
              _tax_name[0] +
              "(" +
              taxrate +
              '%)</td><td id="tax_id_' +
              slugify(taxname) +
              '"></td></tr>';
            $(discount_area).after(tax_row);
            taxes[taxname] = calculated_tax;
          }
        } else {
          // Increment total from this tax
          taxes[taxname] = taxes[taxname] += calculated_tax;
        }
      });
    }
  });

  // Discount by percent
  if (
    discount_percent !== "" &&
    discount_percent != 0 &&
    discount_type == "before_tax" &&
    discount_total_type.hasClass("discount-type-percent")
  ) {
    total_discount_calculated = (subtotal * discount_percent) / 100;
  } else if (
    discount_fixed !== "" &&
    discount_fixed != 0 &&
    discount_type == "before_tax" &&
    discount_total_type.hasClass("discount-type-fixed")
  ) {
    total_discount_calculated = discount_fixed;
  }

  $.each(taxes, function (taxname, total_tax) {
    if (
      discount_percent !== "" &&
      discount_percent != 0 &&
      discount_type == "before_tax" &&
      discount_total_type.hasClass("discount-type-percent")
    ) {
      total_tax_calculated = (total_tax * discount_percent) / 100;
      total_tax = total_tax - total_tax_calculated;
    } else if (
      discount_fixed !== "" &&
      discount_fixed != 0 &&
      discount_type == "before_tax" &&
      discount_total_type.hasClass("discount-type-fixed")
    ) {
      var t = (discount_fixed / subtotal) * 100;
      total_tax = total_tax - (total_tax * t) / 100;
    }

    total += total_tax;
    total_tax = format_money(total_tax);
    $("#tax_id_" + slugify(taxname)).html(total_tax);
  });

  total = total + subtotal;

  // Discount by percent
  if (
    discount_percent !== "" &&
    discount_percent != 0 &&
    discount_type == "after_tax" &&
    discount_total_type.hasClass("discount-type-percent")
  ) {
    total_discount_calculated = (total * discount_percent) / 100;
  } else if (
    discount_fixed !== "" &&
    discount_fixed != 0 &&
    discount_type == "after_tax" &&
    discount_total_type.hasClass("discount-type-fixed")
  ) {
    total_discount_calculated = discount_fixed;
  }

  total = total - total_discount_calculated;
  adjustment = parseFloat(adjustment);

  // Check if adjustment not empty
  if (!isNaN(adjustment)) {
    total = total + adjustment;
  }

  var discount_html = "-" + format_money(total_discount_calculated);
  $('input[name="discount_total"]').val(
    accounting.toFixed(total_discount_calculated, app.options.decimal_places)
  );

  // Append, format to html and display
  $(".discount-total").html(discount_html);
  $(".adjustment").html(format_money(adjustment));
  $(".subtotal").html(
    format_money(subtotal) +
      hidden_input(
        "subtotal",
        accounting.toFixed(subtotal, app.options.decimal_places)
      )
  );
  $(".total").html(
    format_money(total) +
      hidden_input(
        "total",
        accounting.toFixed(total, app.options.decimal_places)
      )
  );

  $(document).trigger("sales-total-calculated");
}

function exclude_tax_from_amount(tax_percent, total_amount) {
  totalTax = accounting.toFixed(
    (total_amount * tax_percent) / (100 + tax_percent),
    app.options.decimal_places
  );
  return accounting.toFixed(
    total_amount - totalTax,
    app.options.decimal_places
  );
}

// Deletes invoice items
function delete_item(row, itemid) {
  $(row)
    .parents("tr")
    .addClass("animated fadeOut", function () {
      setTimeout(function () {
        $(row).parents("tr").remove();
        calculate_total();
      }, 50);
    });

  // If is edit we need to add to input removed_items to track activity
  if (itemid && $('input[name="isedit"]').length > 0) {
    $("#removed-items").append(hidden_input("removed_items[]", itemid));
  }
}

// Format money function
function format_money(total, excludeSymbol) {
  if (typeof excludeSymbol != "undefined" && excludeSymbol) {
    return accounting.formatMoney(total, {
      symbol: "",
    });
  }

  return accounting.formatMoney(total);
}

// Set the currency for accounting
function init_currency(id, callback) {
  var $accountingTemplate = $("body").find(".accounting-template");

  if ($accountingTemplate.length || id) {
    var selectedCurrencyId = !id
      ? $accountingTemplate.find('select[name="currency"]').val()
      : id;

    requestGetJSON("misc/get_currency/" + selectedCurrencyId).done(function (
      currency
    ) {
      // Used for formatting money
      accounting.settings.currency.decimal = currency.decimal_separator;
      accounting.settings.currency.thousand = currency.thousand_separator;
      accounting.settings.currency.symbol = currency.symbol;
      accounting.settings.currency.format =
        currency.placement == "after" ? "%v %s" : "%s%v";
      calculate_total();

      if (callback) {
        callback();
      }
    });
  }
}

// Delete invoice attachment
function delete_invoice_attachment(id) {
  if (confirm_delete()) {
    requestGet("invoices/delete_attachment/" + id)
      .done(function (success) {
        if (success == 1) {
          $("body")
            .find('[data-attachment-id="' + id + '"]')
            .remove();
          init_invoice(
            $("body").find('input[name="_attachment_sale_id"]').val()
          );
        }
      })
      .fail(function (error) {
        alert_float("danger", error.responseText);
      });
  }
}

// Delete credit note attachment
function delete_credit_note_attachment(id) {
  if (confirm_delete()) {
    requestGet("credit_notes/delete_attachment/" + id)
      .done(function (success) {
        if (success == 1) {
          $("body")
            .find('[data-attachment-id="' + id + '"]')
            .remove();
          init_credit_note(
            $("body").find('input[name="_attachment_sale_id"]').val()
          );
        }
      })
      .fail(function (error) {
        alert_float("danger", error.responseText);
      });
  }
}
// Delete debit note attachment
function delete_debit_note_attachment(id) {
  if (confirm_delete()) {
    requestGet("debit_notes/delete_attachment/" + id)
      .done(function (success) {
        if (success == 1) {
          $("body")
            .find('[data-attachment-id="' + id + '"]')
            .remove();
          init_debit_note(
            $("body").find('input[name="_attachment_sale_id"]').val()
          );
        }
      })
      .fail(function (error) {
        alert_float("danger", error.responseText);
      });
  }
}
// Delete estimate attachment
function delete_estimate_attachment(id) {
  if (confirm_delete()) {
    requestGet("estimates/delete_attachment/" + id)
      .done(function (success) {
        if (success == 1) {
          $("body")
            .find('[data-attachment-id="' + id + '"]')
            .remove();
          var rel_id = $("body")
            .find('input[name="_attachment_sale_id"]')
            .val();
          $("body").hasClass("estimates-pipeline")
            ? estimate_pipeline_open(rel_id)
            : init_estimate(rel_id);
        }
      })
      .fail(function (error) {
        alert_float("danger", error.responseText);
      });
  }
}

// Delete proposal attachment
function delete_proposal_attachment(id) {
  if (confirm_delete()) {
    requestGet("proposals/delete_attachment/" + id)
      .done(function (success) {
        if (success == 1) {
          var rel_id = $("body")
            .find('input[name="_attachment_sale_id"]')
            .val();
          $("body")
            .find('[data-attachment-id="' + id + '"]')
            .remove();
          $("body").hasClass("proposals-pipeline")
            ? proposal_pipeline_open(rel_id)
            : init_proposal(rel_id);
        }
      })
      .fail(function (error) {
        alert_float("danger", error.responseText);
      });
  }
}

// Invoices quick total stats
function init_invoices_total(manual) {
  var _inv_total_wrapper = $("#invoices_total");

  if (_inv_total_wrapper.length === 0) {
    return;
  }
  var _inv_total_inline = $(".invoices-total-inline");
  var _inv_total_href_manual = $(".invoices-total");

  if (
    $("body").hasClass("invoices-total-manual") &&
    typeof manual == "undefined" &&
    !_inv_total_href_manual.hasClass("initialized")
  ) {
    return;
  }

  if (
    _inv_total_inline.length > 0 &&
    _inv_total_href_manual.hasClass("initialized")
  ) {
    // On the next request won't be inline in case of currency change
    // Used on dashboard
    _inv_total_inline.removeClass("invoices-total-inline");
    return;
  }

  _inv_total_href_manual.addClass("initialized");
  var _years = $("body")
    .find('select[name="invoices_total_years"]')
    .selectpicker("val");
  var years = [];
  $.each(_years, function (i, _y) {
    if (_y !== "") {
      years.push(_y);
    }
  });

  var currency = $("body").find('select[name="total_currency"]').val();
  
  var data = {
    currency: currency,
    years: years,
    init_total: true,
    display_type: _inv_total_wrapper.attr('data-type')
  };

  var project_id = $('input[name="project_id"]').val();
  var customer_id = $('.customer_profile input[name="userid"]').val();
  if (typeof project_id != "undefined") {
    data.project_id = project_id;
  } else if (typeof customer_id != "undefined") {
    data.customer_id = customer_id;
  }
  $.post(admin_url + "invoices/get_invoices_total", data).done(function (
    response
  ) {
    _inv_total_wrapper.html(response);
  });
}

// Estimates quick total stats
function init_estimates_total(manual) {
  if ($("#estimates_total").length === 0) {
    return;
  }
  var _est_total_href_manual = $(".estimates-total");
  if (
    $("body").hasClass("estimates-total-manual") &&
    typeof manual == "undefined" &&
    !_est_total_href_manual.hasClass("initialized")
  ) {
    return;
  }
  _est_total_href_manual.addClass("initialized");
  var currency = $("body").find('select[name="total_currency"]').val();
  var _years = $("body")
    .find('select[name="estimates_total_years"]')
    .selectpicker("val");
  var years = [];
  $.each(_years, function (i, _y) {
    if (_y !== "") {
      years.push(_y);
    }
  });

  var customer_id = "";
  var project_id = "";

  var _customer_id = $('.customer_profile input[name="userid"]').val();
  var _project_id = $('input[name="project_id"]').val();
  if (typeof _customer_id != "undefined") {
    customer_id = _customer_id;
  } else if (typeof _project_id != "undefined") {
    project_id = _project_id;
  }

  $.post(admin_url + "estimates/get_estimates_total", {
    currency: currency,
    init_total: true,
    years: years,
    customer_id: customer_id,
    project_id: project_id,
  }).done(function (response) {
    $("#estimates_total").html(response);
  });
}

// Expenses quick total stats
function init_expenses_total() {
  if ($("#expenses_total").length === 0) {
    return;
  }
  var currency = $("body").find('select[name="expenses_total_currency"]').val();
  var _years = $("body")
    .find('select[name="expenses_total_years"]')
    .selectpicker("val");
  var years = [];
  $.each(_years, function (i, _y) {
    if (_y !== "") {
      years.push(_y);
    }
  });

  var customer_id = "";
  var _customer_id = $('.customer_profile input[name="userid"]').val();
  if (typeof customer_id != "undefined") {
    customer_id = _customer_id;
  }

  var project_id = "";
  var _project_id = $('input[name="project_id"]').val();
  if (typeof project_id != "undefined") {
    project_id = _project_id;
  }

  $.post(admin_url + "expenses/get_expenses_total", {
    currency: currency,
    init_total: true,
    years: years,
    customer_id: customer_id,
    project_id: project_id,
  }).done(function (response) {
    $("#expenses_total").html(response);
  });
}

// Validate invoice add/edit form
function validate_invoice_form(selector) {
  selector = typeof selector == "undefined" ? "#invoice-form" : selector;

  appValidateForm($(selector), {
    clientid: {
      required: {
        depends: function () {
          var customerRemoved =
            $("select#clientid").hasClass("customer-removed");
          return !customerRemoved;
        },
      },
    },
    date: "required",
    currency: "required",
    repeat_every_custom: {
      min: 1,
    },
    number: {
      required: true,
    },
  });
  $("body")
    .find('input[name="number"]')
    .rules("add", {
      remote: {
        url: admin_url + "invoices/validate_invoice_number",
        type: "post",
        data: {
          number: function () {
            return $('input[name="number"]').val();
          },
          isedit: function () {
            return $('input[name="number"]').data("isedit");
          },
          original_number: function () {
            return $('input[name="number"]').data("original-number");
          },
          date: function () {
            return $('input[name="date"]').val();
          },
        },
      },
      messages: {
        remote: app.lang.invoice_number_exists,
      },
    });
}

function validate_credit_note_form(selector) {
  selector = typeof selector == "undefined" ? "#credit-note-form" : selector;

  appValidateForm($(selector), {
    clientid: {
      required: {
        depends: function () {
          var customerRemoved =
            $("select#clientid").hasClass("customer-removed");
          return !customerRemoved;
        },
      },
    },
    date: "required",
    currency: "required",
    number: {
      required: true,
    },
  });

  $("body")
    .find('input[name="number"]')
    .rules("add", {
      remote: {
        url: admin_url + "credit_notes/validate_number",
        type: "post",
        data: {
          number: function () {
            return $('input[name="number"]').val();
          },
          isedit: function () {
            return $('input[name="number"]').data("isedit");
          },
          original_number: function () {
            return $('input[name="number"]').data("original-number");
          },
          date: function () {
            return $(".credit_note input[name='date']").val();
          },
        },
      },
      messages: {
        remote: app.lang.credit_note_number_exists,
      },
    });
}
//Debit Notes
function validate_debit_note_form(selector) {
  selector = typeof selector == "undefined" ? "#debit-note-form" : selector;

  appValidateForm($(selector), {
    clientid: {
      required: {
        depends: function () {
          var customerRemoved =
            $("select#clientid").hasClass("customer-removed");
          return !customerRemoved;
        },
      },
    },
    date: "required",
    currency: "required",
    number: {
      required: true,
    },
  });

  $("body")
    .find('input[name="number"]')
    .rules("add", {
      remote: {
        url: admin_url + "debit_notes/validate_number",
        type: "post",
        data: {
          number: function () {
            return $('input[name="number"]').val();
          },
          isedit: function () {
            return $('input[name="number"]').data("isedit");
          },
          original_number: function () {
            return $('input[name="number"]').data("original-number");
          },
          date: function () {
            return $(".debit_note input[name='date']").val();
          },
        },
      },
      messages: {
        remote: app.lang.debit_note_number_exists,
      },
    });
}
// Validates estimate add/edit form
function validate_estimate_form(selector) {
  selector = typeof selector == "undefined" ? "#estimate-form" : selector;

  appValidateForm($(selector), {
    clientid: {
      required: {
        depends: function () {
          var customerRemoved =
            $("select#clientid").hasClass("customer-removed");
          return !customerRemoved;
        },
      },
    },
    date: "required",
    currency: "required",
    number: {
      required: true,
    },
  });

  $("body")
    .find('input[name="number"]')
    .rules("add", {
      remote: {
        url: admin_url + "estimates/validate_estimate_number",
        type: "post",
        data: {
          number: function () {
            return $('input[name="number"]').val();
          },
          isedit: function () {
            return $('input[name="number"]').data("isedit");
          },
          original_number: function () {
            return $('input[name="number"]').data("original-number");
          },
          date: function () {
            return $("body").find('.estimate input[name="date"]').val();
          },
        },
      },
      messages: {
        remote: app.lang.estimate_number_exists,
      },
    });
}

// Sort estimates in the pipeline view / switching sort type by click
function estimates_pipeline_sort(type) {
  kan_ban_sort(type, estimate_pipeline);
}

// Sort proposals in the pipeline view / switching sort type by click
function proposal_pipeline_sort(type) {
  kan_ban_sort(type, proposals_pipeline);
}

// Init estimates pipeline
function estimate_pipeline() {
  init_kanban(
    "estimates/get_pipeline",
    estimates_pipeline_update,
    ".pipeline-status",
    290,
    360
  );
}

// Used when estimate is updated from pipeline. eq changed order or moved to another status
function estimates_pipeline_update(ui, object) {
  if (object === ui.item.parent()[0]) {
    var data = {
      estimateid: $(ui.item).attr("data-estimate-id"),
      status: $(ui.item.parent()[0]).attr("data-status-id"),
      order: [],
    };

    $.each(
      $(ui.item).parents(".pipeline-status").find("li"),
      function (idx, el) {
        var id = $(el).attr("data-estimate-id");
        if (id) {
          data.order.push([id, idx + 1]);
        }
      }
    );

    check_kanban_empty_col("[data-estimate-id]");

    setTimeout(function () {
      $.post(admin_url + "estimates/update_pipeline", data).done(function (
        response
      ) {
        update_kan_ban_total_when_moving(ui, data.status);
        estimate_pipeline();
      });
    }, 200);
  }
}

// Used when proposal is updated from pipeline. eq changed order or moved to another status
function proposals_pipeline_update(ui, object) {
  if (object === ui.item.parent()[0]) {
    var data = {
      order: [],
      status: $(ui.item.parent()[0]).attr("data-status-id"),
      proposalid: $(ui.item).attr("data-proposal-id"),
    };

    $.each(
      $(ui.item).parents(".pipeline-status").find("li"),
      function (idx, el) {
        var id = $(el).attr("data-proposal-id");
        if (id) {
          data.order.push([id, idx + 1]);
        }
      }
    );

    check_kanban_empty_col("[data-proposal-id]");

    setTimeout(function () {
      $.post(admin_url + "proposals/update_pipeline", data).done(function (
        response
      ) {
        update_kan_ban_total_when_moving(ui, data.status);
        proposals_pipeline();
      });
    }, 200);
  }
}

// Init proposals pipeline
function proposals_pipeline() {
  init_kanban(
    "proposals/get_pipeline",
    proposals_pipeline_update,
    ".pipeline-status",
    290,
    360
  );
}

// Open single proposal in pipeline
function proposal_pipeline_open(id) {
  if (id === "") {
    return;
  }
  requestGet("proposals/pipeline_open/" + id).done(function (response) {
    var visible = $(".proposal-pipeline-modal:visible").length > 0;
    $("#proposal").html(response);
    if (!visible) {
      $(".proposal-pipeline-modal").modal({
        show: true,
        backdrop: "static",
        keyboard: false,
      });
    } else {
      $("#proposal")
        .find(".modal.proposal-pipeline-modal")
        .removeClass("fade")
        .addClass("in")
        .css("display", "block");
    }
  });
}

// Estimate single open in pipeline
function estimate_pipeline_open(id) {
  if (id === "") {
    return;
  }
  requestGet("estimates/pipeline_open/" + id).done(function (response) {
    var visible = $(".estimate-pipeline:visible").length > 0;
    $("#estimate").html(response);
    if (!visible) {
      $(".estimate-pipeline").modal({
        show: true,
        backdrop: "static",
        keyboard: false,
      });
    } else {
      $("#estimate")
        .find(".modal.estimate-pipeline")
        .removeClass("fade")
        .addClass("in")
        .css("display", "block");
    }
  });
}

// Delete estimate note
function delete_sales_note(wrapper, id) {
  if (confirm_delete()) {
    requestGetJSON("misc/delete_note/" + id).done(function (response) {
      if (response.success === true || response.success == "true") {
        $(wrapper).parents(".sales-note-wrapper").remove();
        var salesNotesWrapper = $("#sales-notes-wrapper");
        var totalNotesNow = salesNotesWrapper.attr("data-total") - 1;
        var notesTotal = $(".notes-total");
        salesNotesWrapper.attr("data-total", totalNotesNow);
        if (totalNotesNow <= 0) {
          notesTotal.addClass("hide");
        } else {
          notesTotal.html('<span class="badge">' + totalNotesNow + "</span>");
        }
      }
    });
  }
}

// Get all estimate notes
function get_sales_notes(id, controller) {
  requestGet(controller + "/get_notes/" + id).done(function (response) {
    $("#sales_notes_area").html(response);
    var totalNotesNow = $("#sales-notes-wrapper").attr("data-total");
    if (totalNotesNow > 0) {
      $(".notes-total")
        .html('<span class="badge">' + totalNotesNow + "</span>")
        .removeClass("hide");
    }
  });
}

// Proposal merge field into the editor
function insert_proposal_merge_field(field) {
  tinymce.activeEditor.execCommand("mceInsertContent", false, $(field).text());
}

// Toggle full view for small tables like proposals
function small_table_full_view() {
  $("#small-table").toggleClass("hide");
  $(".small-table-right-col").toggleClass("col-md-12 col-md-7");
  $(window).trigger("resize");
}

// Used to update manually the prefix after invoice/estimate is created.
function save_sales_number_settings(e) {
  var data = {};
  data.prefix = $("body").find('input[name="s_prefix"]').val();
  $.post($(e).data("url"), data).done(function (response) {
    response = JSON.parse(response);
    if (response.success && response.message) {
      alert_float("success", response.message);
      $("#prefix").html(data.prefix);
    }
  });
}

// Prefix for invoices/estimates in case there is year.
function do_prefix_year(date) {
  var date_array = _split_formatted_date_by_separator(date);

  if (typeof date_array != "undefined") {
    $.each(date_array, function (i, string) {
      if (string.length == 4) {
        var $pYear = $("#prefix_year");
        if ($pYear.hasClass("format-n-yy")) {
          string = string.substr(-2);
        } else if ($pYear.hasClass("format-mm-yyyy")) {
          var month_index;
          if (
            app.options.date_format == "d-m-Y" ||
            app.options.date_format == "d/m/Y" ||
            app.options.date_format == "Y-m-d" ||
            app.options.date_format == "d.m.Y"
          ) {
            month_index = 1;
          } else if (
            app.options.date_format == "m-d-Y" ||
            app.options.date_format == "m.d.Y" ||
            app.options.date_format == "m/d/Y"
          ) {
            month_index = 0;
          }
          $("#prefix_month").html(date_array[month_index]);
        }
        $pYear.html(string);
      }
    });
  }
}

function unformat_date(date) {
  var date_array = _split_formatted_date_by_separator(date),
    // Y-m-d is default, see below commented code
    month_index = 1,
    year_index = 0,
    day_index = 2;
  if (
    app.options.date_format == "d-m-Y" ||
    app.options.date_format == "d/m/Y" ||
    app.options.date_format == "d.m.Y"
  ) {
    day_index = 0;
    month_index = 1;
    year_index = 2;
  } else if (
    /* else if (app.options.date_format == 'Y-m-d') {
            day_index = 2;
            month_index = 1;
            year_index = 0;
        }*/
    app.options.date_format == "m-d-Y" ||
    app.options.date_format == "m.d.Y" ||
    app.options.date_format == "m/d/Y"
  ) {
    day_index = 1;
    month_index = 0;
    year_index = 2;
  }

  return (
    date_array[year_index] +
    "-" +
    date_array[month_index] +
    "-" +
    date_array[day_index]
  );
}

function _split_formatted_date_by_separator(date) {
  var date_array;

  if (date.indexOf(".") > -1) {
    date_array = date.split(".");
  } else if (date.indexOf("-") > -1) {
    date_array = date.split("-");
  } else if (date.indexOf("/") > -1) {
    date_array = date.split("/");
  }

  return date_array;
}

function init_tabs_scrollable() {
  // Not working fine on RTL
  if (isRTL != "true") {
    if ($(window).width() <= 768) {
      $("body").find(".toggle_view").remove();
    }
    // Horinzontal tabs
    $(".horizontal-scrollable-tabs").horizontalTabs();
  } else {
    $(".arrow-left, .arrow-right").css("display", "none");
    $(".horizontal-scrollable-tabs").removeClass("horizontal-scrollable-tabs");
    $(".nav-tabs-horizontal").removeClass("nav-tabs-horizontal");
  }
}

function view_contact_consent(id) {
  requestGet("clients/consents/" + id).done(function (response) {
    $("#consent_data").html(response);
    initDataTableInline($("#consentHistoryTable"));
    $("#consentModal").modal("show");
  });
}

function view_lead_consent(id) {
  window.location.hash = "gdpr";
  init_lead(id);
}

// Set single notification as read INLINE
function set_notification_read_inline(id) {
  requestGet("misc/set_notification_read_inline/" + id).done(function () {
    var notification = $("body").find(
      '.notification-wrapper[data-notification-id="' + id + '"]'
    );
    notification
      .find(".notification-handler")
      .removeClass("unread-notification");
    notification.find(".not-mark-as-read-inline").tooltip("destroy").remove();
  });
}

// Marks all notifications as read INLINE
function mark_all_notifications_as_read_inline() {
  requestGet("misc/mark_all_notifications_as_read_inline/").done(function () {
    var notification = $("body").find(".notification-wrapper");
    notification
      .find(".notification-handler")
      .removeClass("unread-notification");
    notification.find(".not-mark-as-read-inline").tooltip("destroy").remove();
  });
}

// Deletes activity for sales eq. invoices, estimates.
function delete_sale_activity(id) {
  if (confirm_delete()) {
    requestGet("misc/delete_sale_activity/" + id).done(function () {
      $("body")
        .find('[data-sale-activity-id="' + id + '"]')
        .remove();
    });
  }
}

// View calendar custom single event
function view_event(id) {
  if (typeof id == "undefined") {
    return;
  }
  $.post(admin_url + "utilities/view_event/" + id).done(function (response) {
    $("#event").html(response);
    $("#viewEvent").modal("show");
    init_datepicker();
    init_selectpicker();
    validate_calendar_form();
  });
}

// Delete calendar event form
function delete_event(id) {
  if (confirm_delete()) {
    requestGetJSON("utilities/delete_event/" + id).done(function (response) {
      if (response.success === true || response.success == "true") {
        window.location.reload();
      }
    });
  }
}

// Validate calendar event form
function validate_calendar_form() {
  appValidateForm(
    $("body").find("._event form"),
    {
      title: "required",
      start: "required",
      reminder_before: "required",
    },
    calendar_form_handler
  );

  appValidateForm(
    $("body").find("#viewEvent form"),
    {
      title: "required",
      start: "required",
      reminder_before: "required",
    },
    calendar_form_handler
  );
}

// Handles calendar event saving
function calendar_form_handler(form) {
  $.post(form.action, $(form).serialize()).done(function (response) {
    response = JSON.parse(response);
    if (response.success === true || response.success == "true") {
      alert_float("success", response.message);
      setTimeout(function () {
        var location = window.location.href;
        location = location.split("?");
        window.location.href = location[0];
      }, 500);
    }
  });

  return false;
}

// Fetches notifications
function fetch_notifications(callback) {
  requestGetJSON("misc/notifications_check").done(function (response) {
    var nw = notifications_wrapper;
    nw.html(response.html);
    var total = nw.find("ul.notifications").attr("data-total-unread");
    document.title =
      total > 0 ? "(" + total + ") " + doc_initial_title : doc_initial_title;
    var nIds = response.notificationsIds;
    if (app.browser == "firefox" && nIds.length > 1) {
      var lastNotification = nIds[0];
      nIds = [];
      nIds.push(lastNotification);
    }
    setTimeout(function () {
      if (nIds.length > 0) {
        $.each(nIds, function (i, notId) {
          var nSelector = 'li[data-notification-id="' + notId + '"]';
          var $not = nw.find(nSelector);
          $.notify("", {
            title: app.lang.new_notification,
            body: $not.find(".notification-title").text(),
            requireInteraction: true,
            icon: $not.find(".notification-image").attr("src"),
            tag: notId,
            closeTime:
              app.options.dismiss_desktop_not_after != "0"
                ? app.options.dismiss_desktop_not_after * 1000
                : null,
          })
            .close(function () {
              requestGet("misc/set_desktop_notification_read/" + notId).done(
                function (response) {
                  var $totalIndicator = nw.find(".icon-total-indicator");
                  nw.find(
                    'li[data-notification-id="' + notId + '"] .notification-box'
                  ).removeClass("unread");
                  var currentTotalNotifications = $totalIndicator.text();
                  currentTotalNotifications = currentTotalNotifications.trim();
                  currentTotalNotifications = currentTotalNotifications - 1;
                  if (currentTotalNotifications > 0) {
                    document.title =
                      "(" +
                      currentTotalNotifications +
                      ") " +
                      doc_initial_title;
                    $totalIndicator.html(currentTotalNotifications);
                  } else {
                    document.title = doc_initial_title;
                    $totalIndicator.addClass("hide");
                  }
                }
              );
            })
            .click(function (e) {
              parent.focus();
              window.focus();
              setTimeout(function () {
                nw.find(nSelector + " .notification-link")
                  .addClass("desktopClick")
                  .click();
                e.target.close();
              }, 70);
            });
        });
      }
    }, 10);
  });
}

function init_new_task_comment(manual) {
  if (tinymce.get('task_comment')) {
    tinymce.remove("#task_comment");
  }

  if (typeof taskCommentAttachmentDropzone != "undefined") {
    taskCommentAttachmentDropzone.destroy();
  }

  $("#dropzoneTaskComment").removeClass("hide");
  $("#addTaskCommentBtn").removeClass("hide");

  taskCommentAttachmentDropzone = new Dropzone(
    "#task-comment-form",
    appCreateDropzoneOptions({
      uploadMultiple: true,
      clickable: "#dropzoneTaskComment",
      previewsContainer: ".dropzone-task-comment-previews",
      autoProcessQueue: false,
      addRemoveLinks: true,
      parallelUploads: 20,
      maxFiles: 20,
      paramName: "file",
      sending: function (file, xhr, formData) {
        formData.append(
          "taskid",
          $("#addTaskCommentBtn").attr("data-comment-task-id")
        );
        if (tinyMCE.activeEditor) {
          formData.append("content", tinyMCE.activeEditor.getContent());
        } else {
          formData.append("content", $("#task_comment").val());
        }
      },
      success: function (files, response) {
        response = JSON.parse(response);
        if (
          this.getUploadingFiles().length === 0 &&
          this.getQueuedFiles().length === 0
        ) {
          _task_append_html(response.taskHtml);
          tinymce.remove("#task_comment");
        }
      },
    })
  );

  var editorConfig = _simple_editor_config();
  
  editorConfig.toolbar_sticky = true

  if (typeof manual == "undefined" || manual === false) {
    editorConfig.auto_focus = true;
  }

  var taskid = $("#task-modal #taskid").val();

  editorConfig.content_style =
    "span.mention {\
        background-color: #eeeeee;\
        padding: 3px;\
    }";

  editorConfig.setup = function (editor) {
    initializeTinyMceMentions(editor, function () {
      return $.getJSON(
        admin_url + "tasks/get_staff_names_for_mentions/" + taskid     
      )
    })
  };

  init_editor("#task_comment", editorConfig)
}

function initializeTinyMceMentions(editor, usersCallback) {
  if(!Object.hasOwn(editor, 'perfexCommands')) {
    editor.perfexCommands = {}
  }

  let cachedUsers = null;

  editor.perfexCommands.getUsersForMention = async function() {
    if(Array.isArray(cachedUsers)) {
      return cachedUsers
    }

    let users = await usersCallback()

    cachedUsers = users.map(u=>({
      value: u.id.toString(),
      text: u.name,
    }));

    return cachedUsers
  },
  editor.perfexCommands.insertMentionUser = function (id, name, rng) {
    // Insert in to the editor
    editor.selection.setRng(rng || 0)

    editor.insertContent((
      '<span class="mention" contenteditable="false" data-mention-id="' +
      id +
      '">@' +
      name +
      "</span>&nbsp;"
    ))
  }

  editor.ui.registry.addAutocompleter('mentions', {
    trigger: '@', // the trigger character to open the autocompleter
    minChars: 0, // 0 to open the dropdown immediately after the @ is typed
    columns: 1, // must be 1 for text-based results

    // Retrieve the available users
    fetch: function (pattern) {
      return new Promise(resolve =>
          resolve(editor.perfexCommands.getUsersForMention())
      )
    },

    // Executed when user is selected from the dropdown
    onAction: function (autocompleteApi, rng, value) {
      editor.perfexCommands.getUsersForMention().then(users=> {
        let user = users.find(user=>user.value == value)
        editor.perfexCommands.insertMentionUser(value, user.text, rng)
        autocompleteApi.hide()
      })
    },
  })
}

function init_ajax_search(type, selector, server_data, url) {
  var ajaxSelector = $("body").find(selector);

  if (ajaxSelector.length) {
    var options = {
      ajax: {
        url:
          typeof url == "undefined"
            ? admin_url + "misc/get_relation_data"
            : url,
        data: function () {
          var data = {};
          data.type = type;
          data.rel_id = "";
          data.q = "{{{q}}}";
          if (typeof server_data != "undefined") {
            jQuery.extend(data, server_data);
          }
          return data;
        },
      },
      locale: {
        emptyTitle: app.lang.search_ajax_empty,
        statusInitialized: app.lang.search_ajax_initialized,
        statusSearching: app.lang.search_ajax_searching,
        statusNoResults: app.lang.not_results_found,
        searchPlaceholder: app.lang.search_ajax_placeholder,
        currentlySelected: app.lang.currently_selected,
      },
      requestDelay: 500,
      cache: false,
      preprocessData: function (processData) {
        var bs_data = [];
        var len = processData.length;
        for (var i = 0; i < len; i++) {
          var tmp_data = {
            value: processData[i].id,
            text: processData[i].name,
          };
          if (processData[i].subtext) {
            tmp_data.data = {
              subtext: processData[i].subtext,
            };
          }
          bs_data.push(tmp_data);
        }
        return bs_data;
      },
      preserveSelectedPosition: "after",
      preserveSelected: true,
    };
    if (ajaxSelector.data("empty-title")) {
      options.locale.emptyTitle = ajaxSelector.data("empty-title");
    }
    ajaxSelector.selectpicker().ajaxSelectPicker(options);
  }
}

// Used for email template URL
function merge_field_format_url(url, node, on_save, name) {
  // Merge fields url
  if (url && url.indexOf("%7B") > -1 && url.indexOf("%7D") > -1) {
    url = url.replaceAll("%7B", "{").replaceAll("%7D", "}");
  }

  return url;
}

function salesGoogleDriveSave(pickData) {
  salesExtenalFileUpload(pickData, "gdrive");
}

function leadExternalFileUpload(files, externalType, leadId) {
  $.post(admin_url + "leads/add_external_attachment", {
    files: files,
    lead_id: leadId,
    external: externalType,
  }).done(function () {
    init_lead_modal_data(leadId);
  });
}

function taskExternalFileUpload(files, externalType, taskId) {
  $.post(admin_url + "tasks/add_external_attachment", {
    files: files,
    task_id: taskId,
    external: externalType,
  }).done(function () {
    init_task_modal(taskId);
  });
}

function salesExtenalFileUpload(files, externalType) {
  var _data = {};
  _data.rel_id = $("body").find('input[name="_attachment_sale_id"]').val();
  _data.type = $("body").find('input[name="_attachment_sale_type"]').val();
  _data.files = files;
  _data.external = externalType;
  $.post(admin_url + "misc/add_sales_external_attachment", _data).done(
    function () {
      if (_data.type == "estimate") {
        if ($("body").hasClass("estimates-pipeline")) {
          estimate_pipeline_open(_data.rel_id);
        } else {
          init_estimate(_data.rel_id);
        }
      } else if (_data.type == "proposal") {
        if ($("body").hasClass("proposals-pipeline")) {
          proposal_pipeline_open(_data.rel_id);
        } else {
          init_proposal(_data.rel_id);
        }
      } else {
        if (typeof window["init_" + _data.type] == "function") {
          window["init_" + _data.type](_data.rel_id);
        }
      }
      $("#sales_attach_file").modal("hide");
    }
  );
}

function set_search_history(history) {
  var $searchHistory = $("#search-history");
  var historyHtml = "";
  for (var i = 0; i < history.length; i++) {
    historyHtml +=
      '<li data-index="' +
      i +
      '"><a href="#" class="history">' +
      history[i] +
      ' <span class="remove-history pointer pull-right" style="z-index:1500"><i class="fa fa-remove"></i></span></a></li>';
  }
  $searchHistory.html(historyHtml);
}

// General helper function for $.get ajax requests
function requestGet(uri, params) {
  params = typeof params == "undefined" ? {} : params;
  var options = {
    type: "GET",
    url: uri.indexOf(admin_url) > -1 ? uri : admin_url + uri,
  };
  return $.ajax($.extend({}, options, params));
}

// General helper function for $.get ajax requests with dataType JSON
function requestGetJSON(uri, params) {
  params = typeof params == "undefined" ? {} : params;
  params.dataType = "json";
  return requestGet(uri, params);
}

// Templates Js
function update_templates_count(type) {
  var count = $(".templates-wrapper").length;
  $(".total_templates").text(count);
  if (count === 0) {
    $(".total_templates").addClass("hide");
  } else {
    $(".total_templates").removeClass("hide");
  }
}

function get_templates(rel_type, rel_id) {
  if (rel_type === "proposals") {
    $("#proposal-templates").load(
      admin_url + "templates",
      {
        rel_type: rel_type,
        rel_id: rel_id,
      },
      function () {
        update_templates_count();
      }
    );
  } else if (rel_type === "contracts") {
    $("#contract-templates").load(
      admin_url + "templates",
      {
        rel_type: rel_type,
        rel_id: rel_id,
      },
      function () {
        update_templates_count();
      }
    );
  }
}

function add_template(rel_type, rel_id) {
  $("#modal-wrapper").load(
    admin_url + "templates/modal",
    {
      slug: "new",
      rel_type: rel_type,
      rel_id: rel_id,
    },

    function () {
      if ($("#TemplateModal").is(":hidden")) {
        $("#TemplateModal").modal({
          backdrop: "static",
          show: true,
        });
      }

      appValidateForm($("#template-form"), {
        name: "required",
      });

      tinymce.remove("#content");

      init_editor("#content", {
        pagebreak_split_block: true,
        contextmenu:
          "link image inserttable | cell row column deletetable | paste copy | pagebreak",
        append_plugins: "pagebreak",
      });
    }
  );
}

function edit_template(rel_type, id, rel_id) {
  $("#modal-wrapper").load(
    admin_url + "templates/modal",
    {
      slug: "edit",
      id: id,
      rel_type: rel_type,
      rel_id: rel_id,
    },

    function () {
      if ($("#TemplateModal").is(":hidden")) {
        $("#TemplateModal").modal({
          backdrop: "static",
          show: true,
        });
      }

      appValidateForm($("#template-form"), {
        name: "required",
      });

      tinymce.remove("#content");

      init_editor("#content", {
        pagebreak_split_block: true,
        contextmenu:
          "link image inserttable | cell row column deletetable | paste copy | pagebreak",
        append_plugins: "pagebreak",
      });
    }
  );
}

function delete_template(wrapper, rel_type, id) {
  if (confirm_delete()) {
    $.post(admin_url + "templates/delete/" + id).done(function (response) {
      response = JSON.parse(response);

      if (response.success === true || response.success == "true") {
        if (rel_type === "proposals") {
          $(wrapper).parents(".proposal-templates-wrapper").html("");
        } else if (rel_type === "contracts") {
          $(wrapper).parents(".contract-templates-wrapper").html("");
        }

        get_templates(rel_type);
      }
    });
  }
}

function insert_template(wrapper, rel_type, id) {
  requestGetJSON(admin_url + "templates/index/" + id).done(function (response) {
    var data = response.data;
    tinymce.activeEditor.execCommand("mceInsertContent", false, data.content);
    if (rel_type == "proposals") {
      $('a[aria-controls="tab_proposal"]').click();
    } else if (rel_type == "contracts") {
      $('a[aria-controls="tab_content"]').click();
    }
    tinymce.activeEditor.focus();
  });
}

function retrieve_imap_folders(url, params) {
  var dfd = $.Deferred();
  $("#folders-loader").addClass("spinning").removeClass("hidden");

  $.post(url, params)
    .done(function (response) {
      response = JSON.parse(response);
      if (response.hasOwnProperty("alert_type")) {
        alert_float(response.alert_type, response.message);
      } else {
        var output = "";
        var $folder = $("#folder");
        var currentFolder = $folder.selectpicker("val");

        response.forEach(function (folderName) {
          output +=
            '<option name="' +
            folderName +
            '"' +
            (folderName == currentFolder ? " selected" : "") +
            ">" +
            folderName +
            "</option>";
        });

        $folder.html(output);
        $folder.selectpicker("refresh");

        if (!currentFolder) {
          $folder.selectpicker("val", $folder.find("option:eq(0)")[0].value);
        }
      }
      dfd.resolve(response);
    })
    .fail(function (error) {
      dfd.reject(error);
    })
    .always(function () {
      $("#folders-loader").removeClass("spinning").addClass("hidden");
    });

  return dfd.promise();
}

function add_batch_payment() {
  $("#modal-wrapper").load(
    admin_url + "payments/batch_payment_modal",
    function () {
      if ($("#batch-payment-modal").is(":hidden")) {
        $("#batch-payment-modal").modal({
          backdrop: "static",
          show: true,
        });
      }
      init_selectpicker();
      init_datepicker();

      var $filterByClientSelect = $("#batch-payment-filter");
      $filterByClientSelect.on("changed.bs.select", function () {
        if ($filterByClientSelect.val() !== "") {
          $(".batch_payment_item").each(function () {
            if ($(this).data("clientid") == $filterByClientSelect.val()) {
              $(this).find("input, select").prop("disabled", false);
              $(this).removeClass("hide");
            } else {
              $(this).addClass("hide");
              $(this).find("input, select").prop("disabled", true);
            }
          });
        } else {
          $(".batch_payment_item").each(function () {
            $(this).removeClass("hide");
            $(this).find("input, select").prop("disabled", false);
          });
        }
      });
      appValidateForm($("#batch-payment-form"), {});
      $(".batch_payment_item").each(function () {
        var invoiceLine = $(this).find('[name^="invoice"]');

        invoiceLine
          .filter('select[name$="[paymentmode]"],input[name$="[amount]"]')
          .each(function () {
            var field = $(this);
            field.rules("add", {
              required: function () {
                var isRequired = false;
                var rowFields = field
                  .closest(".batch_payment_item")
                  .find("input, select");
                rowFields
                  .filter(
                    'select[name$="[paymentmode]"],input[name$="[transactionid]"],input[name$="[amount]"]'
                  )
                  .each(function () {
                    if ($(this).val() != "") {
                      isRequired = true;
                    }

                    if ($(this).hasClass("selectpicker") && isRequired) {
                      field.prop("required", true);
                      $(this).selectpicker("refresh");
                    }
                  });
                return isRequired;
              },
            });
          });
      });
    }
  );
}

function configure_ai_editor(editor) {
  let items = [
      {
        type: 'menuitem',
        text:app.lang.text_enhancement_make_polite,
        icon: 'brightness',
        onAction: function () {
          make_ai_text_enhancement_request(editor, 'polite')
        }
      },
      {
        type: 'menuitem',
        text: app.lang.text_enhancement_make_formal,
        icon: 'accessibility-check',
        onAction: function () {
          make_ai_text_enhancement_request(editor, 'formal')
        }
      },
      {
        type: 'menuitem',
        icon: 'emoji',
        text: app.lang.text_enhancement_make_friendly,
        onAction: function () {
          make_ai_text_enhancement_request(editor, 'friendly')
        }
      }
    ];

    editor.ui.registry.addMenuButton('ai', {
      icon: 'ai',
      fetch: function (callback) {
        callback(items);
      }
    });
}

function make_ai_text_enhancement_request(editor, type) {
  const selectedText = editor.selection.getContent({ format: 'text' });

  if (!selectedText.trim()) {
      alert_float('warning', 'Please select text to enhance.');
      return;
  }

  $.post(admin_url + 'ai/text_enhancement/' + type, {
      text: selectedText,
  })
  .done(function (response) {
      const result = JSON.parse(response);
      if (result.success) {
          editor.selection.setContent(result.message);
      }
  })
  .catch(function (error) {
      const result = JSON.parse(error.responseText);
      alert_float('danger', result.error ? result.error : app.lang.something_went_wrong);
  });
}

/**
 * @DEPRECATED FUNCTIONS
 */

/**
 * @deprecated
 */
function initDatatableOffline(dt_table) {
  console.warn(
    '"initDatatableOffline" is deprecated, use "initDataTableInline" instead.'
  );
  initDataTableInline(dt_table);
}

/**
 * @deprecated
 * @since  2.3.2
 */
function init_currency_symbol() {
  console.warn(
    '"init_currency_symbol" is deprecated, use "init_currency" instead'
  );
  init_currency();
}

