Here webdriver should click on each element, but the action is same, can you anyone help me
I am new to JavaScript
public void clickOnAllFiters(){
driver.findElement(By.cssSelector("div.scroll-item.all")).click();
driver.findElement(By.cssSelector("div.scroll-item.news")).click();
driver.findElement(By.cssSelector("div.scroll-item.results")).click();
driver.findElement(By.cssSelector("div.scroll-item.schedules")).click();
driver.findElement(By.cssSelector("div.scroll-item.images")).click();
driver.findElement(By.cssSelector("div.scroll-item.video")).click();
driver.findElement(By.cssSelector("div.scroll-item.comment")).click();
driver.findElement(By.cssSelector("div.scroll-item.activity")).click();
}
clickOnAllFilters("div.scroll-item.activity", "div.scroll-item.activity"); // You can add more, or simply send an array of strings.
public void clickOnAllFilters(String... filters)
{
for(String filter : filters)
{
driver.findElement(By.cssSelector(filter)).click();
}
}
Put the strings into an array and loop through the array.
String[] strings = new String[] {"div.scroll-item.all", ...};
for (String string : strings) {
driver.findElement(By.cssSelector(string)).click();
}
Related
i have setup a jquery bootgrid on a .net mvc web page, it shows me a grid with a few commands,like sorting,search autocomplete,scroll pages. Library is here: http://www.jquery-bootgrid.com/documentation
The grid works well, and i decided to send the commands through ajax to a function behind. The library then sends a list of strings to the function, used to handle the grid:
current 1
rowCount 10
sort[filename] asc
where filename is one of the columns for which i wanna sort. it could be sort[id], sort[name] or whatever i set my column to be.
the values are pretty clear, the ajax sends to the function the current grid page,the number of rows and the sorting direction.
but when i get in the function i can read only the first 2 values:
public ActionResult AjaxRequestData(string current,string rowCount,string sort)
this definition reads the first 2 values from the web page,but cannot read the sort ,because the actual name of the var is sort[filename], it's not an array of strings.if i either declare sort as string or string[],the result is always null.
How should i declare the variables in the action? So far i could read the sort by using formcollection["sort[filename]"],formcollection["sort[id]"] etc but i have a lot of columns and i really dont want to write out a condition for each one of them,is there any other solution to this?
Approch1.
consider you have table with columns "col1, col2, col3, ...".
you can use:
public ActionResult AjaxRequestData(string current,string rowCount,Sort sort){
//sort.col1 == 'asc' (consider sorted by col1 in ascending order)
}
public class Sort
{
public string col1 { get; set; }
public string col2 { get; set; }
public string col3 { get; set; }
//... other columns
}
Approach 2.
You can remove you parameters and parse data manually. (notice i used post here instead of get)
[HttpPost]
public object AjaxRequestData(){
string jsonContent = Request.Content.ReadAsStringAsync().Result;
Dictionary<string, string> keyvalues = new Dictionary<string, string>();
string[] keyvalue_strings = jsonContent.Split('&');
string sort_column = "";
string sort_direction = "";
for (var i = 0; i< keyvalue_strings.Length; i++)
{
var a = keyvalue_strings[i].Split('=');
a[0] = a[0].Replace("%5B", "[").Replace("%5D", "]");
keyvalues.Add(a[0], (a[1]));
if (a[0].Contains("sort"))
{
sort_column = a[0].Replace("sort[", "").Replace("]", "");
sort_direction = a[1];
}
}
//now you have keyvalues, sort_column, sort_direction.
//...
}
I'm using hashmap in Java to hold three pairs of servers in format (name,size), and then pass this hashmap to Javascript.
In Javascript there is no comma after the last entry:
data: [
{
name : "client3",
y:23,
},
{
name : "client1",
y:245,
},
{
name : "client2",
y:23,
}]
so I don't know how to get rid of this comma in Java using HashMap iterator :
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
out.println("name : \""+name+"\",");
out.println("y:"+size+",");
out.println("},");
}
Any ideas?
Instead of writing the comma at the end of the loop, write it at the beginning. It's much easier to check first iteration than last iteration.
boolean first = true;
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
if (first)
first = false;
else
out.println("},");
out.println("{");
out.println("name : \""+name+"\",");
out.println("y:"+size);
}
out.println("}");
BTW: You were missing the print of the start-brace {, and had a comma after the y value.
Update: Since that pattern for handling first iteration is so common, and the action is so simple (usually just appending a separator), I usually collapse the code as follows (don't do this if you have strict coding standards):
if (first) first = false; else out.println("},");
It seems you are creating JSON, so consider using proper JSON parser to generate your results. For instance with gson library your code could look like
Class containing single informations you want to store
public class Server{
private String name;
private int value;
public Server(String name, int value) {
this.name = name;
this.value = value;
}
//getters and setters
}
You can use this class like:
List<Server> list = new ArrayList<>();
list.add(new Server("1", 245));
list.add(new Server("2", 23));
list.add(new Server("3", 23));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(list);
System.out.println(json);
which will generate:
[
{
"name": "1",
"value": 245
},
{
"name": "2",
"value": 23
},
{
"name": "3",
"value": 23
}
]
You can add later data = at start if you absolutely need it.
If you can use Java 8, use StringJoiner
final StringJoiner stringJoiner = new StringJoiner(",");
Map<String,String> listClientSize = new HashMap<String,String>(){{
put("client3","23");
put("client1","245");
put("client2","23");
}};
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
stringJoiner.add(String.format("{name:\"%s\", y:%s}", name, size));
}
System.out.println(stringJoiner.toString());
To get rid of the comma after the y property, which is the last property in the object, just do this:
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
out.println("name : \""+name+"\",");
out.println("y:"+size);
out.println("},");
}
To get rid of the comma at the very end, instead of printing from the for loop, build up a string and then use substring to cut off the last character after your for loop, then print the string
One easy thing you could try is accumulating the string to print in a StringBuilder, and then stripping the last comma, using substring. It should look like this:
StringBuilder output = new StringBuilder();
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey();
String size = entry.getValue();
output.append("{name :\"").append(name).append("\", ");
output.append("y: ").append(size).append("},");
}
String toPrint = output.substring(1, output.size() - 1);
out.println(toPrint);
You probably need a way to tell if its not last entry then append the comma. One simplistic way is to keep a counter n n increment each iteration. If counter != hashmap size append comma
I am using javascript with knockout.js and I have 2 arrays:
self.timesheets = ko.observableArray();
self.selectedTimesheets = ko.observableArray();
I load the timesheet data like so:
$.ajax({
url: '/api/Invoice/GetPendingTimesheets',
type: 'GET',
success: function (timesheetData) {
self.timesheets(timesheetData);
}
});
Where the timesheets are defined like so:
public class Timesheet
{
public int Id { get; set; }
public DateTime WeekStart { get; set; }
}
The selectedTimesheets array keeps track of which checkboxes have been selected
What I would like to do is remove the elements in self.timesheets that are also in self.selectedtimesheets, and I am having a mental block figuring out how to do this:
I know there should be something like
self.timesheets.remove(function (el) {
// ????
});
But I just can't think of how to do it exactly.
Programmatically, you want to iterate through your self.timesheets array and compare each item's id to the ids in self.selectedtimesheets. If the ids match, you want to remove that item from self.timesheets.
Or push all items from both arrays into one new array and remove duplicates.
But since you're using Knockout, if you run the compareArrays utility function:
var differences = ko.utils.compareArrays(self.timesheets, self.selectedtimesheets);
differences will now be an array of only the different values.
I have the following classes defined
public ReportsViewmodel
{
public GeographicData GeographicData { get; set; }
...
}
public class GeographicData
{
public List<ZipcodeData> Regions { get; set; }
...
}
public class ZipcodeData
{
//TupleList is defined as public class TupleList<T1, T2> : List<Tuple<T1, T2>>
public TupleList<double, double> Boundries { get; set; }//Contains list of Lat/Long values for plotting on a map.
}
inside my view, I need to do something like this:
foreach (region in GeographicData.Regions)
foreach (boundry in region.Boundries)
add item1 & item2 to a 2 dimensional Javascript array
In the end, I want my javascript array to look like:
var vmBoundries= [[34.1, -85.4], [34.8, -85.234], [34.347, -85.345], [34.541, -85.434], [34.2341, -85.4]];
I can't figure out how to access the data from my view. I keep running into scope issue. For example, if I try to use a javascript for loop I can't index into my ViewModel lists because the loop variable is undefined when I call #Model.GeographicData.Regions[i]...
So how do I pull the data from my ViewModel into the Javascript array?
Typically you'd:
Transform the data into the format you want
Serialize the transformed data into JSON
Assign a JavaScript variable to the serialized value.
So, something like this:
#{
IEnumerable<double[]> flattened = vm.GeographicData.Regions
.SelectMany(region => region.Boundries
.Select(tpl => new double[] { tpl.Item1, tpl.Item2 }));
string json = new JavaScriptSerializer().Serialize(flattened);
}
<script type="text/javascript">
var arr = #json;
// do something with arr.
</script>
Something like:
var array = (from region in GeographicData.Regions
select from boundry in region.Boundries
select new object[] { boundry.Item1, boundry.Item2 }).ToArray();
This will give you a 2D array that you can then just serialize.
Example: https://dotnetfiddle.net/Y9KOaq
I would use a javascript serializer to make it easier:
using System.Web.Script.Serialization;
And add a helper method to ReportsViewmodel:
public string GetBoundriesJs()
{
var pairs =
from r in GeographicData.Regions
from b in r.Boundries
select new[] { b.Item1, b.Item2 };
return new JavaScriptSerializer().Serialize(pairs);
}
Then you can just call it where you need it in your view:
var vmBoundries = #Model.GetBoundriesJs();
I use JSON.net to serialize some objects between C# and JavaScript. The JSON data is transfered via WebSocket between the .NET and browser application.
In the data structure there are some byte[] fields, I want these fields as an Array in JavaScript also.
How can I serialize a C# byte[] to a simple JSON Array like [ 0 , 1 , 254, 255 ] instead of a base64 string?
JSON.NET is selecting the BinaryConverter to read and write an array of bytes. You can see in the source that it uses the WriteValue operation on the JsonWriter class with the array of bytes which causes them to be written to as Base-64.
To modify this, you can write your own converter which reads and writes an array in the format you expect:
public class ByteArrayConverter : JsonConverter
{
public override void WriteJson(
JsonWriter writer,
object value,
JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
return;
}
byte[] data = (byte[])value;
// Compose an array.
writer.WriteStartArray();
for (var i = 0; i < data.Length; i++)
{
writer.WriteValue(data[i]);
}
writer.WriteEndArray();
}
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
var byteList = new List<byte>();
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Integer:
byteList.Add(Convert.ToByte(reader.Value));
break;
case JsonToken.EndArray:
return byteList.ToArray();
case JsonToken.Comment:
// skip
break;
default:
throw new Exception(
string.Format(
"Unexpected token when reading bytes: {0}",
reader.TokenType));
}
}
throw new Exception("Unexpected end when reading bytes.");
}
else
{
throw new Exception(
string.Format(
"Unexpected token parsing binary. "
+ "Expected StartArray, got {0}.",
reader.TokenType));
}
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(byte[]);
}
}
You would use this by applying the JsonConverterAttribute to the member:
[JsonConverter(typeof(ByteArrayConverter))]
public byte[] Data { get; set; }
Simplest way I can think of is to convert the byte array into an integer array, like:
var intArray = byteArray.Select(b => (int)b).ToArray();
This wouldn't require any special handling of the JSON library, or any custom serialization or anything like that.
EDIT: This would mean having to customize your data object to handle the different type. Maybe:
public class CustomFoo : Foo
{
// SomeBytesHere is a byte[] in the base class
public new int[] SomeBytesHere { get;set; }
}
So maybe it's not the simplest - depending on how much stuff you have to serialize
Ref my answer, JSON.net can customze serialization in setting for all instead of attribute in property.
You can easily change it from base64 to number array, just write a square bracketed csv raw value.