Skip to content
Snippets Groups Projects
helpers.js 4.44 KiB
Newer Older
chris's avatar
chris committed
import { each } from 'lodash';
chris's avatar
chris committed
import { DocumentHelpers } from 'wax-prosemirror-utilities';
import { TextSelection } from 'prosemirror-state';
chris's avatar
chris committed

const getMatchesByView = (views, searchValue, matchCase) => {
chris's avatar
chris committed
  let allResults = 0;
  each(views, (singleView, viewId) => {
chris's avatar
chris committed
    const results = DocumentHelpers.findMatches(
      singleView.state.doc,
      searchValue,
      matchCase,
    );
chris's avatar
chris committed
    allResults += results.length;
chris's avatar
chris committed
  });
chris's avatar
chris committed
  return allResults;
chris's avatar
chris committed
};

chris's avatar
chris committed
const getAllResultsByView = (view, searchValue, matchCaseSearch) => {
  const allResults = {};

  each(view, (singleView, viewId) => {
    if (!allResults[viewId]) {
chris's avatar
chris committed
      allResults[viewId] = DocumentHelpers.findMatches(
chris's avatar
chris committed
        singleView.state.doc,
        searchValue,
        matchCaseSearch,
      );
    }
  });
  return allResults;
};

const getNotesIds = main => {
  const notesIds = [];
  const notes = DocumentHelpers.findChildrenByType(
    main.state.doc,
    main.state.schema.nodes.footnote,
    true,
  );
  notes.forEach(note => {
    notesIds.push(note.node.attrs.id);
  });
  return notesIds;
};

const getResultsFrom = results => {
  const resultsFrom = {};

  each(results, (result, viewId) => {
    result.forEach(res => {
      if (!resultsFrom[viewId]) {
        resultsFrom[viewId] = [res.from];
      } else {
        resultsFrom[viewId].push(res.from);
      }
    });
  });
  return resultsFrom;
};

const getClosestMatch = (selectionFrom, results, greater = true) => {
  return results.reduce((a, b) => {
    const greaterSmaller = greater ? a > b : a < b;
    const aDiff = Math.abs(a - selectionFrom);
    const bDiff = Math.abs(b - selectionFrom);

    if (aDiff === bDiff) {
      return greaterSmaller ? a : b;
    }
    return bDiff < aDiff ? b : a;
  });
};

const moveToMatch = (view, lastActiveViewId, results, position) => {
  const selectionFrom = new TextSelection(
    view[lastActiveViewId].state.doc.resolve(
      results[lastActiveViewId][position].from,
    ),
  );

  const selectionTo = new TextSelection(
    view[lastActiveViewId].state.doc.resolve(
      results[lastActiveViewId][position].to,
    ),
  );

  view[lastActiveViewId].dispatch(
    view[lastActiveViewId].state.tr.setSelection(
      TextSelection.between(selectionFrom.$anchor, selectionTo.$head),
    ),
  );
chris's avatar
chris committed
  // if (lastActiveViewId === 'main') {
  view[lastActiveViewId].dispatch(
    view[lastActiveViewId].state.tr.scrollIntoView(),
  );
  // }
chris's avatar
chris committed
};

const clearViewSelection = (view, lastActiveViewId) => {
  view[lastActiveViewId].dispatch(
    view[lastActiveViewId].state.tr.setSelection(
      TextSelection.create(view[lastActiveViewId].state.doc, 0),
    ),
  );
const findViewWithMatchesForward = (results, view, lastActiveViewId) => {
chris's avatar
chris committed
  const notesIds = getNotesIds(view.main);

  if (lastActiveViewId === 'main') {
    for (let i = 0; i < notesIds.length; i += 1) {
      if (results[notesIds[i]].length > 0) {
        return notesIds[i];
      }
    }
  }

  if (notesIds.indexOf(lastActiveViewId) < notesIds.length - 1) {
    for (let i = 0; i < notesIds.length; i += 1) {
      if (results[notesIds[i]].length > 0) {
        return notesIds[i];
      }
    }
chris's avatar
chris committed
  } else if (results.main.length > 0) {
chris's avatar
chris committed
    return 'main';
chris's avatar
chris committed
  } else {
    for (let i = 0; i < notesIds.length; i += 1) {
      if (results[notesIds[i]].length > 0) {
        return notesIds[i];
      }
    }
chris's avatar
chris committed
  }

  if (
    notesIds.indexOf(lastActiveViewId) &&
    notesIds.indexOf(lastActiveViewId) === notesIds.length - 1
  ) {
    return 'main';
  }
  return false;
};

const findViewWithMatchesBackWards = (results, view, lastActiveViewId) => {
  const notesIds = getNotesIds(view.main);
  if (lastActiveViewId === 'main') {
chris's avatar
chris committed
    for (let i = notesIds.length - 1; i >= 0; i -= 1) {
      if (results[notesIds[i]].length > 0) {
        return notesIds[i];
      }
    }
  }

chris's avatar
chris committed
  if (notesIds.indexOf(lastActiveViewId) !== 0) {
    for (let i = notesIds.indexOf(lastActiveViewId) - 1; i >= 0; i -= 1) {
      if (results[notesIds[i]].length > 0) {
        return notesIds[i];
      }
chris's avatar
chris committed
      if (results.main.length > 0) return 'main';
chris's avatar
chris committed
  } else if (results.main.length > 0) {
    return 'main';
chris's avatar
chris committed
  } else {
    for (let i = notesIds.length - 1; i >= 0; i -= 1) {
      if (results[notesIds[i]].length > 0) {
        return notesIds[i];
      }
    }
chris's avatar
chris committed
export default {
  getMatchesByView,
  getAllResultsByView,
  getNotesIds,
  getResultsFrom,
  getClosestMatch,
  moveToMatch,
chris's avatar
chris committed
  clearViewSelection,
  findViewWithMatchesForward,
  findViewWithMatchesBackWards,
chris's avatar
chris committed
};