How to pass variable into xpath expression in protractor with Javascript - javascript

I have to fetch a value from calendar, then add one to it and then use the added value to the xpath to get the next date in calendar. Below is the sample where am stuck. Appreciate any help regarding this
element(by.xpath('//span[#class="ng-binding text-info"]')).getText().then(function (text) {
var val = parseInt(text.value) + 1;
console.log('Next Day Date is ' + parseInt(text.value) + 1);
//How should i write val below?
element.by(by.xpath('//span[#text()='+"+val]'))
});

It's fairly simple, but the combination of single and double quotes looks confusing at first glance:
element(by.xpath("//span[#text()='" + val + "']"));

For me this worked:
var dt = new Date();
var current_day = (dt.getDate()).toString();
end_day = element.all(by.xpath("//span[text()='" + current_day + "']"));

Related

How can I convert the string value of a jQuery object into an actual jQuery object?

I have this string in my JS code right now:
newWords = '$(p span.word[style="--' + paraIndex + 'word-index:undefined"], p span.whitespace[style="--' + paraIndex + 'word-index:undefined"])';
I want to convert this string into a jQuery object that I can use do identify those specific elements.
I also saw the eval() function. That looks like it does what I want it to, but is super unsafe/unsecure.
Does anyone know a safe way to do this?
The simplest solution is to remove $( and ) and pass the remaining string as an argument to $():
var paraIndex = 0;
var newWords = '$(p span.word[style="--' + paraIndex
+ 'word-index:undefined"], p span.whitespace[style="--'
+ paraIndex + 'word-index:undefined"])';
var jQ = $(newWords.slice(2, -1));
console.log(jQ);
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

How to I get javascript date split code to work for all browsers?

I have a piece of code that works in Chrome and MSIE but failing in Opera and Firefox
var end = Browser.getValue(getElement("mydate"));
var parts = end.split('.');
var us_date = parts[1]+'/'+parts[0]+'/'+parts[2];
var someDate = new Date(us_date);
var numberOfDaysRemove = 1;
someDate.setDate(someDate.getDate() - numberOfDaysRemove);
var returndate = someDate.getDate() + '.' + (someDate.getMonth() + 1) + '.' + someDate.getFullYear() + " " + someDate.getHours() + ':' + someDate.getMinutes();
I know why it doesn't work in Opera and Firefox as I need to replace the
var parts = end.split('.');
var returndate = someDate.getDate() + '.' + (someDate.getMonth() + 1) + '.' + someDate.getFullYear() + " " + someDate.getHours() + ':' + someDate.getMinutes();
with
var parts = end.split('/');
var returndate = someDate.getDate() + '/' + (someDate.getMonth() + 1) + '/' + someDate.getFullYear() + " " + someDate.getHours() + ':' + someDate.getMinutes();
When I do this then it won't work in Chrome or MSIE.
Is there a way to get this code to work in all browsers?
You should never parse strings using the Date constructor or Date.parse (which do the same thing) as it is almost entirely implementation dependent and unreliable. Always manually parse strings, a library can help but if you only need to support one or two formats, a bespoke function is trivial.
Given that you have:
var end = Browser.getValue(getElement("mydate"));
var parts = end.split('.');
var us_date = parts[1]+'/'+parts[0]+'/'+parts[2];
I suspect end is something like "dd.mm.yyyy", so replace the last line with:
var someDate = new Date(parts[2], parts[1]-1, parts[0]);
which will work in every browser since javascript was invented.
Edit
Presuming that the date string is "dd.mm.yyyy", a simple function to parse it regardless of the separator is:
/* Parse date string in format d/m/y
** #param {string} s - date string
** #returns {Date} date object
*/
function parseDMY(s) {
var b = s.split(/\D/);
return new Date(b[2], b[1]-1, b[0]);
}
document.write(parseDMY('23.01.2016'));
This assumes that the values are a valid date and will allow any non–digit separator, so d.m.y, d/m/y and d-m-y are all acceptable.
My suggestion is to use something like jquery to manipulate the DOM.
Jquery, adding a level of abstraction, allows to avoid having to adapt the code to the "single browser standard", because even though today is a bit better (than years ago), basically there is still no real standard.
So for instance, if you do $('#mydate') jquery will retrieve that element in every browser (using IE getElementById etc...) and you don't need anymore to worry about your code to be cross-browser.
$('#mydate').val() //assuming it to be an input, will retrieve the value and then you can work with your own logic.
Hope it helps.

JS var inside query does not work when stringed together

I have the following code which is really bloated
$(".field-name-field-parts-status .field-item:contains('Submitted'), .field-name-field-parts-status .field-item:contains('Saved'), .field-name-field-parts-status .field-item:contains('HMNZ Approved')").addClass('btn-primary');
I tried to neaten it up by adding a var
var fieldItemStatus = $(".field-name-field-parts-status .field-item");
So it looked like this
$(fieldItemStatus + ":contains('Submitted'), " + fieldItemStatus + ":contains('Saved'), " + fieldItemStatus + ":contains('HMNZ Approved')").addClass('btn-primary');
But it stopped working, can anyone tell me what I did wrong? Thanks
Because you are trying to add a jQuery object and a string together. It does not work like that.
var fieldItemStatus = $(".field-name-field-parts-status .field-item");
should be a string
var fieldItemStatus = ".field-name-field-parts-status .field-item";
other option is to use filter.
You need to use .filter()
fieldItemStatus.filter(":contains('Submitted'), :contains('Saved'), :contains('HMNZ Approved')").addClass('btn-primary');
fieldItemStatus is an object so
fieldItemStatus + ":contains('Submitted'), " + fieldItemStatus + ":contains('Saved'), " + fieldItemStatus + ":contains('HMNZ Approved') will create a string like [Object object]:contains('Submitted'), [Object object]:contains('Saved'), [Object object]:contains('HMNZ Approved')
remove $ in front for fieldItemStatus
var fieldItemStatus = ".field-name-field-parts-status .field-item";
Because you want to use a jQuery Object to concat string. The right way to do this is using string all the time.
var fieldItemStatus = ".field-name-field-parts-status .field-item";
$(fieldItemStatus + ":contains('Submitted'), " + fieldItemStatus + ":contains('Saved'), " + fieldItemStatus + ":contains('HMNZ Approved')").addClass('btn-primary');
You could use the filter method:
fieldItemStatus.filter(":contains('Submitted'), :contains('Saved'), :contains('HMNZ Approved')").addClass('btn-primary');
Another option is using the filter callback function:
var items = ['Submitted', 'Saved', 'HMNZ Approved'];
fieldItemStatus.filter(function(_, el) {
return items.some(function(item) {
return el.textContent.indexOf(item) > -1;
});
});
.
A more procedural approach. This way if you want to easily change the selectors, just change the contains array. You could turn this into a function to easily retrieve your selector on demand elsewhere in the script.
var contains = ['Submitted','Saved','HMNZ Approved'];
var selector = '';
for(var i = 0; i < contains.length; i++) {
selector += '.field-name-field-parts-status .field-item:contains("' + contains[i] + ')';
if(i < contains.length - 1) selector += ', ';
}
$(selector).addClass('btn-primary');

How to write arguments in function?

I have been using functions but I am not able to tackle this.
What I have done is created a function, then made this to use the values provided by the document class or ids and do the work. Once work is done then just give the data back! It worked!
Now I want to make this function happen for two divs, the first function works good. The issue is with the second one. The function is correct, their is some other bug while writing the result.
Here is my code:
function time_untilCom(id) {
var Time2 = Date.parse(document.getElementById("time_" + 2).value);
var curTime2 = new Date();
var timeToWrite2 = "";
var seconds2 = Math.floor((curTime2 - Time2) / (1000));
if (seconds2 > 0 && seconds2 < 60) {// seconds..
timeToWrite2 = seconds2 + " seconds ago";
$('#update_' + 2).html(seconds2);
$('#jstime_' + 2).html(timeToWrite2 + " <b>Time that was captured!</b>");
}
}
If I use it as it is, it works! The issue comes when I try to replace these
("time_" + 2), ("#update_" + 2), ("#jstime" + 2) with ("time_" + id), ("#update_" + id), ("#jstime_" + id).
What i want to happen is that the function would be provided with a common ID that is applied throughout the div and use that ID, to get the value of time, convert it to seconds, do other stuff and then provide me with the result in the corresponding element with the id that was in the argument.
function works great, it do provide me with the result. But the issue is with the id its not being sent I guess. Or if is being sent then not being applied. What might be the issue here? And don't mind the seconds i have that covered too.
I am really very sorry for short code:
Pardon me, I was about to write the code for the function too. But electricity ran out!
Here is the code: onload="time_untilCom('2'), this is the way I am executing this.
And once in the main code, it will be executed like this: onload="time_untilCom(#row.Id) because I am using ASP.NET Web Pages I will be using the server side code to write the ID from Database. And will then user the ID throughtout the div to update the time!
From what I understand, you probably want to replace the second line
var Time2 = Date.parse(document.getElementById("time_" + 2).value);
with
var Time2 = Date.parse(document.getElementById(id).value);
And at the end you can also use
$('#'+id).html(timeToWrite2 + " <b>Time that was captured!</b>");
You are passing "id" as an argument, but you never use it inside the function. My question is: In your example you are using 2 as appendix to id attributes. Is it the 2 (or other numbers respectively) that you want to have as the id parameter of the function?
Then you could just replace each + 2 in your code by + id
function time_untilCom(id) {
var Time2 = Date.parse(document.getElementById("time_" + id).value);
var curTime2 = new Date();
var timeToWrite2 = "";
var seconds2 = Math.floor((curTime2 - Time2) / (1000));
if (seconds2 > 0 && seconds2 < 60) {// seconds..
timeToWrite2 = seconds2 + " seconds ago";
$('#update_' + id).html(seconds2);
$('#jstime_' + id).html(timeToWrite2 + " <b>Time that was captured!</b>");
}
}
EDIT: Please tell us where and how exactly do you call time_untilCom? Did you pass the id there?

Javascript eval

I am trying to get the following working. It seemed to work initially, but somehow it stopped working
var setCommonAttr = "1_row1_common";
var val = document.getElementById("abc_" + eval("setCommonAttr")).value;
what is wrong with above?
The above code is little different from what I am trying to accomplish. I gave the above example just not to make things complicated here. Below is what I am trying to accomplish:
First I am getting an existing element as follows. The element is a
<tr id="row_1_4_2009_abc" class="rowclick">
<td></td>
</tr>
I am using jquery to get the id on click of a row:
$(".rowclick").click(function() {
var row_id = $(this).attr("id");
var getAttributes = row_id.split("_");
var setCommonAttr = getAttributes[1] + "_" + getAttributes[2] + "_" + getAttributes[3] + "_" + getAttributes[4];
var new_row_id = document.getElementById("new_row_" + setCommonAttr).value;
});
You shouldn't need eval() to do this. The value you want is already a variable in JavaScript. Try:
var setCommonAttr = "1_row1_common";
var val = document.getElementById("abc_" + setCommonAttr).value;
Will everything be in that form? row_xxx_xxx_xxx_xxx
if so, why not var new_row_id = document.getElementById("new_" + row_id).value;
You don't need to call eval().
You can just concatenate the string with the variable:
var setCommonAttr = "1_row1_common"; var val = document.getElementById("abc_" + setCommonAttr).value;

Categories

Resources