0

I'm trying to hack a SquareSpace site to change the selected value of a drop-down menu from a GET variable.

I'm struggling to reference the DOM element of the via document.getElementsByClassName or document.getElementsByID so I can change the value using JS.

SquareSpace has odd references to elements, and the HTML can't be changed, especially in this context. I'm a bit of a JavaScript novice and could use some help from the experts out there...

Question: How do I refer to the DOM element of the drop-down menu in JavaScript? Maybe using document.getElementBy...?

<div class="product-variants" data-item-id="5f6d19150f4fd9415d8a1586" data-variants="[{&quot;attributes&quot;:{&quot;Size&quot;:&quot;Small | 100 Photos&quot;},&quot;optionValues&quot;:[{&quot;optionName&quot;:&quot;Size&quot;,&quot;value&quot;:&quot;Small | 100 Photos&quot;}],&quot;id&quot;:&quot;68115c8d-399e-475b-8ea9-9543ad86cb02&quot;,&quot;sku&quot;:&quot;SQ5845728&quot;,&quot;price&quot;:11900,&quot;salePrice&quot;:0,&quot;priceMoney&quot;:{&quot;currency&quot;:&quot;USD&quot;,&quot;value&quot;:&quot;119.00&quot;},&quot;salePriceMoney&quot;:{&quot;currency&quot;:&quot;USD&quot;,&quot;value&quot;:&quot;0.00&quot;},&quot;onSale&quot;:false,&quot;unlimited&quot;:true,&quot;qtyInStock&quot;:0,&quot;width&quot;:0.0,&quot;height&quot;:0.0,&quot;weight&quot;:0.0,&quot;imageIds&quot;:[],&quot;images&quot;:[],&quot;len&quot;:0.0},{&quot;attributes&quot;:{&quot;Size&quot;:&quot;Medium | 250 Photos&quot;},&quot;optionValues&quot;:[{&quot;optionName&quot;:&quot;Size&quot;,&quot;value&quot;:&quot;Medium | 250 Photos&quot;}],&quot;id&quot;:&quot;dcfe8568-7199-4e68-91e2-d0f202fecdf7&quot;,&quot;sku&quot;:&quot;SQ2105082&quot;,&quot;price&quot;:26900,&quot;salePrice&quot;:0,&quot;priceMoney&quot;:{&quot;currency&quot;:&quot;USD&quot;,&quot;value&quot;:&quot;269.00&quot;},&quot;salePriceMoney&quot;:{&quot;currency&quot;:&quot;USD&quot;,&quot;value&quot;:&quot;0.00&quot;},&quot;onSale&quot;:false,&quot;unlimited&quot;:true,&quot;qtyInStock&quot;:0,&quot;width&quot;:0.0,&quot;height&quot;:0.0,&quot;weight&quot;:0.0,&quot;imageIds&quot;:[],&quot;images&quot;:[],&quot;len&quot;:0.0},{&quot;attributes&quot;:{&quot;Size&quot;:&quot;Large | 500 Photos&quot;},&quot;optionValues&quot;:[{&quot;optionName&quot;:&quot;Size&quot;,&quot;value&quot;:&quot;Large | 500 Photos&quot;}],&quot;id&quot;:&quot;494878cf-2af2-422c-91ec-e6d1850423aa&quot;,&quot;sku&quot;:&quot;SQ9044986&quot;,&quot;price&quot;:49900,&quot;salePrice&quot;:0,&quot;priceMoney&quot;:{&quot;currency&quot;:&quot;USD&quot;,&quot;value&quot;:&quot;499.00&quot;},&quot;salePriceMoney&quot;:{&quot;currency&quot;:&quot;USD&quot;,&quot;value&quot;:&quot;0.00&quot;},&quot;onSale&quot;:false,&quot;unlimited&quot;:true,&quot;qtyInStock&quot;:0,&quot;width&quot;:0.0,&quot;height&quot;:0.0,&quot;weight&quot;:0.0,&quot;imageIds&quot;:[],&quot;images&quot;:[],&quot;len&quot;:0.0}]" data-animation-role="content">
    <div class="variant-option">
        <div class="variant-option-title">Size: </div>
        <div class="variant-select-wrapper">
            <select aria-label="Select Size" data-variant-option-name="Size">
                <option value="">Select Size</option>
                <option value="Small | 100 Photos">Small | 100 Photos</option>
                <option value="Medium | 250 Photos">Medium | 250 Photos</option>
                <option value="Large | 500 Photos">Large | 500 Photos</option>
            </select>
        </div>
        <div class="variant-radiobtn-wrapper" data-variant-option-name="Size">
            <input type="radio" class="variant-radiobtn" value="Small | 100 Photos" name="variant-option-Size" id="variant-option-Size-Small | 100 Photos"/>
            <label for="variant-option-Size-Small | 100 Photos">Small | 100 Photos</label>
            <input type="radio" class="variant-radiobtn" value="Medium | 250 Photos" name="variant-option-Size" id="variant-option-Size-Medium | 250 Photos"/>
            <label for="variant-option-Size-Medium | 250 Photos">Medium | 250 Photos</label>
            <input type="radio" class="variant-radiobtn" value="Large | 500 Photos" name="variant-option-Size" id="variant-option-Size-Large | 500 Photos"/>
            <label for="variant-option-Size-Large | 500 Photos">Large | 500 Photos</label>
        </div>
    </div>
</div>

NOTE - I am able to refer to the data-item-id in CSS using the .page-section[data-section-id="5f7bc0326befc806d06d1e5b"] selector.

andrewniesen
  • 376
  • 2
  • 12
  • 1
    did you forget the question? All that build up and backstory...but no question. What is the issue exactly given you said this: "_I am able to refer to the data-item-id in CSS using the .page-section[data-section-id="5f7bc0326befc806d06d1e5b"] selector._" – Randy Casburn Nov 24 '20 at 21:22
  • @RandyCasburn Ah sorry. Question above. – andrewniesen Nov 24 '20 at 21:47
  • ok- good start - but which element? You can get the ` – Randy Casburn Nov 24 '20 at 21:52
  • right...but I'm confused about the syntax. `var x = document.getElementsByClassName("select[data-variant-option-name=Size]").id; alert(x);` That's what I've got - but it's not working. Again, I'm a JS novice, and I'm a bit stumped based on the documentation I've read – andrewniesen Nov 24 '20 at 22:02
  • my hope is to send a GET string ?size=Small%20%7C%20100%20Photos and change the selection of the drop down menu. – andrewniesen Nov 24 '20 at 22:05
  • You should be using `document.querySelector('...')` rather than 'getElementsByClassName()` – Randy Casburn Nov 24 '20 at 22:13

2 Answers2

1

First get the 'select' element and then the option you need and set the selected property to 'selected'. But be careful if more then one 'select' tags are existing. Since you are getting an array of elements you should know the index of the wanted one.

document.getElementsByTagName('select')[0].getElementsByTagName('option')[2].selected='selected';

Since you want to set by value you can use

document.getElementsByTagName('select')[0].value = 'Small | 100 Photos';

Best option would be to get the parent element you mentioned this way

document.querySelector('div[data-item-id="5f6d19150f4fd9415d8a1586"]')

and then go further to wanted element. This way you can be sure you have the right one. But it requires that the data-item-id is unique and static.

In combination it would look like this:

document.querySelector('div[data-item-id="5f6d19150f4fd9415d8a1586"]').getElementsByTagName('select')[0].value = 'Small | 100 Photos';
0

For those who are interested, here is my final code to solve the problem above, with @ÿmit's input. This was put into a code block in the footer of the SquareSpace commerce page.

<script type = "text/javascript">
    //https://www.denisbouquet.com/squarespace-code-injection-page-transition-run-script-page-reload/ - thanks to Denis Bouquet for this wrapper
    $(function() {
        function changeSizeMenu() {
                //put all get parameters into an object called $_GET
                //https://stackoverflow.com/a/12049737/2880312 - thanks to @gion_13 and @vrijdenker
                var $_GET = {};
                if (document.location.toString().indexOf('?') !== -1) {
                    var query = document.location
                        .toString()
                        // get the query string
                        .replace(/^.*?\?/, '')
                        // and remove any existing hash string (thanks, @vrijdenker)
                        .replace(/#.*$/, '')
                        .split('&');

                    for (var i = 0, l = query.length; i < l; i++) {
                        var aux = decodeURIComponent(query[i]).split('=');
                        $_GET[aux[0]] = aux[1];
                    }
                }

                //if the $_GET['select'] parameter is empty, return false
                if(!$_GET['Size'] || $_GET['Size'] == '') {
                //    return FALSE;
                    console.log("Get parameter 'Size' = " + $_GET['Size']); ////for debugging
                }

                //get array with all selects within data-item-id 5f6d19150f4fd9415d8a1586 - thanks @ÿmit
                var selectItems = document.querySelector('div[data-item-id="5f6d19150f4fd9415d8a1586"]').getElementsByTagName('select');

                //if the selectItems array is empty, return false
                if(!selectItems || selectItems.length == 0) {
                    //return FALSE;
                    console.log("selectItems is empty"); ////for debugging
                }

                //loop through all selects within data-item-id 5f6d19150f4fd9415d8a1586
                for (si = 0; si < selectItems.length; si++) {
                    if(selectItems[si].getAttribute("data-variant-option-name") == 'Size') {
                        //if the data-variant-option-name is "Size" - that's the array key we want. 
                        break;
                    } 
                }

                //get label element for later
                var label = document.querySelector('div[data-item-id="5f6d19150f4fd9415d8a1586"]').getElementsByClassName("variant-select-wrapper")[si];

                // get all the option items from the "Size" select menu; key identified as `si` above
                var optionItems = selectItems[si].getElementsByTagName('option')

                //if the optionItems array is empty, return false
                if(!optionItems || optionItems.length == 0) {
                    // return FALSE;
                    console.log("optionItems is empty"); ////for debugging
                }

                for (oi = 0; oi < optionItems.length; oi++) {
                    if(optionItems[oi].value == $_GET['Size']) {
                        console.log("MATCH" + optionItems[oi].value); //for debugging
                        //change the label on the drop-down menu
                        label.setAttribute("data-text", $_GET['Size']);
                        optionItems[oi].selected = 'selected';
                    } else {
                        optionItems[oi].selected = '';
                    }
                    console.log(oi + ":" + optionItems[oi].value); //for debugging
                } 
        }

        // run the function on first load of the website
        changeSizeMenu();

        // track every time we change of page
        $("body").on('click', ".Header-nav-item", function() {
            setTimeout(function() {
                changeSizeMenu();
            }, 500); // add a delay before to run the code again
        });
    })

</script>
andrewniesen
  • 376
  • 2
  • 12