What would i use to switch to a frame in Playwright - playwright

In selenium there is a method switchTo that can be used to switch to a frame.
Is there anything similar in Playwright?

Yes. The syntax is a bit different than Selenium but the idea is more or less the same. You can use frameLocator to drill down to the frame and interact with elements contained within. Think of it like switchTo().
For example, you have a <iframe> with a login form inside, and want to fill it:
const email = 'foo#bar.com'
await page.frameLocator('#sillyWidget iframe').locator('#username').click();
for (let i = 0; i < email.length; i += 1) {
await page.keyboard.press(email[i], { delay: 20 + Math.random() * 5 });
}
List all the frames on the page:
const frames = await page.childFrames();
for (const frame of frames) {
console.debug('Frame --> ' + frame.url())
}
Listen for new frames:
page.on('frameattached', frames => frames.forEach(frame => console.debug('Frame attached' + frame.url())));
Edit:
A Page already comprises the main Frame and all subframes, so the switchTo() analogy kind of breaks down in that regard. The frame already exists
inside the Page, so switching to it doesn't make sense.
In the case you want to perform many operations in a child frame, just grab a reference to it, and work with it like you would a Page (nearly all the same functions are available).
Also note that:
Playwright uses ChromeDevTools protocol to speak to the browser.
Selenium uses JSONW.
They are fundamentally different beasts, though some syntax is the same. CDP is orders of magnitude more powerful, and directly supported by chromium-based browsers by design.
const frame = page.frame('frame-login'); // reference to your frame
await frame.fill('#username-input', 'Phillip Masse'); // fill an input inside the frame
// [1]
await Promise.all([page.click('#btn'), page.waitForNavigation()]; // now do stuff on the page level
[1]: If memory serves, in selenium to accomplish this we'd need to driver.switch_to_default_content() here.

Context of Selenium driver vs Playwright page
Tl:dr - Driving the browser and everything inside it vs interacting with the browser and specific tabs (or “pages”) within it
Not exactly. Playwright takes a slightly different approach. Instead of just a driver which contains all the methods to drive the browser and anything within it, Playwright splits this into more specific pieces - browser, context, and page.
Browser is for the browser itself as a whole, which can contain many contexts and tabs.
BrowserContext for specific independent browsing sessions (for instance, a tab opened by another tab will be part of the same session or context).
Page for controlling a specific tab (or “page”) within the browser/context. Each separate tab will have its own Page instance to represent it.
The benefits of this include being able to share context between pages, working with multiple tabs simultaneously more easily, and other areas where the separation is useful. You’re not tied down to just using one driver instance for everything.
Specific Answer
For your question there’s an added piece, Frames, which you can access directly from a Page still, while also allowing you to interact with it separately/as its own entity or “page” in a way. The main page is really just its own top frame with page content, and each iframe is basically its own page with its own content.
The closest thing to switchTo here would be to just use .frame() to get the specific Frame and interact with it, whether by calling .frame each time or just storing, using, and passing around the frame itself. It has most of the main methods of Page you would use/need anyway, so in many cases can just be used in its place. So while not exactly like switchTo in making the page interact with the other frame (or tab) and having to switch back, because that was actually telling the driver to drive one vs the other, you can just access the Frame itself to interact with for those parts, and keep the page representing the full page.
Note that there is a difference between FrameLocator and Frame. The first solely provides a way to locate elements within an iframe, whereas the second is like another Page specific to that frame allowing you to interact with it similarly.

Related

How to query WidgetKit if my widgets are being used?

I would like to check if the user added my widgets to the Home Screen, is there an API for this? I could not find one. WidgetCenter.getCurrentConfigurations returns all available widgets served by the app, not the used ones.
The reasons I look for such an API are:
I would like to report usages of the widgets.
I would like to decide if I should trigger timeline reloads via WidgetCenter when state changes happen in the app.
Method WidgetCenter.shared.getCurrentConfigurations does return the number of user configured widgets:
WidgetCenter.shared.getCurrentConfigurations { widgets
if let widgets = widgets, widgets.count > 0 {
// User did configure at least one widgets
}
}
This is also according the documentation:
Retrieves information about user-configured widgets.
Unfortunately, I don't think such an API exists (yet).
For 1. I would write something that identifies the widget in a shared user defaults container. Hooks for that would be getSnapshot(for:,in:,completion:) or getTimeline(for:,in:,completion:) with context.isPreview == false. Now the difficult part is that you don't get any id for the widget so you cannot distinguish two widgets with the same configuration (afaik).
For 2. I think this is (and will be) opaque, so you just tell the WidgetCenter to reload specific or all configurations and when no widget is currently placed on the home screen nothing happens.

How should BloC be structured in Flutter?

I'm new to BloC and Flutter. For a single simple screen it should works without problem. But let's take a look at my case, I'm confused on how to use the BloC pattern.
I have a single screen called Container, which container a PageView of Content screen. Say I have 5 pages within that PageView. These pages count is dynamic. The pages only differ the data.
I'm thinking about 2 ways of implementing this:
1/ Using ONE single bloc and pass it to my 5 child Content.
2/ Using one bloc for the Container and another bloc for the Content. So this seems to be nested blocs. the ContainerBloc will contains the list of ContentBloc.
For the 1st approach. The problem that I see is the re-rendering problem. I will create a list of data of each page:
List<List<String>> allData = [];
BehaviorSubject<List<List<String>>> _allData = BehaviorSubject<List<List<String>>>();
Observable<List<String>> getData(index) => _allData.stream.map((list) => list[index]); //This stream returns the list at the index
and each page will listen to the data by:
//StreamBuilder in the UI
stream: widget.bloc.getData(index);
and the update method for the data should be like:
void updateData(int index, List<String> newData) {
List<String> temp = allData[index];
temp.add(newData);
allData[index] = temp;
_allData.sink.add(allData);
}
As I understand, once one page is updated. All other page will re-render because they all listen to the getData(index) stream which will be triggered by the_allData.sink.add(allData);
So I think all pages will be re-rendered even though the data of that page is not changed.
For the 2nd approach. I don't know if it would be best practice to have nested bloc like that. There maybe some case when the ContainerBloc must listen to some of the ContentBloc output.
I'm kinda confused now.
Thank you for your time.

how to track the social media icons using DTM (Dynamic tag manager)

I have the below code in my web site.
I want to track each anchor tag using DTM. I know how to track single element. Since here we have a bunch of different elements, can anyone help how to track them using DTM? I don't want to create separate rule for each element. In a single rule how can we track these elements.
Here is an example of what you can do.
For Element Tag or Selector put "a.at-share-btn" (no quotes). This will target all the relevant links first. We can look for this too in the next step, but "pre-qualifying" it with this will improve performance so that the rule is not evaluated against every single a click.
Then, under Rule Conditions, add a Criteria of type Data > Custom.
In the Custom box, add the following:
var shareType = this.getAttribute('class').match(/\bat-svc-([a-z_-]+)/i);
if (shareType&&shareType[1]) {
_satellite.setVar('shareType',shareType[1]);
return true;
}
return false;
This code looks for the class (e.g. "at-svc-facebook") and puts the last part of it (e.g. "facebook") into a data element named shareType.
Then, you can reference it using %shareType% in any of the DTM fields. Note: because this data element is made on-the-fly, it will not show up in the auto-complete when you type it out in a field.
Alternatively, in custom code boxes (e.g. if you are needing to reference it in a javascript/3rd party tag box), you can use _satellite.getVar('shareType')

Knockout js registerEvent handler

I'm having a great time playing around with knockout js and have just started to get to grips with adding custom bindingHandlers.
I'm struggling a bit with the update function of a 3rd party jqWidget gauge - I can only get it to animate the first time I update the variable. On each update after that it just sets the value directly.
I don't fully understand ko.utils.registerEventHandler() and what it does although I've seen it in a bunch of other examples. Is this what is causing the animation to break? How do I know which events to register from the 3rd party widget?
For some reason this works fine if I add a jquery ui slider that is also bound to the observable.
You can test this here: set the value a few times to see that it animates the first time and not after that.
http://jsfiddle.net/LkqTU/4531/
When you update the input field, your observable will end up being a string. It looks like the gauge does not like to be updated with a string value, at least after the first time.
So, if you ensure that you are updating it with a number (parseInt, parseFloat, or just + depending on the situation), then it appears to update fine.
Something like:
update: function(element, valueAccessor) {
var gaugeval = parseInt(ko.utils.unwrapObservable(valueAccessor()), 10);
$(element).jqxGauge('value', gaugeval || 0);
}
http://jsfiddle.net/rniemeyer/LkqTU/4532/
You would generally only register event handlers in a scenario like this to react to changes made by a user where you would want to update your view model data. For example, if there was a way for a user to click on the gauge to change the value, then you would want to handle that event and update your view model value accordingly.
I'm answering the
I don't fully understand ko.utils.registerEventHandler() and what it does
part of your question.
registerEventHandler will register your event handler function in a cross-browser compatible way. If you are using jQuery, Knockout will use jQuery's bind function to register the event handler. Otherwise, will use the browser Web API with a consistent behavior across browsers.
You can check it out on the source code.

AJAX pattern in Rails for submitting small chunks of data

I have a web page with lots of small images on it. In a typical scenario user clicks on image and expects it to change with a new image.
Requirements:
When user clicks on image, it should be immediately known to a controller in an Ajax way.
Some strings should be passed to a controller when user clicks on image.
Controller does its job and returns another image (which replaces old one).
Along with image controller returns a couple of extra strings (such as completion status).
Web page updates old image with new one and also updates other parts with these new strings.
Number of images on a page varies but potentially it can be a couple of dozens.
Question: What Ajax technique should be used here? I'm quite new to Ajax and don't feel solid with patterns. Should it be Json or something else?
Any code example would be very very welcome and helpful.
Thank you.
Well it sounds like you need a Event observer on the image object. On that image object, you could have various custom attributes, such as imageid="2", etc. With the element being observed onclick, you'd read the attributes of the elements and pass them on to an AJAX call. I'm not sure if the image is known by the database or would it be available on the page itself. Maybe a back/previous button? In either case, the AJAX call could either return JavaScript directly which then gets parsed to update the DOM and replaces the image with the new image source, or it could return a JSON response which then needs to get read and parsed by the AJAX callback and then updates the DOM. Easiest being to return JS code which gets parsed, but I prefer to have all my JavaScript in one file and not have it all over the place mixed with server side code.
It really depends on what AJAX library you are using.
With jQuery, you might do something like this.
$("#buttonImage").click(function () {
var imageid = $(this).attr('imageid');
$.getJSON("/controller/get_image/" + imageid,
function(data){
$("#buttonImage").attr("src", data.imagesrc);
});
});
And your /controller/get_image/123 would return a JSON response like...
{ 'imagesrc' : '/my/image.jpg' }
As far as I known, the only browser-safe way to change an image is by assigning a new URL to it's src attribute. If you return an image to a request that pass some parameters, it might prevent client-side cashing of the images. For these reasons, I would treat separately the transfer of textual data and images.
The completion status can always be return as the HTTP status text but if more information is needed from the server, you can always return it in JSON or XML, the simplest being JSON.
The responsiveness could be improved by preloading images on the mouseover event.

Resources