How Can I Click the Last Matching XPath on a Web Page?

I'm trying to interact with a page that has a series of identical buttons.

//a[@ng-click='addNewSignature(question)'][last()]
clicks the first instance

//a[@ng-click='addNewSignature(question)']/last()
doesn't do anything at all

Is there a way to click the last matching item on the page?

Yes, but would not use XPath. I prefer querySelectorAll:

This will click on the LAST "Reply" button on any forum topic:

var elemCol = document.querySelectorAll('button.widget-button.btn-flat.reply.create.fade-out.btn-icon-text');
var numElem = elemCol.length;
var elemLast = elemCol[numElem - 1];
elemLast.click();

Just put this JavaScript in a Execute a JavaScript in Browser action.

3 Likes

Thanks for your response! I'm dealing with a kind of messy web app that doesn't give any names or identifying characteristics to many of its page components, and can't figure out how to get it working with either XPath or your javascript method. I may be out of luck on this one but appreciate your help.

It is rare that we can't identify a HTML element by its path.
If you want to post your URL, or upload a zip file of the HTML code, I'll take a look at it.
Also provide a screenshot that is annotated to show the link you want to click on.

Well I definitely won't turn down your offer to take a look! :smiley:

The web app is a scheduling system called IntakeQ -- it lets you build form templates, and when you're filling one out there are buttons with dropdown menus that allow you to add additional items into the form.

Attached you can see an image of the button (marked "+") and the menu that pops up when you click it. My first impulse was to find the link directly instead of clicking the button first, but the app seems to take info about where to insert the new section based on which button is clicked. So I think have to first click the last plus button on the page, and then click the last "Add New Signature" link on the page.

Image 1, the plus button:

Image 2, the popup menu:

Image 3 the plus button object:

Here's the code for the last content box on the page (labelled "Progress" and containing the last plus button":


        <fieldset>

            <div class="panel-body">

                <div class="number-square" ng-class="{current: question.focused, answered:question.isanswered}" ng-hide="question.QuestionType==16">

                    13

                </div>
                <div class="move-to-note ui-draggable ui-draggable-handle" uib-tooltip="Drag this item to a note on the left panel." tooltip-append-to-body="true" draggable-question="question" draggable-target=".timeline .list .item">
                    <i class="fa fa-arrows"></i>
                </div>

                <!--<i ng-show="question.isanswered && question.OfficeUse" class="answered glyphicon glyphicon-ok"></i>-->


                <!----><h4 ng-if="question.QuestionType != 9">
                    <pre> Progress <!----></pre>
                </h4><!---->

                <!---->

                <!---->

                <!----><div ng-if="!intake.Questionnaire.IsLocked">
                    <ng-switch on="question.QuestionType">

                        <!---->
                        <!---->
                        <!---->
                        <!---->
                        <!---->
                        <!---->
                        <!---->
                        <!---->
                        <!----><div ng-switch-when="10">
                            <!----><ng-include src="'Mixed.html'">

<div class="form mixed" style="margin-left:-10px;">

    <!----><div ng-repeat="row in ::getRows(question)" class="row">

        <!----><div ng-repeat="i in row" class="form-group text-item col-md-12">

            <!---->
            <!---->
            <!----><div ng-if="i.Type==2" ng-class="{'item-ignored':i.ignored}">
                <label ng-show="i.Text" for="input1" class="control-label">Patient condition: <!----><span ng-if="i.IsRequired &amp;&amp; enableAsterisk" class="asterisk">*</span><!----></label>
                <div style="">
                    <!----><label ng-repeat="option in ::i.PossibleAnswers track by $index" class="normal-weight">
                        <input type="radio" icheck-intake="" name="q_15_1" ng-model="i.Answer" ng-value="i.PossibleAnswers[$index]" ng-change="changed(question, i)" class="ng-pristine ng-untouched ng-valid ng-empty" value="Improving">
                        <span>Improving</span>
                    </label><!----><label ng-repeat="option in ::i.PossibleAnswers track by $index" class="normal-weight">
                        <input type="radio" icheck-intake="" name="q_15_1" ng-model="i.Answer" ng-value="i.PossibleAnswers[$index]" ng-change="changed(question, i)" class="ng-pristine ng-untouched ng-valid ng-empty" value="Stable">
                        <span>Stable</span>
                    </label><!----><label ng-repeat="option in ::i.PossibleAnswers track by $index" class="normal-weight">
                        <input type="radio" icheck-intake="" name="q_15_1" ng-model="i.Answer" ng-value="i.PossibleAnswers[$index]" ng-change="changed(question, i)" class="ng-pristine ng-untouched ng-valid ng-empty" value="Worsening">
                        <span>Worsening</span>
                    </label><!---->
                </div>
            </div><!---->
            <!---->








              <!---->
            <!---->
            <!---->
            <!---->
            <!---->
            <!---->
            <!---->
            <!---->
             <!---->
            <!---->
            <!---->
            <!---->
        </div><!---->


    </div><!---->
</div>
                <!---->
                
                <!--<div class="form-group" ng-show="::(!intake.Questionnaire.IsLocked && question.QuestionType == 13 && !canAddMoreRows(question))">
                    <button class="btn btn-primary" ng-click="addMatrixRow(question)"><i class="fa fa-plus"></i> Add Empty Row</button>
                </div>-->

                <div class="row">
                    <div class="col-sm-12">
                        <div class="form-group further ng-hide" ng-show="!intake.Questionnaire.IsLocked &amp;&amp; question.DisplayFurtherExplanation">
                            <label ng-show="question.FurtherExplanationLabel" class="ng-hide"></label>
                            <textarea class="form-control ng-pristine ng-untouched ng-valid ng-empty" msd-elastic="" ng-model="question.FurtherExplanation" rows="1" ng-change="textChanged()" style="overflow: hidden; word-wrap: break-word; resize: horizontal; height: 32px;"></textarea>
                        </div>
                        <div class="form-group further ng-hide" style="margin-top: 10px;" ng-show="intake.Questionnaire.IsLocked &amp;&amp; question.DisplayFurtherExplanation">
                            <label ng-show="question.FurtherExplanationLabel" class="ng-hide"></label>
                            <div class="answer-text">
                                <pre></pre>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="form-group text-right" style="margin-bottom: 0" ng-show="!intake.Questionnaire.IsLocked">

                    <button class="btn btn-sm btn-default ng-hide" uib-tooltip="Select Snippet" ng-hide="question.QuestionType != 1 &amp;&amp; question.QuestionType != 2" ng-click="openSnippets(question)">

                        <i class="fa fa-flash"></i>
                    </button>
                    <div style="display: inline-block" ng-hide="!intake.Questionnaire.IsPinned &amp;&amp; !canEditTemplate">
                        &nbsp;
                        <div class="btn-group">
                            <button class="btn btn-sm btn-default dropdown-toggle" uib-tooltip="Add a new item below" tooltip-append-to-body="true" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <i class="fa fa-plus"></i>
                            </button>
                            <ul class="dropdown-menu dropdown-menu-round dropdown-menu-left text-left">
                                <li>
                                    <a ng-click="addQuestion(question)">
                                        Add New Text Item
                                    </a>
                                </li>
                                <li>
                                    <a ng-click="addNewAttachment(question)">
                                        Add New Attachment
                                    </a>
                                </li>
                                <li>
                                    <a ng-click="addNewSignature(question)">
                                        Add New Signature
                                    </a>
                                </li>
                                <li>
                                    <a ng-click="addRichText(question)">
                                        Add Rich Text
                                    </a>
                                </li>
                            </ul>
                        </div>

                        &nbsp;
                        <button class="btn btn-sm btn-default" uib-tooltip="Move this item up" ng-click="moveQuestion(question, -1)" ng-disabled="$index==0">
                            <i class="fa fa-chevron-up"></i>
                        </button>&nbsp;
                        <button class="btn btn-sm btn-default" uib-tooltip="Move this item down" ng-click="moveQuestion(question, 1)" ng-disabled="$index == intake.Questionnaire.Questions.length - 1">
                            <i class="fa fa-chevron-down"></i>
                        </button>
                        &nbsp;
                        <button class="btn btn-sm btn-default" uib-tooltip="Delete item" ng-click="deleteQuestion(question)">
                            <i class="fa fa-times"></i>
                        </button>    
                    </div>
                </div>
            </div>
        </fieldset>
    </div>

Shame javascript doesn't have a [-1] construction for the last element of an array.