JavaScript to Hide "Copy To..." in Kebabs

Jump to solution
casey_eubank
Community Explorer

We are wanting hide the "Copy To.." option from faculty and non root-admins anywhere it is seen on a kebab (modules, individual content items in the module, pages, quizzes, assignments and discussions). 

What JavaScript could I use to do this?

 Copy To.PNG
 

Thank so much in advance!

0 Likes
1 Solution
robotcars
Community Champion

Mutations will work best.

I have absolutely no idea if this hits every instance of these.

Does not work in c4e.

 

// https://community.canvaslms.com/t5/Canvas-Developers-Group/JavaScript-to-Hide-quot-Copy-To-quot-in-Kebabs/m-p/586911#M9855

(function () {
  'use strict';

  // course context
  if (!/\/courses\/\d+\/?/.test(window.location.pathname)) return;

  // remove option for roles not listed
  if (['root_admin', 'consortium_admin'].some(a => ENV.current_user_roles.includes(a))) return;

  // be super cool if the dependency chain made this consistent
  // selectors for most
  var targets = [
    'a.direct-share-copy-to-menu-item', // direct share found in most (single use cases) course home, page, discussion, assignment, module
    'a.copy_assignment_to', // assignments
    'a.copy-wiki-page-to', // pages
    'a.module_copy_to', // module group
    'a.module_item_copy_to', // module (covers kyle-menu for discussions on /modules)
    'a.quiz-copy-to', // quizzes
    // files has no specific class, needs decent non-language target, using innerText fails to include someone
    // discussions has different structure with spans, no kyle menu... requires separate observer targeting
    'a.unset-as-front-page-menu-item', // remove the remove as front page option
    'a.use-as-front-page-menu-item', // remove the ability to set another
  ];
  // selectors for discussions
  var topic_targets = [
    '#copyTo-discussion-menu-option', // copy to for discussions
  ];
  // strings for files
  // break accessbility by being language specific
  var strings_for_files = [
    'Copy To...',
  ];

  var watch_kyle_menus = (_mtx, observer) => {
    // watch most kyle menus
    let active_kyle_menu = document.querySelector('ul.ui-kyle-menu[aria-expanded="true"]');
    // watch discussion_topic content control menus
    // only on discussion_topics, but not a discussion_topics/:id
    // maintains the kyle menu at the top of discussions - Commons Favorites, would have to account for that if necessary
    if (!/\/courses\/\d+\/discussion_topics\/\d+\/?/.test(window.location.pathname)) {
      active_kyle_menu = document.querySelector('span[class$="view--inlineBlock-contextView"][data-position-content^="Menu_"]');
    } 

    if (!active_kyle_menu) {
      if (typeof observer === 'undefined') {
        var obs = new MutationObserver(watch_kyle_menus);
        obs.observe(document.body, {
          attributes: true,
          childList: true,
          subtree: true
        });
      }
      return;
    }

    // class added to menu instance when changes are complete
    let complete = [...active_kyle_menu.classList].includes('modified-kyle-menu');

    // remove content control options
    if (active_kyle_menu && !complete) {
      let menu_opts = [];

      // only on discussion_topics, but not a discussion_topics/:id
      if (!/\/courses\/\d+\/discussion_topics\/\d+\/?/.test(window.location.pathname)) {
        // discussion topics
        menu_opts = Array.from(document.querySelectorAll(`span[class$="view--inlineBlock-contextView"][data-position-content^="Menu_"] ${topic_targets.join(', ')}`));
      } else if (/\/courses\/\d+\/files/.test(window.location.pathname)) {
        // files
        menu_opts = Array.from(document.querySelectorAll(`ul.ui-kyle-menu[aria-expanded="true"] li a`))
          .filter(o => strings_for_files.includes(o.innerText));
      } else {
        // all others
        menu_opts = Array.from(document.querySelectorAll(`ul.ui-kyle-menu[aria-expanded="true"] li ${targets.join(', ')}`));
      }
      menu_opts.forEach((mo, i, a) => {
        mo.closest('li').remove();
        // update menu instance with complete class, after last removable item
        if (i === a.length - 1 && mo.closest('ul') !== null && !complete) { 
          mo.closest('ul').classList.add('modified-kyle-menu');
        }
      });
    }
  };
  watch_kyle_menus();
})();

 

View solution in original post

0 Likes