this doesn't work for me SESSION_STORAGE: - postgresql
I am trying to create a new session to have the session in a database, Postgres. I am trying to use this code, but nothing works, and it is frustrating.
I'm almost sure that I need to send a second argument, but I don't know what it will be!.
my code:
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.April22,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.PostgreSQLSessionStorage(
new URL(process.env.DATABASE_URL)
),
});
error:
┃ file:///Users/blablabla/Documents/Apps/cli_shopify_mayo2022/cli-19may/server/middleware/verify-request.js:25
┃ if (session?.isActive()) {
┃ ^
┃
┃ TypeError: session?.isActive is not a function
┃ at file:///Users/diegotorres/Documents/Apps/cli_shopify_mayo2022/cli-19may/server/middleware/verify-request.js:25:18
┃ at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
┃
┃ Node.js v18.0.0
┃ [nodemon] app crashed - waiting for file changes before starting...
postgres file
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostgreSQLSessionStorage = void 0;
var tslib_1 = require("tslib");
var pg_1 = tslib_1.__importDefault(require("pg"));
var session_utils_1 = require("../session-utils");
var defaultPostgreSQLSessionStorageOptions = {
sessionTableName: 'shopify_sessions',
port: 3211,
};
var PostgreSQLSessionStorage = /** #class */ (function () {
function PostgreSQLSessionStorage(dbUrl, opts) {
if (opts === void 0) { opts = {}; }
this.dbUrl = dbUrl;
if (typeof this.dbUrl === 'string') {
this.dbUrl = new URL(this.dbUrl);
}
this.options = tslib_1.__assign(tslib_1.__assign({}, defaultPostgreSQLSessionStorageOptions), opts);
this.ready = this.init();
}
PostgreSQLSessionStorage.withCredentials = function (host, dbName, username, password, opts) {
return new PostgreSQLSessionStorage(new URL("postgres://".concat(encodeURIComponent(username), ":").concat(encodeURIComponent(password), "#").concat(host, "/").concat(encodeURIComponent(dbName))), opts);
};
PostgreSQLSessionStorage.prototype.storeSession = function (session) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var entries, query;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.ready];
case 1:
_a.sent();
entries = (0, session_utils_1.sessionEntries)(session);
query = "\n INSERT INTO ".concat(this.options.sessionTableName, "\n (").concat(entries.map(function (_a) {
var _b = tslib_1.__read(_a, 1), key = _b[0];
return key;
}).join(', '), ")\n VALUES (").concat(entries.map(function (_, i) { return "$".concat(i + 1); }).join(', '), ")\n ON CONFLICT (id) DO UPDATE SET ").concat(entries
.map(function (_a) {
var _b = tslib_1.__read(_a, 1), key = _b[0];
return "".concat(key, " = Excluded.").concat(key);
})
.join(', '), ";\n ");
return [4 /*yield*/, this.query(query, entries.map(function (_a) {
var _b = tslib_1.__read(_a, 2), _key = _b[0], value = _b[1];
return value;
}))];
case 2:
_a.sent();
return [2 /*return*/, true];
}
});
});
};
PostgreSQLSessionStorage.prototype.loadSession = function (id) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var query, rows, rawResult;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.ready];
case 1:
_a.sent();
query = "\n SELECT * FROM ".concat(this.options.sessionTableName, "\n WHERE id = $1;\n ");
return [4 /*yield*/, this.query(query, [id])];
case 2:
rows = _a.sent();
if (!Array.isArray(rows) || (rows === null || rows === void 0 ? void 0 : rows.length) !== 1)
return [2 /*return*/, undefined];
rawResult = rows[0];
return [2 /*return*/, (0, session_utils_1.sessionFromEntries)(Object.entries(rawResult))];
}
});
});
};
PostgreSQLSessionStorage.prototype.deleteSession = function (id) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var query;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.ready];
case 1:
_a.sent();
query = "\n DELETE FROM ".concat(this.options.sessionTableName, "\n WHERE id = $1;\n ");
return [4 /*yield*/, this.query(query, [id])];
case 2:
_a.sent();
return [2 /*return*/, true];
}
});
});
};
PostgreSQLSessionStorage.prototype.disconnect = function () {
return this.client.end();
};
PostgreSQLSessionStorage.prototype.init = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.client = new pg_1.default.Client({ connectionString: this.dbUrl.toString() });
return [4 /*yield*/, this.connectClient()];
case 1:
_a.sent();
return [4 /*yield*/, this.createTable()];
case 2:
_a.sent();
return [2 /*return*/];
}
});
});
};
PostgreSQLSessionStorage.prototype.connectClient = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.client.connect()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
PostgreSQLSessionStorage.prototype.hasSessionTable = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var query, _a, rows;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
query = "\n SELECT * FROM pg_catalog.pg_tables WHERE tablename = $1\n ";
return [4 /*yield*/, this.query(query, [this.options.sessionTableName])];
case 1:
_a = tslib_1.__read.apply(void 0, [_b.sent(), 1]), rows = _a[0];
return [2 /*return*/, Array.isArray(rows) && rows.length === 1];
}
});
});
};
PostgreSQLSessionStorage.prototype.createTable = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var hasSessionTable, query;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.hasSessionTable()];
case 1:
hasSessionTable = _a.sent();
if (!!hasSessionTable) return [3 /*break*/, 3];
query = "\n CREATE TABLE ".concat(this.options.sessionTableName, " (\n id varchar(255) NOT NULL PRIMARY KEY,\n shop varchar(255) NOT NULL,\n state varchar(255) NOT NULL,\n isOnline boolean NOT NULL,\n scope varchar(255),\n accessToken varchar(255)\n )\n ");
return [4 /*yield*/, this.query(query)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
};
PostgreSQLSessionStorage.prototype.query = function (sql, params) {
if (params === void 0) { params = []; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.client.query(sql, params)];
case 1:
result = _a.sent();
return [2 /*return*/, result.rows];
}
});
});
};
return PostgreSQLSessionStorage;
}());
exports.PostgreSQLSessionStorage = PostgreSQLSessionStorage;
so, investigating a bit I found the following file which is where the app breaks
import { Shopify } from "#shopify/shopify-api";
const TEST_GRAPHQL_QUERY = `
{
shop {
name
}
}`;
export default function verifyRequest(app, { returnHeader = true } = {}) {
return async (req, res, next) => {
const session = await Shopify.Utils.loadCurrentSession(
req,
res,
app.get("use-online-tokens")
);
let shop = req.query.shop;
if (session && shop && session.shop !== shop) {
// The current request is for a different shop. Redirect gracefully.
return res.redirect(`/auth?shop=${shop}`);
}
if (session?.isActive()) {
try {
// make a request to make sure oauth has succeeded, retry otherwise
const client = new Shopify.Clients.Graphql(
session.shop,
session.accessToken
);
await client.query({ data: TEST_GRAPHQL_QUERY });
return next();
} catch (e) {
if (
e instanceof Shopify.Errors.HttpResponseError &&
e.response.code === 401
) {
// We only want to catch 401s here, anything else should bubble up
} else {
throw e;
}
}
}
if (returnHeader) {
if (!shop) {
if (session) {
shop = session.shop;
} else if (Shopify.Context.IS_EMBEDDED_APP) {
const authHeader = req.headers.authorization;
const matches = authHeader?.match(/Bearer (.*)/);
if (matches) {
const payload = Shopify.Utils.decodeSessionToken(matches[1]);
shop = payload.dest.replace("https://", "");
}
}
}
if (!shop || shop === "") {
return res
.status(400)
.send(
`Could not find a shop to authenticate with. Make sure you are making your XHR request with App Bridge's authenticatedFetch method.`
);
}
res.status(403);
res.header("X-Shopify-API-Request-Failure-Reauthorize", "1");
res.header(
"X-Shopify-API-Request-Failure-Reauthorize-Url",
`/auth?shop=${shop}`
);
res.end();
} else {
res.redirect(`/auth?shop=${shop}`);
}
};
}
You should use cloneSession from Session
Here is full code from my working project and custom implimentation of postgresql session
// tslint:disable-next-line:no-submodule-imports
import { Session } from '#shopify/shopify-api/dist/auth/session/index.js';
import pg from 'pg';
// tslint:disable-next-line:interface-name
interface SessionInterface {
readonly id: string;
shop: string;
state: string;
isOnline: boolean;
scope?: string;
expires?: Date;
accessToken?: string;
onlineAccessInfo?: any;
isActive(): boolean;
}
// tslint:disable-next-line:interface-name
interface SessionStorage {
/**
* Creates or updates the given session in storage.
*
* #param session Session to store
*/
storeSession(session: SessionInterface): Promise<boolean>;
/**
* Loads a session from storage.
*
* #param id Id of the session to load
*/
loadSession(id: string): Promise<SessionInterface | undefined>;
/**
* Deletes a session from storage.
*
* #param id Id of the session to delete
*/
deleteSession(id: string): Promise<boolean>;
}
function fromEntries<T>(entries: Array<[keyof T, T[keyof T]]>): T {
return entries.reduce(
(acc, [key, value]) => ({ ...acc, [key]: value }),
<T>{}
);
}
function sessionFromEntries(
entries: Array<[string, string | number]>,
): SessionInterface {
const obj = fromEntries(
entries
// tslint:disable-next-line:variable-name
.filter(([_key, value]) => value !== null)
.map(([key, value]) => {
switch (key.toLowerCase()) {
case 'isonline':
return ['isOnline', value];
case 'accesstoken':
return ['accessToken', value];
default:
return [key.toLowerCase(), value];
}
}),
) as any;
if (typeof obj.isOnline === 'string') {
obj.isOnline = obj.isOnline.toString().toLowerCase() === 'true';
} else if (typeof obj.isOnline === 'number') {
obj.isOnline = Boolean(obj.isOnline);
}
if (obj.scope) { obj.scope = obj.scope.toString(); }
return obj;
}
const includedKeys = [
'id',
'shop',
'state',
'isOnline',
'scope',
'accessToken',
];
function sessionEntries(
session: SessionInterface,
): Array<[string, string | number]> {
return Object.entries(session).filter(([key]) => includedKeys.includes(key));
}
// tslint:disable-next-line:interface-name
interface PostgreSQLSessionStorageOptions {
sessionTableName: string;
port: number;
}
const defaultPostgreSQLSessionStorageOptions: PostgreSQLSessionStorageOptions =
{
sessionTableName: 'shopify_sessions',
port: 3211,
};
export class PostgreSQLSessionStorage implements SessionStorage {
public static withCredentials(
host: string,
dbName: string,
username: string,
password: string,
opts: Partial<PostgreSQLSessionStorageOptions>,
) {
return new PostgreSQLSessionStorage(
new URL(
`postgres://${encodeURIComponent(username)}:${encodeURIComponent(
password,
)}#${host}/${encodeURIComponent(dbName)}`,
),
opts,
);
}
public readonly ready: Promise<void>;
private options: PostgreSQLSessionStorageOptions;
private client: pg.Client;
constructor(
private dbUrl: URL,
opts: Partial<PostgreSQLSessionStorageOptions> = {},
) {
if (typeof this.dbUrl === 'string') {
this.dbUrl = new URL(this.dbUrl);
}
this.options = {...defaultPostgreSQLSessionStorageOptions, ...opts};
this.ready = this.init();
}
public async storeSession(session: SessionInterface): Promise<boolean> {
await this.ready;
const entries = sessionEntries(session);
const query = `
INSERT INTO ${this.options.sessionTableName}
(${entries.map(([key]) => key).join(', ')})
VALUES (${entries.map((_, i) => `$${i + 1}`).join(', ')})
ON CONFLICT (id) DO UPDATE SET ${entries
.map(([key]) => `${key} = Excluded.${key}`)
.join(', ')};
`;
await this.query(
query,
// tslint:disable-next-line:variable-name
entries.map(([_key, value]) => value),
);
return true;
}
public async loadSession(id: string): Promise<Session | undefined> {
await this.ready;
const query = `
SELECT * FROM ${this.options.sessionTableName}
WHERE id = $1;
`;
const rows = await this.query(query, [id]);
if (!Array.isArray(rows) || rows?.length !== 1) { return undefined; }
const rawResult = rows[0] as any;
const sessionData = sessionFromEntries(Object.entries(rawResult));
return Session.cloneSession(sessionData, sessionData.id);
}
public async deleteSession(id: string): Promise<boolean> {
await this.ready;
const query = `
DELETE FROM ${this.options.sessionTableName}
WHERE id = $1;
`;
await this.query(query, [id]);
return true;
}
public disconnect(): Promise<void> {
return this.client.end();
}
private async init() {
this.client = new pg.Client({connectionString: this.dbUrl.toString(), ssl: true});
await this.connectClient();
await this.createTable();
}
private async connectClient(): Promise<void> {
await this.client.connect();
}
private async hasSessionTable(): Promise<boolean> {
const query = `
SELECT * FROM pg_catalog.pg_tables WHERE tablename = $1
`;
const [rows] = await this.query(query, [this.options.sessionTableName]);
return Array.isArray(rows) && rows.length === 1;
}
private async createTable() {
const hasSessionTable = await this.hasSessionTable();
if (!hasSessionTable) {
const query = `
CREATE TABLE IF NOT EXISTS ${this.options.sessionTableName} (
id varchar(255) NOT NULL PRIMARY KEY,
shop varchar(255) NOT NULL,
state varchar(255) NOT NULL,
isOnline boolean NOT NULL,
scope varchar(255),
accessToken varchar(255)
)
`;
await this.query(query);
}
}
private async query(sql: string, params: any[] = []): Promise<any> {
const result = await this.client.query(sql, params);
return result.rows;
}
}
Related
Javascript class how to make it, with a constructor?
Also what are these: `from selenium import webdriver` \`def hladaj(vyraz): driver = webdriver.Chrome() driver.get('https://www.bing.com/') search_bar = driver.find_element_by_name('q') search_bar.send_keys(vyraz) search_bar.submit() def otvor(n): result_links = driver.find_elements_by_css_selector('.b_algo a') result_links\[n-1\].click() class Laptop { constructor(vyrobca, model, rocnik) { this.vyrobca = vyrobca; this.model = model; this.rocnik = rocnik; } vypis() { return `${this.vyrobca},${this.model},${this.rocnik}`; } }\` `<script> // Ziskanie tlacidla var button = document.getElementById("remove"); // Pridanie event listenera na stlacenie tlacidla button.addEventListener("click", function() { // Ziskanie vsetkych elementov s triedou "col" var elements = document.getElementsByClassName("col"); // Prechod cez vsetky elementy for (var i = 0; i < elements.length; i++) { // Zistenie textu v elemente var text = elements[i].textContent; // Ak element obsahuje retazec "Row" if (text.includes("Row")) { // Zmazanie elementu elements[i].parentNode.removeChild(elements[i]); } } }); </script>` `function o2a(obj){ let final= []; final = Object.keys(objs).map(key=> { let arr = []; arr.push(key); arr.push(obj[key]); return arr; }) return final; }` `function a2o(arr){ let obj = {} arr.forEach(item=> { obj[item[0]] = item[1]; }); return obj; ` \`import React, { useState } from "react"; function Inp() { const \[value, setValue\] = useState(""); return ( \<input value={value} onChange={(e) =\> setValue(e.target.value)} placeholder="Input value" /\> ); } function But() { const \[clicked, setClicked\] = useState(false); return ( \<button onClick={() =\> setClicked(true)}\>Submit\</button\> ); } function Out({ value }) { return \<div\>{value}\</div\>; } function App() { const \[inputValue, setInputValue\] = useState(""); const handleClick = () =\> { setInputValue(inputValue); }; return ( \<div\> \<Inp /\> \<But onClick={handleClick} /\> \<Out value={inputValue} /\> \</div\> ); } export default App;\` Jazyk javascript bezi defaultne na jednom jadre. Na rozhodnutie toho kedy spusti ktoru funkciu, pouziva event Loop. Multi-threaded funkcionalitu vieme dosiahnut ponocou builtin API ktore sa nazyva Webliorker. Tento API umoznuje beh paralelnych procesov. A este tab a browser maju vlastne javascript thready a tak aj prehliadaci je multi thread const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8084 }); let counter = 0; setInterval(() => { counter += 2; }, 2000); wss.on('connection', (ws) => { console.log('Connected'); setInterval(() => { ws.send(counter.toString()); }, 2000); }); const WebSocket = require('ws'); const ws = new WebSocket('ws://localhost:8084'); ws.on('message', (message) => { const counter = parseInt(message); const span = document.createElement('span'); span.textContent = `Aktualny stav pocitadla: ${counter}`; document.body.appendChild(span); }); 1.prehliada precita kod ako text 2. parsuje to na AST (Abstract Syntax Tree) 3.optimalizuje to 4. vnutorne si ho za behu to kompiluje do bytecode a za behu kontroluje. Pocas kontroly sa engine pozera ze ktore funkcie su ako casto volane, alebo vypoctovo narocne a podla toho ich optimalizuje const http = require('http'); const fs = require('fs'); const server = http.createServer((req, res)=>{ if (req.method !== 'GET') { res.end({"error": "error"}") }else{ if (req.url === '/indexFile'){ fs.readFile('./index.html', function (err, html) { if (err) { throw err; res.writeHeader (200, "Content-Type": "text/html"}); res.write(html); } res.end(); if(req.url === '/response'){ const data = fetch('http://esh.op/order').then(res => res.data); res.writeHead (200, {'Content-Type': 'application/json'}); res.end(JSON.stringify(data)); } } }); server.listen(8080) function conv(str){ str = str.replaceAll(',',""); str = str.replaceAll(';', ""); str = str.replaceAll('.',""); return str.split('').sort((a,b) => b.localeCompare(a)) }
Updating data doesnt expand the data tree inside material-table
Im trying to build a table with nested tree folder inside. When trying to add nested data into the datasource data the structure will not updated and will not toggle anymore. Code below: https://stackblitz.com/edit/angular-table-tree-example-k2zqmt?file=app%2Ftable-basic-example.ts&file=app%2Ftable-basic-example.html,app%2Ftable-basic-example.ts Environment Angular: Material Table Material tree system
These are the things that are happening when logNode method is called The item is getting added but the treeControl.toggle method does not work anymore. When you are assigning a new dataset to the dataSource all the nodes get reset and the tree closes, so this.treeControl.toggle is trying to toggle a node that does not exist. You need to find the node to be toggled from the list you get from treeControl.dataNodes I would suggest having the toggle code in a separate method and adding a node code in a separate method, and a separate button to add the node. The below code should work for your scenario, also remove this line from your HTML, (click)="treeControl.toggle(data)" interface ExampleFlatNode { expandable: boolean; RoleName: string; Access: boolean; level: number; CatId: number; } private transformer = (node: FoodNode, level: number) => { return { expandable: !!node.CategoryPermissions && node.CategoryPermissions.length > 0, RoleName: node.RoleName, Access: node.Access, level: level, CatId: node.CatId, }; }; tempNodes = [] constructor() { this.dataSource.data = TREE_DATA; } logNode(clickedNode) { this.tempNodes = []; this.treeControl.dataNodes.forEach((node) => this.tempNodes.push({ ...node, expanded: this.treeControl.isExpanded(node), }) ); if (!this.treeControl.isExpanded(clickedNode)) { const temp = { Access: true, RoleName: 'test 1 2', CatId: 113, }; const clickedNodeIdx = this.treeControl.dataNodes.findIndex( (node: any) => node.CatId === clickedNode.CatId && node.RoleName === clickedNode.RoleName && node.level === clickedNode.level ); const childIdx = 1; let child; if (clickedNode.level === 0) { child = this.dataSource.data[clickedNodeIdx].CategoryPermissions[childIdx]; } else { this.dataSource.data.forEach( (item) => (child = this.findDataSource(item, clickedNode)) ); } child.CategoryPermissions.push(temp); this.dataSource.data = this.dataSource.data; const addedNode = this.treeControl.dataNodes.find( (node: any) => node.CatId === temp.CatId && node.RoleName === temp.RoleName ); this.expandParent(addedNode); this.setPreviousState(); } else { this.treeControl.collapse(clickedNode); } } findDataSource(item, node) { if (item.RoleName === node.RoleName) { return item; } else if (item.CategoryPermissions) { let matchedItem; item.CategoryPermissions.forEach((e) => { const temp = this.findDataSource(e, node); if (temp) { matchedItem = temp; } }); return matchedItem; } } setPreviousState() { for (let i = 0, j = 0; i < this.treeControl.dataNodes.length; i++) { if ( this.tempNodes[j] && this.treeControl.dataNodes[i].RoleName === this.tempNodes[j].RoleName && this.treeControl.dataNodes[i].CatId === this.tempNodes[j].CatId && this.treeControl.dataNodes[i].level === this.tempNodes[j].level ) { if (this.tempNodes[j].expanded) { this.treeControl.expand(this.treeControl.dataNodes[i]); } j++; } } } expandParent(node: ExampleFlatNode) { const { treeControl } = this; const currentLevel = treeControl.getLevel(node); const index = treeControl.dataNodes.indexOf(node) - 1; for (let i = index; i >= 0; i--) { const currentNode = treeControl.dataNodes[i]; if (currentLevel === 0) { this.treeControl.expand(currentNode); return null; } if (treeControl.getLevel(currentNode) < currentLevel) { this.treeControl.expand(currentNode); this.expandParent(currentNode); break; } } }
Refresh sticky mobile leaderboard ad slot by changing the content URL in infinite scroll
I want to refresh sticky mobile leaderboard slot when the URL changes in infinite scroll. What do you think is the best way to go? Please let me know if you have any suggestions. class DFPAds { constructor() { this.slots = []; this.onScroll = throttle(this.loopAds, 300); this.addEvents(); this.createAdObject = this.createAdObject.bind(this); this.createSlotForAd = this.createSlotForAd.bind(this); this.displayAd = this.displayAd.bind(this); } static get() { return DFPAds._instance; } static set() { if (!DFPAds._instance) { DFPAds._instance = new DFPAds(); return DFPAds._instance; } else { throw new Error("DFPAds: instance already initialized"); } } addEvents() { window.addEventListener("scroll", e => this.onScroll()); } loopAds() { this.slots.map(slot => this.displayAd(slot)); } createAdObject(ad) { let id = ad.id; let attributes = getDataSet(ad); let sizes = JSON.parse(attributes.sizes); let sizeMapping; if (attributes.sizemapping) { attributes.sizemapping.length ? (sizeMapping = JSON.parse(attributes.sizemapping)) : (sizeMapping = null); } attributes.id = id; attributes.sizes = sizes; attributes.sizemapping = sizeMapping; return attributes; } createSlotForAd(adObject) { let { id, adtype, position, slotname, sizes, sizemapping, shouldlazyload, pagenumber, pageid } = adObject; googletag.cmd.push(() => { let slot = googletag.defineSlot(slotname, sizes, id); if(position){ slot.setTargeting("position", position); } if(pagenumber){ slot.setTargeting("pagenumber", pagenumber); } if(pageid){ slot.setTargeting("PageID", pageid) } if (sizemapping) { let mapping = googletag.sizeMapping(); sizemapping.map(size => { mapping.addSize(size[0], size[1]) }); slot.defineSizeMapping(mapping.build()); } slot.addService(googletag.pubads()); googletag.display(id); shouldlazyload ? this.slots.push({ slot: slot, id: id }) : googletag.pubads().refresh([slot]); console.log("SlotTop", slot) }); } displayAd(slot) { console.log("Slottwo", slot) let item = document.getElementById(slot.id); if (item) { let parent = item.parentElement; let index = this.slots.indexOf(slot); let parentDimensions = parent.getBoundingClientRect(); if ( (parentDimensions.top - 300) < window.innerHeight && parentDimensions.top + 150 > 0 && parent.offsetParent != null ) { googletag.cmd.push(function() { googletag.pubads().refresh([slot.slot]); }); this.slots.splice(index, 1); } } } setUpAdSlots(context = document) { let ads = [].slice.call(context.getElementsByClassName("Ad-data")); if (ads.length) { ads.map(ad => compose(this.createSlotForAd, this.createAdObject)(ad)); } } } export default DFPAds; And this is my Infinite Scroll code: export default class InfiniteScroll { constructor() { this._end = document.getElementById('InfiniteScroll-End'); this._container = document.getElementById('InfiniteScroll-Container'); if(!this._end || !this._container) return; this._articles = { }; this._triggeredArticles = []; this._currentArticle = ''; this._apiUrl = ''; this._count = 1; this._timedOut = false; this._loading = false; this._ended = false; this._viewedParameter = "&alreadyViewedContentIds="; this._articleSelector = "InfiniteScroll-Article-"; this._articleClass = "Article-Container"; this.setStartData(); this.onScroll = throttle(this.eventScroll, 200); this.addEvents(); } addEvents(){ setTimeout(()=>{ window.addEventListener('scroll', (e) => this.onScroll() ); }, 2000); } addToStore(article){ this._articles["a" + article.id] = article; } addToTriggeredArticles(id){ this._triggeredArticles.push(id); } getRequestUrl(){ return this._apiUrl + this._viewedParameter + Object.keys(this._articles).map(key => this._articles[key].id).join(); } getLastArticle(){ return this._articles[Object.keys(this._articles)[Object.keys(this._articles).length-1]]; } setStartData() { let dataset = getDataSet(this._container); if(dataset.hasOwnProperty('apiurl')){ let article = Article.get(); if(article){ this._apiUrl = dataset.apiurl; this._currentArticle = "a" + article.id; this.addToStore(article); }else{ throw(new Error('Infinite Scroll: Article not initialized.')); } }else{ throw(new Error('Infinite Scroll: Start object missing "apiurl" property.')); } } eventScroll() { if(this.isApproachingNext()){ this.requestNextArticle(); } if(!this.isMainArticle(this._articles[this._currentArticle].node)){ this.updateCurrentArticle(); } } eventRequestSuccess(data){ this._loading = false; if(data != ''){ if(data.hasOwnProperty('Id') && data.hasOwnProperty('Html') && data.hasOwnProperty('Url')){ this.incrementCount(); let node = document.createElement('div'); node.id = this._articleSelector + data.Id; node.innerHTML = data.Html; node.className = this._articleClass; this._container.appendChild(node); this.initArticleUpNext({ img: data.Img, title: data.ArticleTitle, category: data.Category, target: node.id }); this.addToStore( new Article({ id: data.Id, node: node, url: data.Url, title: data.Title, count: this._count, nielsenProps: { section: data.NeilsenSection, sega: data.NeilsenSegmentA, segb: data.NeilsenSegmentB, segc: data.NeilsenSegmentC } }) ); }else{ this._ended = true; throw(new Error('Infinite Scroll: Response does not have an ID, Url and HTML property')); } }else{ this._ended = true; throw(new Error('Infinite Scroll: No new article was received.')); } } eventRequestError(response){ this._loading = false; this._ended = true; throw(new Error("Infinite Scroll: New article request failed.")); } requestNextArticle(){ if(!this._loading){ this._loading = true; return API.requestJSON(this.getRequestUrl()) .then( (response)=>{this.eventRequestSuccess(response)}, (response)=>{this.eventRequestError(response)} ); } } triggerViewEvent(article){ if(article.count > 1 && !this.isAlreadyTriggeredArticle(article.id)){ this.addToTriggeredArticles(article.id); Tracker.pushView(article.url, article.count); if(isFeatureEnabled('Nielsen') && Nielsen.get()){ Nielsen.get().eventInfiniteScroll({ id: article.id, url: article.url, section: article.nielsenProps.section, sega: article.nielsenProps.sega, segb: article.nielsenProps.segb, segc: article.nielsenProps.segc }); NielsenV60.trackEvent(article.title); } } } updateCurrentArticle(){ Object.keys(this._articles).map( key => { if(this._currentArticle !== key && this.isMainArticle(this._articles[key].node)){ this._currentArticle = key; this.updateUrl(this._articles[key]); this.triggerViewEvent(this._articles[key]); } }); } updateUrl(article){ try{ if(history.replaceState){ if(window.location.pathname !== article.url){ history.replaceState('', article.title, article.url); } } }catch(e){} } incrementCount(){ this._count = this._count + 1; } initArticleUpNext(data){ this.getLastArticle().initUpNext(data); } isApproachingNext(){ return window.pageYOffset > this._end.offsetTop - (window.innerHeight * 2) && !this._ended && this._end.offsetTop >= 100; } isMainArticle(node){ if(node.getBoundingClientRect){ return (node.getBoundingClientRect().top < 80 && node.getBoundingClientRect().bottom > 70); }else{ return false; } } isAlreadyTriggeredArticle(id){ return this._triggeredArticles.indexOf(id) > -1; } }
TypeError: 'undefined' is not a function (evaluating 'ime.registIMEKey()')
Despite of setting and defining everything in Samsung smart TV SDK 4.0 I am getting this error: TypeError: 'undefined' is not a function (evaluating 'ime.registIMEKey()') Please help! CODE: var widgetAPI = new Common.API.Widget(); var tvKey = new Common.API.TVKeyValue(); var wapal_magic = { elementIds: new Array(), inputs: new Array(), ready: new Array() }; ///////////////////////// var Input = function (id, previousId, nextId) { var previousElement = document.getElementById(previousId), nextElement = document.getElementById(nextId); var installFocusKeyCallbacks = function () { ime.setKeyFunc(tvKey.KEY_UP, function (keyCode) { previousElement.focus(); return false; }); ime.setKeyFunc(tvKey.KEY_DOWN, function (keyCode) { nextElement.focus(); return false; }); ime.setKeyFunc(tvKey.KEY_RETURN, function (keyCode) { widgetAPI.blockNavigation(); return false; }); ime.setKeyFunc(tvKey.KEY_EXIT, function (keyCode) { widgetAPI.blockNavigation(); return false; }); } var imeReady = function (imeObject) { installFocusKeyCallbacks(); wapal_magic.ready(id); }, ime = new IMEShell(id, imeReady, 'en'), element = document.getElementById(id); } wapal_magic.createInputObjects = function () { var index, previousIndex, nextIndex; for (index in this.elementIds) { previousIndex = index - 1; if (previousIndex < 0) { previousIndex = wapal_magic.inputs.length - 1; } nextIndex = (index + 1) % wapal_magic.inputs.length; wapal_magic.inputs[index] = new Input(this.elementIds[index], this.elementIds[previousIndex], this.elementIds[nextIndex]); } }; wapal_magic.ready = function (id) { var ready = true, i; for (i in wapal_magic.elementIds) { if (wapal_magic.elementIds[i] == id) { wapal_magic.ready[i] = true; } if (wapal_magic.ready[i] == false) { ready = false; } } if (ready) { document.getElementById("txtInp1").focus(); } }; //////////////////////// wapal_magic.onLoad = function() { // Enable key event processing //this.enableKeys(); // widgetAPI.sendReadyEvent(); this.initTextBoxes(new Array("txtInp1", "txtInp2")); }; wapal_magic.initTextBoxes = function(textboxes){ this.elementIds = textboxes; for(i=0;i<this.elementIds.length;i++){ this.inputs[i]=false; this.ready[i]=null; } this.createInputObjects(); widgetAPI.registIMEKey(); }; wapal_magic.onUnload = function() { }; wapal_magic.enableKeys = function() { document.getElementById("anchor").focus(); }; wapal_magic.keyDown = function() { var keyCode = event.keyCode; alert("Key pressed: " + keyCode); switch(keyCode) { case tvKey.KEY_RETURN: case tvKey.KEY_PANEL_RETURN: alert("RETURN"); widgetAPI.sendReturnEvent(); break; case tvKey.KEY_LEFT: alert("LEFT"); break; case tvKey.KEY_RIGHT: alert("RIGHT"); break; case tvKey.KEY_UP: alert("UP"); break; case tvKey.KEY_DOWN: alert("DOWN"); break; case tvKey.KEY_ENTER: case tvKey.KEY_PANEL_ENTER: alert("ENTER"); break; default: alert("Unhandled key"); break; } };
The registIMEKey method is part of the Plugin API. var pluginAPI = new Common.API.Plugin(); pluginAPI.registIMEKey(); See: http://www.samsungdforum.com/Guide/ref00006/common_module_plugin_object.html#ref00006-common-module-plugin-object-registimekey Edit: Updated to add code solution.
widgetAPI no contains method registIMEKey();, it contains in IMEShell.
Moled Dataset using Pex and Moles
I want to test below method.I am returning dataset and checking table collection. public string FetchAllDetails(string useCase, string strMainFlow) { var strError = new StringBuilder(); DataSet ds = _dal.Fetchdetails(useCase, strMainFlow, useCaseId, useCaseName); DataTable dt = new DataTable(); dt = ds.Tables[0]; if (dt.Rows.Count > 0) { BindUsecaseId(strError, useCaseName); foreach (var row in ds.Tables[0].AsEnumerable()) BindError(strError, GetOriginalFieldName(row[0].ToString())); } return strError.ToString(); } I wrote below unit test using Pex. [PexMethod] public string FetchAllDetailsTest(string useCase, string strMainFlow) { SIUploadtoolDAL dal = new SIUploadtoolDAL(); UploadtoolBL target = new UploadtoolBL(dal); MDataTableCollection dt2 = new MDataTableCollection(); dt2.Add = () => { MDataTable dt1 = new MDataTable(); dt1.ColumnsGet = () => { MDataColumnCollection dcCollection = new MDataColumnCollection(); dcCollection.Add = () => { MDataColumn dc = new MDataColumn(); dc.ColumnNameGet = () => { return "string"; }; dc.DataTypeGet = () => { return typeof(string); }; return dc; }; return dcCollection; }; return dt1; }; dal.FetchdetailsStringStringInt32StringSqlTransaction = (useCaselocal, strMainFlowlocal, useCaseIdlocal, useCaseNamelocal) => { MDataSet ds = new MDataSet(); ds.TablesGet = () => { MDataTableCollection dt = new MDataTableCollection(); dt.Add = () => { MDataTable dt1 = new MDataTable(); dt1.ColumnsGet = () => { MDataColumnCollection dcCollection = new MDataColumnCollection(); dcCollection.Add = () => { MDataColumn dc = new MDataColumn(); dc.ColumnNameGet = () => { return "string"; }; dc.DataTypeGet = () => { return typeof(string); }; return dc; }; return dcCollection; }; return dt1; }; return dt; }; return ds; }; return target.FetchAllDetails(useCase, strMainFlow, useCaseId, useCaseName); } Now I am getting MoledNotImplemented for DataTablecollection error. How I can moled dataset tabele collection?