Move List Collector Options

Home/Scripting/Client scripts/Move List Collector Options

Move List Collector Options

H

ere’s a cool catalog client script that I figured out for a client. It allows you to move one or more selected options from one side of a list collector variable slushbucket to another. Using the script is pretty straight forward. Just supply the name of the list collector variable you are working with, and then make sure you provide an array of option IDs to move from one side to another. The option IDs need to be added to the ‘selectedIDs’ array in the middle chunk of code. The code below is set up to move ALL options in the right column of a slushbucket to the left.

//Name of variable to move options from
var varName = 'YOUR_VARIABLE_NAME_HERE';
var leftBucket = gel(varName + '_select_0');
var rightBucket = gel(varName + '_select_1');
var selectedOptions = rightBucket.options;

//Get an array of all option IDs to move
var selectedIDs = new Array();
var index = 0;
for(var i = 0; i < selectedOptions.length; i++){
   selectedIDs[index] = i;
   index++;
}

//Move all returned options from right to left bucket and sort the results
//Switch 'rightBucket' and 'leftBucket' to move from left to right
moveSelectedOptions(selectedIDs, rightBucket, leftBucket, '--None--');
//Sort the resultant options in the left bucket
sortSelect(leftBucket);
By | 2010-11-29T17:45:00+00:00 June 22nd, 2010|Categories: Client scripts|Tags: , , , |35 Comments

About the Author:

Mark has worked in the IT industry since 2002 and with ServiceNow since 2007. He is the founder and creator of SN | Guru and the co-founder of Crossfuze, one of the worlds leading ServiceNow consulting partners. Prior to co-founding Crossfuze, he worked for ServiceNow as a Senior Architect on the Professional Services team. He has personally led dozens of successful implementations encompassing every part of the ServiceNow platform. He is also responsible for designing and developing groundbreaking ServiceNow solutions and best practices in the form of various applications, turnkey solutions, and integrations during his tenure at ServiceNow, Crossfuze and, of course, SN | Guru. These solutions are used today by ServiceNow administrators and consultants alike in hundreds of ServiceNow instances around the world!

35 Comments

  1. Phil Wright September 7, 2010 at 1:32 pm - Reply

    Great script!! I do have a question. How do I reference the value of an item in the left bucket. What I want to do is step through the left bucket and move only certain one to the right based on a dynamic condition. I have tried:

    selectedOptions[i]

    selectedOptions[i].value

    selectedOptions.value[i]

    Any ideas??

    Phil

    • Mark Stanger September 7, 2010 at 2:43 pm - Reply

      You should just have to modify the ‘for’ loop to be something like this…

      for(var i = 0; i < selectedOptions.length; i++){
         //Check for the item to add here based on sys_id
         if(selectedOptions[i].value == 'sys_id_value_of_item'){
         //Or check for item here based on display value
         //if(selectedOptions[i].text == 'display_value_of_item'){
            selectedIDs[index] = i;
            index++;
         }
      }
  2. Chris York September 8, 2010 at 4:21 am - Reply

    Mark,

    Thanks for this script. This has helped me out a great deal. I have one issue I can’t figure out though. I am using an onChange client Script to move the List items from List Collector 2 when an item in List Collector 1 is changed. the onChange event occurs even when simply clicking in the list, not necessarily when moving an item from left/right or right/left. Therefore my script runs prematurely. Comparing oldValue to newValue doesn’t appear to be worthwhile because oldValue is always empty. Is there a way to see previous list prior to the onChange? Or is there a way to only fire the onChange event when an item is really moved?

    Thanks!

    • Mark Stanger September 8, 2010 at 4:43 am - Reply

      Hey Chris. Unfortunately I’m not aware of a way around that. That actually sounds like a bug to me though. The onChange event shouldn’t be triggering unless an item is moved from one side to the other. I think you’ll have to open that one with Service-now support.

  3. Russ Hart November 25, 2010 at 8:18 pm - Reply

    Hi Mark,

    Very useful script !..

    Do you know of a way to modify or remove the add / remove labels from a catalog list collector ?

    • Mark Stanger November 26, 2010 at 1:10 am - Reply

      There’s not really a good way to change this for single variables/items because it would require a client script with easy access to those labels. Neither of those labels have a DOM ID so you could use a client script hack and modify them but that’s probably not a good (or simple) solution.
      The simplest way of changing them would be a global setting for ALL slushbuckets in the system. You can just go to ‘System UI->Messages’ and search for the messages with keys of ‘uppercase_add’ and ‘Remove’ and change the associated ‘Message’ values.

  4. Jim Coyne April 18, 2011 at 5:50 pm - Reply

    Just wondering where the “moveSelectedOptions” function is hiding? I was trying to figure out why the “–None–” item is not being removed from the right bucket as I move stuff over from the left (I swapped the left/right variables in the function call). I added the check for a particular set of values in the left bucket and move them over if they exist instead of moving all items over.

    for(var i = 0; i < selectedOptions.length; i++){
        //check for items here based on display value
        if((selectedOptions[i].text.toLowerCase() == 'string1')||(selectedOptions[i].text.toLowerCase() == 'string2')){
          selectedIDs[index] = i;
          index++;
        }
      }
      moveSelectedOptions(selectedIDs, leftBucket, rightBucket,'--None--');
      sortSelect(rightBucket);
    • Mark Stanger April 19, 2011 at 3:22 am - Reply

      You can dig into the code by using the script panel in a dom inspector. I use firebug most of the time. You can search through any client scripts loaded for a given page. You should be able to find the ‘moveSelectedOptions’ function by searching for ‘function moveSelectedOptions’ from the script panel in firebug.

      As to why it’s not removing the ‘–None–‘ value, the system adds that after the fact any time the right slushbucket ends up empty as a result of the move. I’m not sure why you would want to change that behavior, but you could add “rightBucket.options.length = ‘0’;” to the end of your script to wipe out the ‘–None–‘ value.

      • Jim Coyne April 19, 2011 at 4:23 am - Reply

        The problem is “–None–” is still in the right bucket list when I move over 2 items into the right from the left. The catalog item starts off with 10 items in the left bucket list and I have an onLoad script to pre-populate the right bucket with 2 of those items. I end up with 3 items in the right bucket once I run my code above: “–None–” and the 2 default items I need over there. I added rightBucket.options.length = ’0′; before the move and it is working OK now.

        Thanks

        • David B February 22, 2012 at 2:58 pm - Reply

          Slightly more error-checked:

          if(rightBucket.options.length == 1 && rightBucket.options[0].text == '--None--'){
              rightBucket.options.length = '0';
          }
  5. Gary March 20, 2012 at 9:20 am - Reply

    Mark,
    How are the values for the options stored? I’m trying to take information from a form and populate the right side of the list with the results I get from a previous query. For example: I am having a user pick a group, getting the group members and trying to populate the list collector(sys_user list collector) with the members. Then the user can pick which members to add/remove and then we are passing the updated list back to automate the update of AD. The part I am having issues with is just populating the right column of the list collector with the options from the previous query.

    • Mark Stanger March 20, 2012 at 10:17 am - Reply

      It’s stored as a comma-separated list of sys_ids. If you’re trying to manipulate it with a client script you have to construct a choice list and place it in the correct side of the slush bucket though. Each side acts like its own choice list dropdown.

  6. RDF August 15, 2012 at 2:56 pm - Reply

    I was trying to use this to build a “manage your own group memberships” catalog item. The idea being a list of groups you can pick on the left side (all the groups in our system), and a list of groups you’re currently a member of on the right. My problem: the list of groups far exceeds the quantity actually listed in the Left side of the slush bucket. I’m not sure if there’s a clever work around, but it looks like this will only work if the number of options is less than the 100 record display limit on slushbucket sides.

    • Mark Stanger August 15, 2012 at 3:08 pm - Reply

      You’re right. You could probably come up with a clever way to query for the groups the user was a member of and just manually add them to the right-side via client script. I’m just not sure if you’d end up with duplicate groups coming over or not that way. You might have to add to the right and then remove from the left via script to avoid any conflict.

  7. Mike March 18, 2014 at 3:23 pm - Reply

    This is a great article, but my situation is a little different. I’ve got a lookup table with a list field in it referencing the cmdb_ci_appl table. On a catalog item I have a list collector variable referencing the same table. I have an onChange client script that wants to set the variable list collector with the contents of the lookup table list field. It’s not populating the right-side of the list collector. But I have an alert set up as a debug tool and the sys_ids of the applications in the list field are displayed in the alert. Any thoughts on how to get the list collector variable to show the correct contents from the lookup table list field?

  8. Kapil M. July 22, 2014 at 9:17 am - Reply

    The above script is working fine whileusing it in a client script but throws an exception while using it in a ui script. If you are facing a similar issue kindly help.

  9. Joe W August 19, 2014 at 12:45 am - Reply

    Hi Mark, any idea how to clear any values in the Search window of a List Collector variable via script? We have a record producer with a List Collector variable on it. A user might enter a value to search on in the List Collector variable, in the Search box. Then depending on what the user does elsewhere on the form, the List Collector variable is sometimes either hidden or made visible again.

    Whenever the List Collector variable is hidden, we clear all values from the right column (which is working fine thanks to your scripts), but if the user makes List Collector variable reappear, anything they had in the Search box for previously in the List Collector is still there. Ideally, anytime we hide the List Collector variable, we’d like to clear any values from the search box at the same time, so that if they do come back to the List Collector variable, they get a fresh start, as if they’d never been there before.

    Any thoughts?

    • Mark Stanger August 19, 2014 at 7:20 am - Reply

      You should be able to do this by clearing out the HTML element and triggering the ‘keyup’ event like this…

      //Replace 'test' with the name of your list collector variable
      $('test_sys_user').value = '';
      $('test_sys_user').onkeyup();
  10. Nathan Giere March 10, 2015 at 11:13 am - Reply

    Hello Mr. Guru,

    I am running a Eureka Instance and am trying to get 1 record from the left bucket to the right. I have the set of code wrapped in a try – catch and it throws an error for this line moveSelectedOptions(moveSelectedOptions(selectedIDs,leftBucket, rightBucket, ‘–None–‘);. I know this is an older post and I am not sure if functions have changed over time. Any help would be appreciated.

    Thx,
    Nate

    • Mark Stanger March 12, 2015 at 2:31 pm - Reply

      It looks like ServiceNow has changed the function calls some. You can try replacing the final chunk of the code snippet above with this line and that should help.

      moveOptionAndSort(rightBucket, leftBucket, ‘–None–‘, selectedIDs, ‘–None–‘);

      • Nathan Giere March 23, 2015 at 3:00 pm - Reply

        I have taken the code from above and replaced what was needed. I am also setting the selectedIDs array with static values for testing purposes. Here is a very simplified version. I cannot get it to transfer any values from the left to the right.

        Thanks for all the great help,
        Nate

        function setBucket(){
        try{

        var varName = ‘u_related_request’;
        var leftBucket = gel(varName + ‘_select_0’);
        var rightBucket = gel(varName + ‘_select_1’);
        var selectedIDs = new Array();
        var index = 0;

        selectedIDs[0]=1;
        selectedIDs[1]=2;

        //Switch ‘rightBucket’ and ‘leftBucket’ to move from left to right
        moveOptionAndSort(rightBucket, leftBucket, ‘–None–’, selectedIDs, ‘–None–’);
        }catch(e){alert(e);}
        }

        I did find this in the DOM scripting which means the function is there:
        function moveOptionAndSort(
        sourceSelect,
        targetSelect,
        keepSourceLabel,
        unmovableSourceValues,
        keepTargetLabel) {
        moveOption(sourceSelect, targetSelect, keepSourceLabel, unmovableSourceValues, keepTargetLabel, null, null, sortSupported(targetSelect));
        }

  11. Nathan Giere March 26, 2015 at 8:41 am - Reply

    Mr. Guru,

    Here is the proposed solution that my team helped me come up with. Not sure if others might find this useful.
    It takes in a sysID and the Req# from the URL and prepopulates the right bucket with that value. Not sure how to post the script in format sorry.
    If you think this solution would propose any issues please let me know.

    Thanks,
    Nate

    var reqNumber;
    function onLoad() {

    var reqNumber2 = getParmVal(‘sysparm_risk’);

    if(reqNumber2){
    reqNumber = reqNumber2.split(‘,’);
    setBucket();
    }
    }

    function setBucket() {
    //Type appropriate comment here, and begin script below
    try{
    var varName = ‘u_related_request’;
    var rightBucket = gel(varName + ‘_select_1’);
    var option = document.createElement(“option”);
    option.value = reqNumber[0];
    option.text = reqNumber[1];
    rightBucket.add(option);
    var selectedOptions = rightBucket.options;

    }catch(e){alert(e);}
    }

    function getParmVal(name) {
    name = name.replace(/[\[]/,”\\\[“).replace(/[\]]/,”\\\]”);
    var regexS = “[\\?&]”+name+”=([^&#]*)”;
    var regex = new RegExp(regexS);
    var results = regex.exec( window.location.href );
    if(results == null){
    return “”;
    }
    else{
    return unescape(results[1]);
    }
    }

  12. Nick May 29, 2015 at 1:07 pm - Reply

    Hello, I’ve used the script for many features over the years; however it seems to have broken in Fuji as well, even after adjusting the new function call ‘moveOptionAndSort’. Any ideas?

  13. Sourabh April 28, 2016 at 12:04 pm - Reply

    Hi Mark,

    Is there any way we can do this in a workflow? I need to move all the available option from left to right on a task activity in a workflow for the variable: “Variables On Task Form”. As this is a client side script, is there any business side script?

    Kind regards,
    Sourabh Dhaygude

  14. Matt May 24, 2016 at 4:42 am - Reply

    I couldn’t get it to work by passing the IDs, certainly not in Geneva. So I had to do things a round about way. This is what I used if I know the sys_id of the left bucket value and wanted to move to the right bucket. I haven’t tested this extensively yet, but I’ve add the option to look up a missing value, add it and then move it across if needed. parseResponse being the callback from glide ajax.

    function parseResponse(response) {
        var answer = response.responseXML.documentElement.getAttribute("answer");
        var ans_arr = answer.split(",");
        for(var i = 0; i &lt; ans_arr.length; i++){

            if(jQuery(&#039;#services_select_0 option[value=&quot;&#039;+ans_arr[i]+&#039;&quot;]&#039;)){
                jQuery(&#039;#services_select_0 option[value=&quot;&#039;+ans_arr[i]+&#039;&quot;]&#039;).attr(&quot;selected&quot;, &quot;selected&quot;);
            }
            else{
                //Add missing option then move it across.
                var gBS = new GlideRecord(&quot;cmdb_ci_service&quot;);
                if(gBS.get(ans_arr[i])){
                    jQuery(&#039;#services_select_0&#039;).append(jQuery(&quot;", {
                        value: ans_arr[i],
                        text: gBS.name,
                        selected: "
    selected"
                    }));
                }
            }
           
        }
        moveOptionAndSort(gel('services_select_0'),gel('services_select_1'), '--None--', [], '--None--');
  15. Siaka Massaquoi August 3, 2016 at 10:18 am - Reply

    I’ve been running into an issue while running this code. For some reason, the function is running too fast and instead of pulling over everything from the avaiable column, its grabbing the ‘Loading’ text that appears while the list collector is loading. Do you know a way to have this function wait till the list collector is fully loaded?

    • Siaka Massaquoi August 9, 2016 at 8:00 am - Reply

      Figured it out. I just added a 2 sec timeout to give the page time to load.

  16. Sherard Pulmano March 20, 2017 at 7:22 am - Reply

    does this work any different if it was in a scoped app? I have this in a scoped app and the AJAX script is not be called at all.

  17. Brian Lancaster August 18, 2017 at 9:28 am - Reply

    Has this script been updated to work with the Service Portal?

    • Mila Morales September 21, 2017 at 1:20 pm - Reply

      This script will not work in Service Portal since the behavior of list collector in the default view and Service Portal is different. There are no left and right buckets in Service Portal’s list collector.

      • Mohammed January 29, 2018 at 2:13 pm - Reply

        Did anyone figure out on how to make this work in Service Portal?

        Thanks in advance.

  18. Sheetal January 9, 2018 at 6:19 pm - Reply

    Hi Mark,

    I am trying to copy RITM and have few list collector variables.Values are being copied but getting error” Unhandled exception in GlideAjax”.

    Have tried steps mentioned in KB article ServiceNow KB: Unable to set the value of a list collector using setValue() (KB0622779)

    Also used try & catch method.but still no luck.

    Any suggesstion?

  19. Sheetal January 9, 2018 at 6:20 pm - Reply

    we are on Jakarta patch 6a

  20. Mohammed January 29, 2018 at 2:14 pm - Reply

    Hi Mark,

    How can we achieve the same functionality in Service Portal?

    Thanks,

Leave A Comment