Best JavaScript code snippet using playwright-internal
crPage.js
Source:crPage.js
...162 async updateGeolocation() {163 await this._forAllFrameSessions(frame => frame._updateGeolocation(false));164 }165 async updateOffline() {166 await this._forAllFrameSessions(frame => frame._updateOffline(false));167 }168 async updateHttpCredentials() {169 await this._forAllFrameSessions(frame => frame._updateHttpCredentials(false));170 }171 async setEmulatedSize(emulatedSize) {172 (0, _utils.assert)(this._page._state.emulatedSize === emulatedSize);173 await this._mainFrameSession._updateViewport();174 }175 async bringToFront() {176 await this._mainFrameSession._client.send('Page.bringToFront');177 }178 async updateEmulateMedia() {179 await this._forAllFrameSessions(frame => frame._updateEmulateMedia(false));180 }181 async updateRequestInterception() {182 await this._forAllFrameSessions(frame => frame._updateRequestInterception());183 }184 async setFileChooserIntercepted(enabled) {185 await this._forAllFrameSessions(frame => frame._setFileChooserIntercepted(enabled));186 }187 async reload() {188 await this._mainFrameSession._client.send('Page.reload');189 }190 async _go(delta) {191 const history = await this._mainFrameSession._client.send('Page.getNavigationHistory');192 const entry = history.entries[history.currentIndex + delta];193 if (!entry) return false;194 await this._mainFrameSession._client.send('Page.navigateToHistoryEntry', {195 entryId: entry.id196 });197 return true;198 }199 goBack() {200 return this._go(-1);201 }202 goForward() {203 return this._go(+1);204 }205 async evaluateOnNewDocument(source, world = 'main') {206 await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(source, world));207 }208 async closePage(runBeforeUnload) {209 if (runBeforeUnload) await this._mainFrameSession._client.send('Page.close');else await this._browserContext._browser._closePage(this);210 }211 async setBackgroundColor(color) {212 await this._mainFrameSession._client.send('Emulation.setDefaultBackgroundColorOverride', {213 color214 });215 }216 async takeScreenshot(progress, format, documentRect, viewportRect, quality, fitsViewport) {217 const {218 visualViewport219 } = await this._mainFrameSession._client.send('Page.getLayoutMetrics');220 if (!documentRect) {221 documentRect = {222 x: visualViewport.pageX + viewportRect.x,223 y: visualViewport.pageY + viewportRect.y,224 ..._helper.helper.enclosingIntSize({225 width: viewportRect.width / visualViewport.scale,226 height: viewportRect.height / visualViewport.scale227 })228 };229 } // When taking screenshots with documentRect (based on the page content, not viewport),230 // ignore current page scale.231 const clip = { ...documentRect,232 scale: viewportRect ? visualViewport.scale : 1233 };234 progress.throwIfAborted();235 const result = await this._mainFrameSession._client.send('Page.captureScreenshot', {236 format,237 quality,238 clip,239 captureBeyondViewport: !fitsViewport240 });241 return Buffer.from(result.data, 'base64');242 }243 async getContentFrame(handle) {244 return this._sessionForHandle(handle)._getContentFrame(handle);245 }246 async getOwnerFrame(handle) {247 return this._sessionForHandle(handle)._getOwnerFrame(handle);248 }249 isElementHandle(remoteObject) {250 return remoteObject.subtype === 'node';251 }252 async getBoundingBox(handle) {253 return this._sessionForHandle(handle)._getBoundingBox(handle);254 }255 async scrollRectIntoViewIfNeeded(handle, rect) {256 return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect);257 }258 async setScreencastOptions(options) {259 if (options) {260 await this._mainFrameSession._startScreencast(this, {261 format: 'jpeg',262 quality: options.quality,263 maxWidth: options.width,264 maxHeight: options.height265 });266 } else {267 await this._mainFrameSession._stopScreencast(this);268 }269 }270 rafCountForStablePosition() {271 return 1;272 }273 async getContentQuads(handle) {274 return this._sessionForHandle(handle)._getContentQuads(handle);275 }276 async setInputFiles(handle, files) {277 await handle.evaluateInUtility(([injected, node, files]) => injected.setInputFiles(node, files), files);278 }279 async adoptElementHandle(handle, to) {280 return this._sessionForHandle(handle)._adoptElementHandle(handle, to);281 }282 async getAccessibilityTree(needle) {283 return (0, _crAccessibility.getAccessibilityTree)(this._mainFrameSession._client, needle);284 }285 async inputActionEpilogue() {286 await this._mainFrameSession._client.send('Page.enable').catch(e => {});287 }288 async pdf(options) {289 return this._pdf.generate(options);290 }291 coverage() {292 return this._coverage;293 }294 async getFrameElement(frame) {295 let parent = frame.parentFrame();296 if (!parent) throw new Error('Frame has been detached.');297 const parentSession = this._sessionForFrame(parent);298 const {299 backendNodeId300 } = await parentSession._client.send('DOM.getFrameOwner', {301 frameId: frame._id302 }).catch(e => {303 if (e instanceof Error && e.message.includes('Frame with the given id was not found.')) (0, _stackTrace.rewriteErrorMessage)(e, 'Frame has been detached.');304 throw e;305 });306 parent = frame.parentFrame();307 if (!parent) throw new Error('Frame has been detached.');308 return parentSession._adoptBackendNodeId(backendNodeId, await parent._mainContext());309 }310}311exports.CRPage = CRPage;312class FrameSession {313 // Marks the oopif session that remote -> local transition has happened in the parent.314 // See Target.detachedFromTarget handler for details.315 constructor(crPage, client, targetId, parentSession) {316 this._client = void 0;317 this._crPage = void 0;318 this._page = void 0;319 this._networkManager = void 0;320 this._contextIdToContext = new Map();321 this._eventListeners = [];322 this._targetId = void 0;323 this._firstNonInitialNavigationCommittedPromise = void 0;324 this._firstNonInitialNavigationCommittedFulfill = () => {};325 this._firstNonInitialNavigationCommittedReject = e => {};326 this._windowId = void 0;327 this._swappedIn = false;328 this._videoRecorder = null;329 this._screencastId = null;330 this._screencastClients = new Set();331 this._client = client;332 this._crPage = crPage;333 this._page = crPage._page;334 this._targetId = targetId;335 this._networkManager = new _crNetworkManager.CRNetworkManager(client, this._page, parentSession ? parentSession._networkManager : null);336 this._firstNonInitialNavigationCommittedPromise = new Promise((f, r) => {337 this._firstNonInitialNavigationCommittedFulfill = f;338 this._firstNonInitialNavigationCommittedReject = r;339 });340 client.once(_crConnection.CRSessionEvents.Disconnected, () => {341 this._firstNonInitialNavigationCommittedReject(new Error('Page closed'));342 });343 }344 _isMainFrame() {345 return this._targetId === this._crPage._targetId;346 }347 _addRendererListeners() {348 this._eventListeners.push(...[_eventsHelper.eventsHelper.addEventListener(this._client, 'Log.entryAdded', event => this._onLogEntryAdded(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameDetached', event => this._onFrameDetached(event.frameId, event.reason)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame, false)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameRequestedNavigation', event => this._onFrameRequestedNavigation(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.javascriptDialogOpening', event => this._onDialog(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.bindingCalled', event => this._onBindingCalled(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.consoleAPICalled', event => this._onConsoleAPI(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Runtime.executionContextsCleared', event => this._onExecutionContextsCleared()), _eventsHelper.eventsHelper.addEventListener(this._client, 'Target.attachedToTarget', event => this._onAttachedToTarget(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Target.detachedFromTarget', event => this._onDetachedFromTarget(event))]);349 }350 _addBrowserListeners() {351 this._eventListeners.push(...[_eventsHelper.eventsHelper.addEventListener(this._client, 'Inspector.targetCrashed', event => this._onTargetCrashed()), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.screencastFrame', event => this._onScreencastFrame(event)), _eventsHelper.eventsHelper.addEventListener(this._client, 'Page.windowOpen', event => this._onWindowOpen(event))]);352 }353 async _initialize(hasUIWindow) {354 if (hasUIWindow && !this._crPage._browserContext._browser.isClank() && !this._crPage._browserContext._options.noDefaultViewport) {355 const {356 windowId357 } = await this._client.send('Browser.getWindowForTarget');358 this._windowId = windowId;359 }360 let screencastOptions;361 if (this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {362 const screencastId = (0, _utils.createGuid)();363 const outputFile = _path.default.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + '.webm');364 screencastOptions = { // validateBrowserContextOptions ensures correct video size.365 ...this._crPage._browserContext._options.recordVideo.size,366 outputFile367 };368 await this._crPage._browserContext._ensureVideosPath(); // Note: it is important to start video recorder before sending Page.startScreencast,369 // and it is equally important to send Page.startScreencast before sending Runtime.runIfWaitingForDebugger.370 await this._createVideoRecorder(screencastId, screencastOptions);371 this._crPage.pageOrError().then(p => {372 if (p instanceof Error) this._stopVideoRecording().catch(() => {});373 });374 }375 let lifecycleEventsEnabled;376 if (!this._isMainFrame()) this._addRendererListeners();377 this._addBrowserListeners();378 const promises = [this._client.send('Page.enable'), this._client.send('Page.getFrameTree').then(({379 frameTree380 }) => {381 if (this._isMainFrame()) {382 this._handleFrameTree(frameTree);383 this._addRendererListeners();384 }385 const localFrames = this._isMainFrame() ? this._page.frames() : [this._page._frameManager.frame(this._targetId)];386 for (const frame of localFrames) {387 // Note: frames might be removed before we send these.388 this._client._sendMayFail('Page.createIsolatedWorld', {389 frameId: frame._id,390 grantUniveralAccess: true,391 worldName: UTILITY_WORLD_NAME392 });393 for (const binding of this._crPage._browserContext._pageBindings.values()) frame.evaluateExpression(binding.source, false, undefined).catch(e => {});394 for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources) frame.evaluateExpression(source, false, undefined, 'main').catch(e => {});395 }396 const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':';397 if (isInitialEmptyPage) {398 // Ignore lifecycle events for the initial empty page. It is never the final page399 // hence we are going to get more lifecycle updates after the actual navigation has400 // started (even if the target url is about:blank).401 lifecycleEventsEnabled.catch(e => {}).then(() => {402 this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));403 });404 } else {405 this._firstNonInitialNavigationCommittedFulfill();406 this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)));407 }408 }), this._client.send('Log.enable', {}), lifecycleEventsEnabled = this._client.send('Page.setLifecycleEventsEnabled', {409 enabled: true410 }), this._client.send('Runtime.enable', {}), this._client.send('Page.addScriptToEvaluateOnNewDocument', {411 source: '',412 worldName: UTILITY_WORLD_NAME413 }), this._networkManager.initialize(), this._client.send('Target.setAutoAttach', {414 autoAttach: true,415 waitForDebuggerOnStart: true,416 flatten: true417 })];418 if (this._isMainFrame()) promises.push(this._client.send('Emulation.setFocusEmulationEnabled', {419 enabled: true420 }));421 const options = this._crPage._browserContext._options;422 if (options.bypassCSP) promises.push(this._client.send('Page.setBypassCSP', {423 enabled: true424 }));425 if (options.ignoreHTTPSErrors) promises.push(this._client.send('Security.setIgnoreCertificateErrors', {426 ignore: true427 }));428 if (this._isMainFrame()) promises.push(this._updateViewport());429 if (options.hasTouch) promises.push(this._client.send('Emulation.setTouchEmulationEnabled', {430 enabled: true431 }));432 if (options.javaScriptEnabled === false) promises.push(this._client.send('Emulation.setScriptExecutionDisabled', {433 value: true434 }));435 if (options.userAgent || options.locale) promises.push(this._client.send('Emulation.setUserAgentOverride', {436 userAgent: options.userAgent || '',437 acceptLanguage: options.locale438 }));439 if (options.locale) promises.push(emulateLocale(this._client, options.locale));440 if (options.timezoneId) promises.push(emulateTimezone(this._client, options.timezoneId));441 promises.push(this._updateGeolocation(true));442 promises.push(this._updateExtraHTTPHeaders(true));443 promises.push(this._updateRequestInterception());444 promises.push(this._updateOffline(true));445 promises.push(this._updateHttpCredentials(true));446 promises.push(this._updateEmulateMedia(true));447 for (const binding of this._crPage._page.allBindings()) promises.push(this._initBinding(binding));448 for (const source of this._crPage._browserContext._evaluateOnNewDocumentSources) promises.push(this._evaluateOnNewDocument(source, 'main'));449 for (const source of this._crPage._page._evaluateOnNewDocumentSources) promises.push(this._evaluateOnNewDocument(source, 'main'));450 if (screencastOptions) promises.push(this._startVideoRecording(screencastOptions));451 promises.push(this._client.send('Runtime.runIfWaitingForDebugger'));452 promises.push(this._firstNonInitialNavigationCommittedPromise);453 await Promise.all(promises);454 }455 dispose() {456 _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);457 this._networkManager.dispose();458 this._crPage._sessions.delete(this._targetId);459 }460 async _navigate(frame, url, referrer) {461 const response = await this._client.send('Page.navigate', {462 url,463 referrer,464 frameId: frame._id465 });466 if (response.errorText) throw new Error(`${response.errorText} at ${url}`);467 return {468 newDocumentId: response.loaderId469 };470 }471 _onLifecycleEvent(event) {472 if (this._eventBelongsToStaleFrame(event.frameId)) return;473 if (event.name === 'load') this._page._frameManager.frameLifecycleEvent(event.frameId, 'load');else if (event.name === 'DOMContentLoaded') this._page._frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded');474 }475 _onFrameStoppedLoading(frameId) {476 if (this._eventBelongsToStaleFrame(frameId)) return;477 this._page._frameManager.frameStoppedLoading(frameId);478 }479 _handleFrameTree(frameTree) {480 this._onFrameAttached(frameTree.frame.id, frameTree.frame.parentId || null);481 this._onFrameNavigated(frameTree.frame, true);482 if (!frameTree.childFrames) return;483 for (const child of frameTree.childFrames) this._handleFrameTree(child);484 }485 _eventBelongsToStaleFrame(frameId) {486 const frame = this._page._frameManager.frame(frameId); // Subtree may be already gone because some ancestor navigation destroyed the oopif.487 if (!frame) return true; // When frame goes remote, parent process may still send some events488 // related to the local frame before it sends frameDetached.489 // In this case, we already have a new session for this frame, so events490 // in the old session should be ignored.491 const session = this._crPage._sessionForFrame(frame);492 return session && session !== this && !session._swappedIn;493 }494 _onFrameAttached(frameId, parentFrameId) {495 const frameSession = this._crPage._sessions.get(frameId);496 if (frameSession && frameId !== this._targetId) {497 // This is a remote -> local frame transition.498 frameSession._swappedIn = true;499 const frame = this._page._frameManager.frame(frameId); // Frame or even a whole subtree may be already gone, because some ancestor did navigate.500 if (frame) this._page._frameManager.removeChildFramesRecursively(frame);501 return;502 }503 if (parentFrameId && !this._page._frameManager.frame(parentFrameId)) {504 // Parent frame may be gone already because some ancestor frame navigated and505 // destroyed the whole subtree of some oopif, while oopif's process is still sending us events.506 // Be careful to not confuse this with "main frame navigated cross-process" scenario507 // where parentFrameId is null.508 return;509 }510 this._page._frameManager.frameAttached(frameId, parentFrameId);511 }512 _onFrameNavigated(framePayload, initial) {513 if (this._eventBelongsToStaleFrame(framePayload.id)) return;514 this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url + (framePayload.urlFragment || ''), framePayload.name || '', framePayload.loaderId, initial);515 if (!initial) this._firstNonInitialNavigationCommittedFulfill();516 }517 _onFrameRequestedNavigation(payload) {518 if (this._eventBelongsToStaleFrame(payload.frameId)) return;519 if (payload.disposition === 'currentTab') this._page._frameManager.frameRequestedNavigation(payload.frameId);520 }521 _onFrameNavigatedWithinDocument(frameId, url) {522 if (this._eventBelongsToStaleFrame(frameId)) return;523 this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);524 }525 _onFrameDetached(frameId, reason) {526 if (this._crPage._sessions.has(frameId)) {527 // This is a local -> remote frame transtion, where528 // Page.frameDetached arrives after Target.attachedToTarget.529 // We've already handled the new target and frame reattach - nothing to do here.530 return;531 }532 if (reason === 'swap') {533 // This is a local -> remote frame transtion, where534 // Page.frameDetached arrives before Target.attachedToTarget.535 // We should keep the frame in the tree, and it will be used for the new target.536 const frame = this._page._frameManager.frame(frameId);537 if (frame) this._page._frameManager.removeChildFramesRecursively(frame);538 return;539 } // Just a regular frame detach.540 this._page._frameManager.frameDetached(frameId);541 }542 _onExecutionContextCreated(contextPayload) {543 const frame = contextPayload.auxData ? this._page._frameManager.frame(contextPayload.auxData.frameId) : null;544 if (!frame || this._eventBelongsToStaleFrame(frame._id)) return;545 const delegate = new _crExecutionContext.CRExecutionContext(this._client, contextPayload);546 let worldName = null;547 if (contextPayload.auxData && !!contextPayload.auxData.isDefault) worldName = 'main';else if (contextPayload.name === UTILITY_WORLD_NAME) worldName = 'utility';548 const context = new dom.FrameExecutionContext(delegate, frame, worldName);549 context[contextDelegateSymbol] = delegate;550 if (worldName) frame._contextCreated(worldName, context);551 this._contextIdToContext.set(contextPayload.id, context);552 }553 _onExecutionContextDestroyed(executionContextId) {554 const context = this._contextIdToContext.get(executionContextId);555 if (!context) return;556 this._contextIdToContext.delete(executionContextId);557 context.frame._contextDestroyed(context);558 }559 _onExecutionContextsCleared() {560 for (const contextId of Array.from(this._contextIdToContext.keys())) this._onExecutionContextDestroyed(contextId);561 }562 _onAttachedToTarget(event) {563 const session = _crConnection.CRConnection.fromSession(this._client).session(event.sessionId);564 if (event.targetInfo.type === 'iframe') {565 // Frame id equals target id.566 const targetId = event.targetInfo.targetId;567 const frame = this._page._frameManager.frame(targetId);568 if (!frame) return; // Subtree may be already gone due to renderer/browser race.569 this._page._frameManager.removeChildFramesRecursively(frame);570 const frameSession = new FrameSession(this._crPage, session, targetId, this);571 this._crPage._sessions.set(targetId, frameSession);572 frameSession._initialize(false).catch(e => e);573 return;574 }575 if (event.targetInfo.type !== 'worker') {576 // Ideally, detaching should resume any target, but there is a bug in the backend.577 session._sendMayFail('Runtime.runIfWaitingForDebugger').then(() => {578 this._client._sendMayFail('Target.detachFromTarget', {579 sessionId: event.sessionId580 });581 });582 return;583 }584 const url = event.targetInfo.url;585 const worker = new _page.Worker(this._page, url);586 this._page._addWorker(event.sessionId, worker);587 session.once('Runtime.executionContextCreated', async event => {588 worker._createExecutionContext(new _crExecutionContext.CRExecutionContext(session, event.context));589 }); // This might fail if the target is closed before we initialize.590 session._sendMayFail('Runtime.enable');591 session._sendMayFail('Network.enable');592 session._sendMayFail('Runtime.runIfWaitingForDebugger');593 session.on('Runtime.consoleAPICalled', event => {594 const args = event.args.map(o => worker._existingExecutionContext.createHandle(o));595 this._page._addConsoleMessage(event.type, args, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));596 });597 session.on('Runtime.exceptionThrown', exception => this._page.emit(_page.Page.Events.PageError, (0, _crProtocolHelper.exceptionToError)(exception.exceptionDetails))); // TODO: attribute workers to the right frame.598 this._networkManager.instrumentNetworkEvents(session, this._page._frameManager.frame(this._targetId));599 }600 _onDetachedFromTarget(event) {601 // This might be a worker...602 this._page._removeWorker(event.sessionId); // ... or an oopif.603 const childFrameSession = this._crPage._sessions.get(event.targetId);604 if (!childFrameSession) return; // Usually, we get frameAttached in this session first and mark child as swappedIn.605 if (childFrameSession._swappedIn) {606 childFrameSession.dispose();607 return;608 } // However, sometimes we get detachedFromTarget before frameAttached.609 // In this case we don't know wheter this is a remote frame detach,610 // or just a remote -> local transition. In the latter case, frameAttached611 // is already inflight, so let's make a safe roundtrip to ensure it arrives.612 this._client.send('Page.enable').catch(e => null).then(() => {613 // Child was not swapped in - that means frameAttached did not happen and614 // this is remote detach rather than remote -> local swap.615 if (!childFrameSession._swappedIn) this._page._frameManager.frameDetached(event.targetId);616 childFrameSession.dispose();617 });618 }619 _onWindowOpen(event) {620 this._crPage._nextWindowOpenPopupFeatures.push(event.windowFeatures);621 }622 async _onConsoleAPI(event) {623 if (event.executionContextId === 0) {624 // DevTools protocol stores the last 1000 console messages. These625 // messages are always reported even for removed execution contexts. In626 // this case, they are marked with executionContextId = 0 and are627 // reported upon enabling Runtime agent.628 //629 // Ignore these messages since:630 // - there's no execution context we can use to operate with message631 // arguments632 // - these messages are reported before Playwright clients can subscribe633 // to the 'console'634 // page event.635 //636 // @see https://github.com/GoogleChrome/puppeteer/issues/3865637 return;638 }639 const context = this._contextIdToContext.get(event.executionContextId);640 if (!context) return;641 const values = event.args.map(arg => context.createHandle(arg));642 this._page._addConsoleMessage(event.type, values, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));643 }644 async _initBinding(binding) {645 await Promise.all([this._client.send('Runtime.addBinding', {646 name: binding.name647 }), this._client.send('Page.addScriptToEvaluateOnNewDocument', {648 source: binding.source649 })]);650 }651 async _onBindingCalled(event) {652 const pageOrError = await this._crPage.pageOrError();653 if (!(pageOrError instanceof Error)) {654 const context = this._contextIdToContext.get(event.executionContextId);655 if (context) await this._page._onBindingCalled(event.payload, context);656 }657 }658 _onDialog(event) {659 if (!this._page._frameManager.frame(this._targetId)) return; // Our frame/subtree may be gone already.660 this._page.emit(_page.Page.Events.Dialog, new dialog.Dialog(this._page, event.type, event.message, async (accept, promptText) => {661 await this._client.send('Page.handleJavaScriptDialog', {662 accept,663 promptText664 });665 }, event.defaultPrompt));666 }667 _handleException(exceptionDetails) {668 this._page.firePageError((0, _crProtocolHelper.exceptionToError)(exceptionDetails));669 }670 async _onTargetCrashed() {671 this._client._markAsCrashed();672 this._page._didCrash();673 }674 _onLogEntryAdded(event) {675 const {676 level,677 text,678 args,679 source,680 url,681 lineNumber682 } = event.entry;683 if (args) args.map(arg => (0, _crProtocolHelper.releaseObject)(this._client, arg.objectId));684 if (source !== 'worker') {685 const location = {686 url: url || '',687 lineNumber: lineNumber || 0,688 columnNumber: 0689 };690 this._page._addConsoleMessage(level, [], location, text);691 }692 }693 async _onFileChooserOpened(event) {694 const frame = this._page._frameManager.frame(event.frameId);695 if (!frame) return;696 let handle;697 try {698 const utilityContext = await frame._utilityContext();699 handle = await this._adoptBackendNodeId(event.backendNodeId, utilityContext);700 } catch (e) {701 // During async processing, frame/context may go away. We should not throw.702 return;703 }704 await this._page._onFileChooserOpened(handle);705 }706 _willBeginDownload() {707 const originPage = this._crPage._initializedPage;708 if (!originPage) {709 // Resume the page creation with an error. The page will automatically close right710 // after the download begins.711 this._firstNonInitialNavigationCommittedReject(new Error('Starting new page download'));712 }713 }714 _onScreencastFrame(payload) {715 this._page.throttleScreencastFrameAck(() => {716 this._client.send('Page.screencastFrameAck', {717 sessionId: payload.sessionId718 }).catch(() => {});719 });720 const buffer = Buffer.from(payload.data, 'base64');721 this._page.emit(_page.Page.Events.ScreencastFrame, {722 buffer,723 timestamp: payload.metadata.timestamp,724 width: payload.metadata.deviceWidth,725 height: payload.metadata.deviceHeight726 });727 }728 async _createVideoRecorder(screencastId, options) {729 (0, _utils.assert)(!this._screencastId);730 const ffmpegPath = _registry.registry.findExecutable('ffmpeg').executablePathOrDie(this._page._browserContext._browser.options.sdkLanguage);731 this._videoRecorder = await _videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);732 this._screencastId = screencastId;733 }734 async _startVideoRecording(options) {735 const screencastId = this._screencastId;736 (0, _utils.assert)(screencastId);737 this._page.once(_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {}));738 const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));739 await this._startScreencast(this._videoRecorder, {740 format: 'jpeg',741 quality: 90,742 maxWidth: options.width,743 maxHeight: options.height744 }); // Wait for the first frame before reporting video to the client.745 gotFirstFrame.then(() => {746 this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage.pageOrError());747 });748 }749 async _stopVideoRecording() {750 if (!this._screencastId) return;751 const screencastId = this._screencastId;752 this._screencastId = null;753 const recorder = this._videoRecorder;754 this._videoRecorder = null;755 await this._stopScreencast(recorder);756 await recorder.stop().catch(() => {}); // Keep the video artifact in the map utntil encoding is fully finished, if the context757 // starts closing before the video is fully written to disk it will wait for it.758 const video = this._crPage._browserContext._browser._takeVideo(screencastId);759 video === null || video === void 0 ? void 0 : video.reportFinished();760 }761 async _startScreencast(client, options = {}) {762 this._screencastClients.add(client);763 if (this._screencastClients.size === 1) await this._client.send('Page.startScreencast', options);764 }765 async _stopScreencast(client) {766 this._screencastClients.delete(client);767 if (!this._screencastClients.size) await this._client._sendMayFail('Page.stopScreencast');768 }769 async _updateExtraHTTPHeaders(initial) {770 const headers = network.mergeHeaders([this._crPage._browserContext._options.extraHTTPHeaders, this._page._state.extraHTTPHeaders]);771 if (!initial || headers.length) await this._client.send('Network.setExtraHTTPHeaders', {772 headers: (0, _utils.headersArrayToObject)(headers, false773 /* lowerCase */774 )775 });776 }777 async _updateGeolocation(initial) {778 const geolocation = this._crPage._browserContext._options.geolocation;779 if (!initial || geolocation) await this._client.send('Emulation.setGeolocationOverride', geolocation || {});780 }781 async _updateOffline(initial) {782 const offline = !!this._crPage._browserContext._options.offline;783 if (!initial || offline) await this._networkManager.setOffline(offline);784 }785 async _updateHttpCredentials(initial) {786 const credentials = this._crPage._browserContext._options.httpCredentials || null;787 if (!initial || credentials) await this._networkManager.authenticate(credentials);788 }789 async _updateViewport() {790 if (this._crPage._browserContext._browser.isClank()) return;791 (0, _utils.assert)(this._isMainFrame());792 const options = this._crPage._browserContext._options;793 const emulatedSize = this._page._state.emulatedSize;794 if (emulatedSize === null) return;795 const viewportSize = emulatedSize.viewport;...
lp-app.js
Source:lp-app.js
1import { HP_HOST } from './config';2import { LitElement, html, css } from 'lit-element';3import { setPassiveTouchGestures } from '@polymer/polymer/lib/utils/settings';4import { menuIcon, Twitter, Facebook, Linkedin, Blogger, Github } from './lp-icons.js';5import './snack-bar.js';6import './search-imput-decorator';7import './speech-mic.js';8import './lp-home.js';9import { connect } from 'pwa-helpers/connect-mixin';10import { installRouter } from 'pwa-helpers/router';11import { installOfflineWatcher } from 'pwa-helpers/network';12import { installMediaQueryWatcher } from 'pwa-helpers/media-query';13import { updateMetadata, setMetaTag } from 'pwa-helpers/metadata';14import { store } from '../store.js';15import '@polymer/app-layout/app-drawer/app-drawer';16import '@polymer/app-layout/app-scroll-effects/effects/waterfall';17import '@polymer/app-layout/app-header/app-header';18import '@polymer/app-layout/app-toolbar/app-toolbar';19import {20 navigate,21 updateOffline,22 updateDrawerState,23 updateLayout,24 updateLocationURL,25} from '../actions/app';26import { Theme } from './style-theme';27import { MenuStyles } from './style-menu';28import { ButtonStyle } from './style-button';29import { SearchIcon } from './lp-icons';30class App extends connect(store)(LitElement) {31 static get styles() {32 return [33 Theme,34 MenuStyles,35 ButtonStyle,36 SearchIcon,37 css`38 /*--------------------------------------------------------------39 # Accessibility40 --------------------------------------------------------------*/41 /* Text meant only for screen readers. */42 .screen-reader-text {43 clip: rect(1px, 1px, 1px, 1px);44 position: absolute !important;45 height: 1px;46 width: 1px;47 overflow: hidden;48 word-wrap: normal !important;49 /* Many screen reader and browser combinations announce broken words as they would appear visually. */50 }51 .screen-reader-text:focus {52 background-color: #f1f1f1;53 border-radius: 3px;54 box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);55 clip: auto !important;56 color: #21759b;57 display: block;58 font-size: 14px;59 font-size: 0.875rem;60 font-weight: bold;61 height: auto;62 left: 5px;63 line-height: normal;64 padding: 15px 23px 14px;65 text-decoration: none;66 top: 5px;67 width: auto;68 z-index: 100000;69 /* Above WP toolbar. */70 }71 /* Do not show the outline on the skip link target. */72 #primary[tabindex='-1']:focus {73 outline: 0;74 }75 [hidden] {76 display: none !important;77 }78 app-header {79 position: fixed;80 top: 0;81 left: 0;82 z-index: 200;83 width: 100%;84 text-align: left;85 background-color: var(--app-header-background-color);86 color: var(--app-header-text-color);87 border-bottom: 1px solid var(--app-primary-border-color);88 }89 nav {90 height: 46px;91 }92 .masthead {93 background-color: var(--app-primary-background-color);94 padding: 12px 8px;95 height: inherit;96 align-items: center;97 }98 .title {99 margin-left: 0px;100 font-weight: 300;101 color: var(--app-secondary-color);102 }103 .paper-font-body2 {104 font-size: 14px;105 transform: uppercase;106 }107 .cta-header {108 background: var(--app-secondary-background-color);109 font-size: 1.2rem;110 margin-right: 24px;111 padding: 0px 10px 0px 10px;112 border: solid 1px var(--app-form-border-color);113 -webkit-border-radius: 10em;114 -moz-border-radius: 10em;115 border-radius: 10em;116 }117 .cta-header:focus-within {118 background-color: var(--app-reverse-text-color);119 -webkit-box-shadow: 0 0 5px rgba(28, 64, 26, 0.9);120 -moz-box-shadow: 0 0 5px rgba(28, 64, 26, 0.9);121 box-shadow: 0 0 5px rgba(28, 64, 26, 0.9);122 }123 .search-btn {124 background: var(--app-reverse-text-color);125 border: 1px solid var(--app-primary-icon-color);126 fill: var(--app-primary-icon-color);127 cursor: pointer;128 width: 34px;129 height: 33px;130 position: absolute;131 top: 24px;132 padding: 4px 5px 4px 5px;133 }134 .search-btn:hover {135 background: var(--app-primary-icon-color);136 fill: var(--app-reverse-text-color);137 }138 input[type='search'] {139 background: var(--app-secondary-background-color);140 padding: 8px 8px 8px 8px;141 width: 220px;142 margin-top: 14px;143 margin-bottom: 14px;144 border-top: 1px solid var(--app-form-border-color);145 border-right: 0px solid var(--app-form-border-color);146 border-left: 1px solid var(--app-form-border-color);147 border-bottom: 1px solid var(--app-form-border-color);148 }149 input[type='search']:focus {150 background-color: var(--app-reverse-text-color);151 }152 input:-moz-placeholder,153 input::-webkit-input-placeholder {154 color: var(--app-footer-secondary-background-color);155 }156 input:-moz-placeholder:focus,157 input::-webkit-input-placeholder:focus {158 color: var(--app-form-text-color);159 }160 .toolbar-top {161 background-color: var(--app-header-background-color);162 }163 [main-title] {164 font-family: 'Roboto';165 text-transform: lowercase;166 font-size: 24px;167 /* 168 In the narrow layout, the toolbar is offset by the width of the169 drawer button, and the text looks not centered. Add a padding to170 match that button 171 */172 padding-right: 44px;173 }174 .sub-tagline {175 margin-left: 5px;176 }177 .toolbar-list {178 display: none;179 }180 .toolbar-list > a {181 display: inline-block;182 color: var(--app-header-text-color);183 text-decoration: none;184 line-height: 30px;185 padding: 0px 18px;186 }187 .toolbar-list > a[selected] {188 color: var(--app-header-selected-color);189 border-bottom: 4px solid var(--app-header-selected-color);190 }191 /* 192 We need to make sure when drawer is open193 it covers our app header. Otherwise there's194 menu button that is disabled 195 */196 #drawer {197 z-index: 200;198 }199 #drawer app-toolbar {200 border-bottom: 1px solid var(--app-primary-border-color);201 margin-bottom: 5px;202 background-color: var(--app-primary-color);203 color: var(--app-reverse-text-color);204 }205 .drawer-list {206 box-sizing: border-box;207 width: 100%;208 height: 100%;209 padding: 10px 24px;210 background: var(--app-drawer-background-color);211 position: relative;212 text-align: left;213 overflow-y: auto;214 }215 .drawer-list > a {216 display: block;217 text-decoration: none;218 font: 400 16px/24px Roboto, sans-serif;219 color: var(--app-drawer-text-color);220 letter-spacing: 0.25px;221 padding: 0.6rem 8px 0.6rem 0px;222 }223 .drawer-list > a[selected] {224 color: var(--app-drawer-selected-color);225 }226 .main-content {227 padding-top: 20px;228 min-height: 100vh;229 }230 .page {231 display: none;232 }233 .page[active] {234 display: block;235 }236 .footer-linkboxes-all-backup,237 .footer-linkbox-cloud {238 background-color: var(--app-footer-primary-background-color);239 }240 .footer-linkboxes > nav::before {241 background: var(--app-footer-primary-background-color);242 border-bottom: solid 1px var(--app-form-border-color);243 color: var(--app-footer-primary-background-color);244 content: 'Logical Phase';245 display: block;246 height: 73px;247 padding: 24px;248 }249 *,250 *:before,251 *:after {252 -webkit-box-sizing: inherit;253 box-sizing: inherit;254 }255 .nav {256 font-size: 13px;257 }258 .site-name {259 display: none;260 }261 .utility-footer-nav {262 color: var(--app-reverse-text-color);263 overflow: auto;264 padding: 10px 24px;265 }266 .full-site-width,267 .toast-fill {268 margin: 0 auto;269 color: var(--app-footer-text-color);270 }271 .footer-linkboxes-all-backup,272 .footer-linkbox-cloud {273 background-color: var(--app-footer-primary-background-color);274 }275 .footer-linkboxes {276 background: #263238;277 font: 14px/16px Roboto, sans-serif;278 }279 .utility-footer {280 background: var(--app-footer-secondary-background-color);281 color: var(--app-footer-text-color);282 text-align: center;283 }284 .utility-footer-nav-left {285 display: inline-block;286 padding-right: 20px;287 }288 .utility-footer-nav-right {289 display: inline-block;290 }291 .utility-footer-link + .utility-footer-link::before {292 content: '|';293 padding-left: 6px;294 padding-right: 8px;295 }296 footer nav {297 height: inherit;298 }299 .utility-footer-link {300 color: var(--app-reverse-text-color);301 font-size: 14px;302 font-weight: 400;303 text-decoration: none;304 }305 .utility-footer-links,306 .utility-footer-newsletter-signup-text {307 font-weight: 500;308 margin-right: 16px;309 }310 .brand-site-logo {311 display: block;312 height: auto;313 width: 141px;314 text-align: left;315 margin-left: 12px;316 }317 img {318 border: 0;319 max-width: 100%;320 }321 /* 322 Wide layout: when the viewport width is bigger than 460px, layout323 changes to a wide layout. 324 */325 @media (min-width: 460px) {326 #dropdownMenuButton {327 margin-right: 3px;328 padding-top: 13px;329 }330 .toolbar-list {331 display: block;332 }333 .cta-header {334 background: var(--app-secondary-background-color);335 font-size: 1.1rem;336 margin-right: 24px;337 border: solid 1px var(--app-form-border-color);338 -webkit-border-radius: 4px;339 -moz-border-radius: 4px;340 border-radius: 4px;341 }342 .cta-header:focus-within {343 border: none;344 }345 .small-print .social-icon {346 padding-left: 0px;347 }348 .get-social {349 font-size: 16px;350 font-weight: 400;351 }352 a.social-icon {353 margin-right: 0px;354 margin-left: 8px;355 }356 .social-icon svg {357 border:1px solid var(--app-primary-text-thin-color);358 border-radius: 5px;359 padding: 3px;360 margin-top: 8px;361 }362 .social-icon {363 fill: var(--app-primary-text-thin-color);364 padding-left: 0;365 cursor: pointer;366 }367 .gplus-icon:hover {368 fill: #db4437;369 }370 .blogger-icon:hover {371 fill: #fb8f3d;372 }373 .twitter-icon:hover {374 fill: #1da1f2;375 }376 .facebook-icon:hover {377 fill: #3b5998;378 }379 .linkedin-icon:hover {380 fill: #007bb5;381 }382 input[type='search']::placeholder {383 font-size: 14px;384 }385 input[type='search'] {386 background: var(--app-secondary-background-color);387 width: 170px;388 font-size: 1rem;389 padding: 0px 0px 0px 8px;390 margin-top: 0px;391 margin-bottom: 0px;392 border: none;393 -webkit-transition: all 0.5s;394 -moz-transition: all 0.5s;395 transition: all 0.5s;396 }397 input[type='search']:focus {398 width: 380px;399 background-color: var(--app-reverse-text-color);400 }401 lp-input-decorator {402 max-width: 460px;403 transform: translate3d(0, 0, 0);404 }405 lp-input-decorator[top] {406 transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);407 transform: translate3d(0, 0, 0);408 }409 .masthead {410 padding: 5px 8px 5px 36px;411 }412 .brand-site-logo {413 display: block;414 height: auto;415 width: 168px;416 margin-left: 0px;417 }418 .menu-btn {419 display: none;420 }421 .toolbar-list > a {422 padding: 0px 18px;423 }424 ul.nav-right {425 width: 50%;426 }427 .main-content {428 padding-top: 55px;429 }430 nav.full-site-width {431 background-color: #212121 !important;432 }433 .utility-footer-nav-left {434 float: left;435 }436 .utility-footer-nav-right {437 float: right;438 }439 .footer-linkboxes > nav::before {440 background-color: var(--app-footer-primary-background-color) !important;441 color: var(--app-secondary-background-color);442 content: 'Logical Phase';443 display: block;444 min-height: 73px;445 padding: 24px;446 }447 /* The drawer button isn't shown in the wide layout, so we don't448 need to offset the title */449 [main-title] {450 padding-right: 0px;451 }452 html[dir='rtl'] .microphone-icon {453 left: 0;454 right: auto;455 }456 #realbox-input-wrapper > :-webkit-any(.google-g-icon, .microphone-icon, .search-icon) {457 z-index: 3;458 }459 }460 `,461 ];462 }463 render() {464 const {465 _page,466 _offline,467 _drawerOpened,468 _snackbarOpened,469 _searchTerms,470 } = this;471 const hideInput = !_page;472 // True to make the search input aligns at the top inside the header instead of inside the main content.473 const inputAtTop = 'ontouchstart' in window || !_page;474 const searchTerms = _page ? '' : _searchTerms;475 const appTitle = "Digital Experience Solutions by Logical Phase";476 const appShortTitle = "Logical Phase";477 updateMetadata({478 title: `Digital Experience Solutions by Logical Phase`,479 description: `Combining powerful cloud technologies that keep you ahead of the competition`,480 image: `https://storage.googleapis.com/logicalphase.com/assets/9a6ed0c3-bg-homepage-container.jpg`,481 });482 setMetaTag('name', 'twitter:card', 'photo');483 setMetaTag('name', 'twitter:url', 'https://logicalphase.com/');484 return html`485 <!-- Header -->486 <header class="header-wrapper">487 <app-header-layout id="appheaderlayout" has-scrolling-region>488 <app-header slot="header" condenses reveals effects="waterfall">489 <app-toolbar class="masthead">490 <a href="/">491 <img492 rel="dns-prefetch"493 class="brand-site-logo"494 src="/images/logicalphase-logo-204x36.svg"495 alt="${appTitle} logo"496 />497 </a>498 <div class="title" main-title>499 <span class="site-name">${appTitle}</span>500 </div>501 <div class="cta-header toolbar-list">502 <lp-input-decorator ?top="${inputAtTop}" ?hidden="${hideInput}">503 <input504 slot="input"505 id="input"506 aria-label="Search Content"507 type="search"508 placeholder="Enter search term"509 value="${decodeURI(searchTerms)}"510 @change="${e => store.dispatch(updateLocationURL(`/search/${e.target.value}`))}"511 />512 <speech-mic513 slot="button"514 continuous515 interimResults516 @result="${e => this._micResult(e)}"517 ></speech-mic>518 </lp-input-decorator>519 </div>520 <button521 class="menu-btn"522 title="Menu"523 @click="${() => store.dispatch(updateDrawerState(true))}"524 >525 ${menuIcon}526 </button>527 </app-toolbar>528 <app-toolbar class="desktop-menu toolbar-list" sticky>529 <nav role="navigation" aria-label="Header Navigation Menu">530 <div class="main-navigation">531 <a ?selected="${_page === 'home'}" href="/">Home</a>532 <a ?selected="${_page === 'about'}" href="/about">About</a>533 <button534 id="dropdownMenuButton"535 class="toolbar-platform-chooser__button"536 role="menu"537 aria-haspopup="true"538 aria-owns="dropdownListElement"539 aria-controls="dropdownListElement"540 @click="${this._toggleDropdownMenu}"541 >542 <span class="toolbar-platform-chooser__label">Solutions</span>543 <svg544 class="triangle dropdown__arrow closed"545 width="24"546 height="24"547 viewBox="0 0 24 24"548 fill="none"549 >550 <title>Open drop down menu</title>551 <path d="M7 10l5 5 5-5z"></path>552 </svg>553 </button>554 <a ?selected="${_page === 'blog'}" href="/blog">Blog</a>555 <a ?selected="${_page === 'contact'}" href="/contact">Contact</a>556 <div class="slide-icons slide-left login-nav-item">557 <span class="get-social">Get social</span>558 <a559 class="social-icon twitter-icon"560 href="https://twitter.com/logicalphase/"561 >${Twitter}</a562 >563 <a564 class="social-icon linkedin-icon"565 href="https://www.linkedin.com/in/john-t-teague/"566 >${Linkedin}</a567 >568 <a569 class="social-icon github-icon"570 href="https://github.com/logicalphase"571 >${Github}</a572 >573 </div>574 </div>575 <div576 id="dropdownListElement"577 class="main-navigation dropdown-menu hide"578 data-target="slide-content"579 role="group"580 aria-labelledby="dropdownMenuButton"581 aria-hidden="true"582 >583 <a584 class="dropdown-item submenu"585 ?selected="${_page === 'pagespeed'}"586 href="/pagespeed"587 role="menuitem"588 >Site Performance</a589 >590 <a591 class="dropdown-item submenu"592 ?selected="${_page === 'security'}"593 href="/security"594 role="menuitem"595 >Security Services</a596 >597 <a class="submenu" 598 ?selected="${_page === 'hosting'}" 599 href="/hosting"600 role="menuitem"601 >GCP Hosting Solutions</a602 >603 <a 604 class="submenu" 605 ?selected="${_page === 'design'}" 606 href="/design"607 role="menuitem"608 >Progressive Web Apps</a609 >610 <a611 class="dropdown-item submenu"612 ?selected="${_page === 'migration'}"613 href="/migration"614 role="menuitem"615 >Site Migrations</a616 >617 </div>618 </nav>619 </app-toolbar>620 </app-header>621 </app-header-layout>622 </header>623 <!-- Drawer content -->624 <app-drawer625 id="drawer"626 .opened="${_drawerOpened}"627 @opened-changed="${e => store.dispatch(updateDrawerState(e.target.opened))}"628 swipe-open629 >630 <app-toolbar>631 ${appShortTitle}632 </app-toolbar>633 <nav class="drawer-list">634 <div class="search-wrapper">635 <form636 class="header-search-drawer"637 name="toolbar-search-drawer"638 action="/search/wordpress"639 >640 <input641 class="search-field-drawer"642 type="search"643 aria-label="Search box"644 placeholder="Search..."645 value="" 646 tabindex="-1"647 />648 <button649 class="search-btn"650 title="Search"651 @click="${() => this._getValueFromSearchFieldDrawer()}"652 tabindex="-1"653 >654 ${SearchIcon}655 </button>656 </form>657 </div>658 <a ?selected="${_page === 'home'}" href="/">Home</a>659 <a ?selected="${_page === 'about'}" href="/about">About</a>660 <a class="submenu" ?selected="${_page === 'pagespeed'}" href="/pagespeed">Site Performance</a>661 <a class="submenu" ?selected="${_page === 'security'}" href="/security">Security Services</a>662 <a class="submenu" ?selected="${_page === 'hosting'}" href="/hosting">Cloud Hosting</a>663 <a class="submenu" ?selected="${_page === 'design'}" href="/design">Progressive Web Apps</a>664 <a class="submenu" ?selected="${_page === 'migration'}" href="/migration">Site Migrations</a>665 <a ?selected="${_page === 'blog'}" href="/blog">Logical Blog</a>666 <a ?selected="${_page === 'contact'}" href="/contact">Contact Us</a>667 <a ?selected="${_page === 'support'}" href="/support">Client Support</a>668 <a ?selected="${_page === 'privacy'}" href="/privacy">Privacy</a>669 <a ?selected="${_page === 'terms'}" href="/terms">Terms of Service</a>670 </nav>671 </app-drawer>672 <!-- Main content -->673 <main class="main-content">674 <lp-home class="page" ?active="${_page === 'home'}"></lp-home>675 <lp-article class="page" ?active="${_page === 'article'}"></lp-article>676 <lp-about class="page" ?active="${_page === 'about'}"></lp-about>677 <lp-blog class="page" ?active="${_page === 'blog'}"></lp-blog>678 <lp-contact class="page" ?active="${_page === 'contact'}"></lp-contact>679 <lp-category class="page" ?active="${_page === 'category'}"></lp-category>680 <lp-design class="page" ?active="${_page === 'design'}"></lp-design>681 <lp-hosting class="page" ?active="${_page === 'hosting'}"></lp-hosting>682 <lp-migration class="page" ?active="${_page === 'migration'}"></lp-migration>683 <lp-pagespeed class="page" ?active="${_page === 'pagespeed'}"></lp-pagespeed>684 <lp-privacy class="page" ?active="${_page === 'privacy'}"></lp-privacy>685 <lp-search class="page" ?active="${_page === 'search'}"></lp-search>686 <lp-security class="page" ?active="${_page === 'security'}"></lp-security>687 <lp-support class="page" ?active="${_page === 'support'}"></lp-support>688 <lp-terms class="page" ?active="${_page === 'terms'}"></lp-terms>689 <lp-view404 class="page" ?active="${_page === '404'}"></lp-view404>690 </main>691 <!-- Footer content -->692 <footer title="footer-links" class="footer-linkboxes nocontent footer-linkboxes-all-backup">693 <nav aria-label="footer" class="full-site-width"></nav>694 <div title="footer-navigation" class="utility-footer">695 <nav aria-label="policy" class="utility-footer-nav nav full-site-width">696 <div class="utility-footer-nav-left">697 <span class="footer-links">698 <a class="utility-footer-link gc-analytics-event" href="/terms">Site Terms</a>699 <a class="utility-footer-link gc-analytics-event" href="/privacy">Privacy</a>700 </span>701 </div>702 <div class="utility-footer-nav-right">703 <span class="footer-links">704 <span class="utility-footer-link gc-analytics-event">Copyright © 2019 Logical Phase. All Rights Reserved</span>705 </span>706 </div>707 </nav>708 </div>709 </footer>710 <snack-bar ?active="${_snackbarOpened}">711 You are currently ${_offline ? 'offline' : 'online'}.</snack-bar712 >713 `;714 }715 static get properties() {716 return {717 appTitle: {718 type: String,719 },720 appShortTitle: {721 type: String,722 },723 _query: {724 type: String,725 },726 _categoryId: {727 type: String,728 },729 _page: {730 type: String,731 },732 _lazyResourcesLoaded: {733 type: Boolean,734 },735 _lastVisitedListPage: {736 type: Boolean,737 },738 _offline: {739 type: Boolean,740 },741 _drawerOpened: {742 type: Boolean,743 },744 _snackbarOpened: {745 type: Boolean,746 },747 _updateOffline: {748 type: Boolean,749 },750 _data: {751 type: Object,752 },753 _item: {754 type: Object,755 },756 _articleSlug: {757 type: String,758 },759 dropdownList: {760 type: String,761 },762 searchFieldValue: {763 type: String,764 },765 searchTerms: {766 type: Object,767 },768 _searchAction: {769 type: Object,770 },771 };772 }773 constructor() {774 super();775 // To force all event listeners for gestures to be passive.776 // See https://www.polymer-project.org/3.0/docs/devguide/settings#setting-passive-touch-gestures777 setPassiveTouchGestures(true);778 }779 firstUpdated() {780 installRouter(location => store.dispatch(navigate(location)));781 installOfflineWatcher(offline => store.dispatch(updateOffline(offline)));782 installMediaQueryWatcher(`(min-width: 648px) and (min-height: 648px)`, matches =>783 store.dispatch(updateLayout(matches)),784 );785 this.removeAttribute('unresolved');786 this._input = this.shadowRoot.getElementById('input');787 }788 updated(changedProps) {789 if (changedProps.has('_page')) {790 const pageTitle = this.appTitle + ' - ' + this._page;791 updateMetadata({792 title: pageTitle,793 description: pageTitle,794 // This object also takes an image property, that points to an img src.795 });796 // Maybe move this into a store, but for now I need a quick and dirty way797 // to make sure the dropdown menu element closes after a menu selection798 // and to properly update aria attributes.799 this._hideDropdownButtonBlur();800 window.scrollTo(0, 0);801 }802 }803 _toggleDropdownMenu(e) {804 const dropdownButton = this.shadowRoot.getElementById('dropdownMenuButton');805 const dropdownList = this.shadowRoot.getElementById('dropdownListElement');806 const dropdownArrow = this.shadowRoot.querySelector('.dropdown__arrow');807 if (dropdownList.classList.contains('hide')) {808 dropdownList.classList.replace('hide', 'show');809 dropdownArrow.classList.replace('closed', 'open');810 dropdownButton.setAttribute('aria-expanded', 'true');811 dropdownList.setAttribute('aria-hidden', 'false');812 console.log(dropdownList.classList);813 } else {814 dropdownList.classList.replace('show', 'hide');815 dropdownArrow.classList.replace('open', 'closed');816 dropdownButton.setAttribute('aria-expanded', 'false');817 dropdownList.setAttribute('aria-hidden', 'true');818 console.log(dropdownList.classList);819 }820 }821 _hideDropdownButtonBlur(e) {822 const dropdownButton = this.shadowRoot.getElementById('dropdownMenuButton');823 const dropdownList = this.shadowRoot.getElementById('dropdownListElement');824 const dropdownArrow = this.shadowRoot.querySelector('.dropdown__arrow');825 dropdownList.classList.replace('show', 'hide');826 dropdownArrow.classList.replace('open', 'closed');827 dropdownButton.setAttribute('aria-expanded', 'false');828 dropdownList.setAttribute('aria-hidden', 'true');829 }830 // To get our drawer search to work we need to get the value of the search field831 // and set the action attribute of our form action. We should add a condition832 // so if the search form is empty, return a message we need an actual search term.833 _getValueFromSearchFieldDrawer(e) {834 const searchTermsDrawer = this.shadowRoot.querySelector('.search-field-drawer').value;835 const searchActionDrawer = (this.shadowRoot.querySelector('.header-search-drawer').action =836 '/search/' + searchTermsDrawer);837 }838 stateChanged(state) {839 this.appTitle = state.app.appTitle;840 this._page = state.app.page;841 this._lastVisitedListPage = state.app.lastVisitedListPage;842 this._offline = state.app.offline;843 this._snackbarOpened = state.app.snackbarOpened;844 this._drawerOpened = state.app.drawerOpened;845 this._data = state.article && state.article.data;846 this._item = state.article && state.article.item;847 this._query = state.articles && state.articles.query;848 this._categoryId = state.categories && state.categories.categoryId;849 this._articleSlug = state.article && state.article.slug;850 this._searchTerms = state.search_results && state.search_results.searchTerms;851 this._searchAction = state.search_results && state.search_results._searchAction;852 }853 _micResult(e) {854 const d = e.detail;855 const value = d.completeTranscript;856 this._input.value = value;857 if (d.isFinal) {858 store.dispatch(updateLocationURL(`/search/${value}`));859 }860 }861}...
PresenceStore.js
Source:PresenceStore.js
...33 user.lastEventTimestamp = eventTimestamp;34 if (status === 'on') {35 _updateOnline(user);36 } else {37 _updateOffline(user);38 }39}40function _updateOnline(user) {41 user.status = 'on';42 clearTimeout(user.timeoutId); // In case a setTimeout is running43 user.timeoutId = null;44}45function _updateOffline(user) {46 if (user.status !== 'on' || user.timeoutId) return;47 user.timeoutId = setTimeout(function() { // To prevent blinking on auto-reconnection48 delete _state.users[user.userId];49 PresenceStore.emitEvent(); // TODO: Couldn't find a better way50 }, 5000);51}52var PresenceStore = assign({}, EventEmitter.prototype, {53 emitEvent: function() {54 this.emit(CHANGE_EVENT);55 },56 addChangeListener: function(callback) {57 this.on(CHANGE_EVENT, callback);58 },59 removeChangeListener: function(callback) {...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({ headless: false });4 const context = await browser.newContext();5 const page = await context.newPage();6 await page._updateOffline(true);7 await page.reload();8 await page.screenshot({ path: 'test.png' });9 await browser.close();10})();11const { chromium } = require('playwright');12(async () => {13 const browser = await chromium.launch({ headless: false });14 const context = await browser.newContext();15 const page = await context.newPage();16 await page._updateOffline(true);17 await page.reload();18 await page.screenshot({ path: 'test.png' });19 await browser.close();20})();21const { chromium } = require('playwright');22(async () => {23 const browser = await chromium.launch({ headless: false });24 const context = await browser.newContext();25 const page = await context.newPage();26 await page._updateOffline(true);27 await page.reload();28 await page.screenshot({ path: 'test.png' });29 await browser.close();30})();31const { chromium } = require('playwright');32(async () => {33 const browser = await chromium.launch({ headless: false });34 const context = await browser.newContext();35 const page = await context.newPage();36 await page._updateOffline(true);37 await page.reload();38 await page.screenshot({ path: 'test.png' });39 await browser.close();40})();41const { chromium } = require('playwright');
Using AI Code Generation
1const { chromium } = require('playwright');2const fs = require('fs');3(async () => {4 const browser = await chromium.launch({headless: false});5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.evaluate(() => {8 const offline = true;9 const updateOffline = window.__playwright__._updateOffline;10 updateOffline(offline);11 });12 await page.screenshot({path: 'offline.png'});13 await browser.close();14})();
Using AI Code Generation
1const playwright = require('playwright');2const path = require('path');3const fs = require('fs');4(async () => {5 for (const browserType of ['chromium']) {6 const browser = await playwright[browserType].launch();7 const context = await browser.newContext();8 const page = await context.newPage();9 const offlinePath = path.join(__dirname, 'offline.html');10 const offlineContent = fs.readFileSync(offlinePath, 'utf8');11 await page._updateOffline(offlineContent);12 await page.screenshot({ path: `example-${browserType}.png` });13 await browser.close();14 }15})();
Using AI Code Generation
1const { _updateOffline } = require('playwright/lib/server/browserType');2_updateOffline(false);3const { _updateOffline } = require('playwright/lib/server/browserType');4_updateOffline(false);5const { _updateOffline } = require('playwright/lib/server/browserType');6_updateOffline(false);7const { _updateOffline } = require('playwright/lib/server/browserType');8_updateOffline(false);9const { _updateOffline } = require('playwright/lib/server/browserType');10_updateOffline(false);11const { _updateOffline } = require('playwright/lib/server/browserType');12_updateOffline(false);13const { _updateOffline } = require('playwright/lib/server/browserType');14_updateOffline(false);15const { _updateOffline } = require('playwright/lib/server/browserType');16_updateOffline(false);17const { _updateOffline } = require('playwright/lib/server/browserType');18_updateOffline(false);19const { _updateOffline } = require('playwright/lib/server/browserType');20_updateOffline(false);21const { _updateOffline } = require('playwright/lib/server/browserType');22_updateOffline(false);23const { _updateOffline } = require('playwright/lib/server/browserType');24_updateOffline(false);25const { _updateOffline } = require('playwright/lib/server/browserType');26_updateOffline(false);27const { _updateOffline } = require('playwright/lib/server/browserType');28_updateOffline(false);29const { _updateOffline } = require('playwright/lib/server/browserType');30_updateOffline(false);
Using AI Code Generation
1const { _updateOffline } = require('playwright-core/lib/server/browserContext');2const { chromium } = require('playwright-core');3const context = await chromium.launch().newContext();4await _updateOffline(context, false);5await context.close();6const { _updateOffline } = require('playwright-core/lib/server/browserContext');7const { chromium } = require('playwright-core');8const context = await chromium.launch().newContext();9await _updateOffline(context, false);10await context.close();11const { _updateOffline } = require('playwright-core/lib/server/browserContext');12const { chromium } = require('playwright-core');13const context = await chromium.launch().newContext();14await _updateOffline(context, false);15await context.close();
Using AI Code Generation
1const { Playwright } = require('playwright');2const { BrowserType } = require('playwright/types/types');3const { BrowserContext } = require('playwright/types/types');4const { Browser } = require('playwright/types/types');5const { Page } = require('playwright/types/types');6const { BrowserContextOptions } = require('playwright/types/types');7const { LaunchOptions } = require('playwright/types/types');8const { ChromiumBrowser } = require('playwright/types/types');9const { ChromiumBrowserContext } = require('playwright/types/types');10const { ChromiumPage } = require('playwright/types/types');11const browserType = Playwright['chromium'];12const browser = browserType['launch']({headless: false});13const context = browser['newContext']();14const page = context['newPage']();15const chromiumBrowser = browser;16const chromiumBrowserContext = context;17const chromiumPage = page;18chromiumBrowserContext['_updateOffline'](true);19chromiumPage['_updateOffline'](true);20const chromiumBrowser = browser;21const chromiumBrowserContext = context;22const chromiumPage = page;23chromiumBrowserContext['_updateOffline'](false);24chromiumPage['_updateOffline'](false);25const chromiumBrowser = browser;26const chromiumBrowserContext = context;27const chromiumPage = page;28chromiumBrowserContext['_updateOffline'](true);29chromiumPage['_updateOffline'](true);30chromiumPage['_updateOffline'](false);31const chromiumBrowser = browser;32const chromiumBrowserContext = context;33const chromiumPage = page;34chromiumBrowserContext['_updateOffline'](false);35chromiumPage['_updateOffline'](false);36chromiumPage['_updateOffline'](true);37const chromiumBrowser = browser;38const chromiumBrowserContext = context;39const chromiumPage = page;40chromiumBrowserContext['_updateOffline'](true);41chromiumPage['_updateOffline'](true);42chromiumPage['_updateOffline'](false);43const chromiumBrowser = browser;44const chromiumBrowserContext = context;45const chromiumPage = page;
Using AI Code Generation
1const { Playwright } = require('playwright');2const playwright = new Playwright();3const browser = playwright.chromium.launch();4const context = browser.newContext();5const page = context.newPage();6await page._updateOffline(true);7await page._updateOffline(false);8await page.close();9await context.close();10await browser.close();11await playwright.stop();
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!