Referencing part of the url from html href element in javascript - javascript

I'm new to programming and have run into what is probably a beginner problem. I'm not quite sure how to phrase this question but I am basically trying to figure out how to reference part of a URL for a userscript I'm modifying.
Here's the website HTML:
<div class="header module">
<h2 class="heading">
Title
I'm trying to refer to the "12345" part. "/example/12345" would also work. Here's the relevant part of the code:
function selectFromBlurb(blurb) {
return {
reference: selectTextsIn(blurb, "header .heading a:first-child")
};
}
Currently the code is referring to the Title. I tried a bunch of things but as an amateur I couldn't figure it out. Thanks for any help!
Edit: Thank you everyone for the answers! Unfortunately I couldn't figure out how to make them work with the current code, so I'm posting the full userscript here.
The parts I added are the ones with "storyid". The purpose of this userscript is to be able to hide/filter out stories based on tags, title and such, I wanted to adapt it to also be able to filter based on the unique id of each story.
Here's the original: https://greasyfork.org/en/scripts/409956-ao3-blocker
// ==UserScript==
// #name AO3 Blocker Modified
// #description Fork of ao3 savior; blocks works based on certain conditions
// #author JacenBoy
// #namespace https://github.com/JacenBoy/ao3-blocker#readme
// #license Apache-2.0; http://www.apache.org/licenses/LICENSE-2.0
// #match http*://archiveofourown.org/*
// #version 2.2
// #require https://openuserjs.org/src/libs/sizzle/GM_config.js
// #require https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js
// #grant GM_getValue
// #grant GM_setValue
// #run-at document-end
// ==/UserScript==
(function () {
"use strict";
window.ao3Blocker = {};
// Initialize GM_config options
GM_config.init({
"id": "ao3Blocker",
"title": "AO3 Blocker",
"fields": {
"tagBlacklist": {
"label": "Tag Blacklist",
"type": "text",
"default": ""
},
"tagWhitelist": {
"label": "Tag Whitelist",
"type": "text",
"default": ""
},
"authorBlacklist": {
"label": "Author Blacklist",
"type": "text",
"default": ""
},
"titleBlacklist": {
"label": "Title Blacklist",
"type": "text",
"default": ""
},
"summaryBlacklist": {
"label": "Summary Blacklist",
"type": "text",
"default": ""
},
"storyidBlacklist": {
"label": "ID Blacklist",
"type": "textarea",
"default": ""
},
"showReasons": {
"label": "Show Block Reason",
"type": "checkbox",
"default": true
},
"showPlaceholders": {
"label": "Show Work Placeholder",
"type": "checkbox",
"default": true
},
"alertOnVisit": {
"label": "Alert When Opening Blocked Work",
"type": "checkbox",
"default": false
}
},
"events": {
"save": () => {
window.ao3Blocker.updated = true;
alert("Your changes have been saved.");
},
"close": () => {
if (window.ao3Blocker.updated) location.reload();
}
},
"css": ".config_var {display: grid; grid-template-columns: repeat(2, 0.7fr);}"
});
// Define the custom styles for the script
const STYLE = "\n html body .ao3-blocker-hidden {\n display: none;\n }\n \n .ao3-blocker-cut {\n display: none;\n }\n \n .ao3-blocker-cut::after {\n clear: both;\n content: '';\n display: block;\n }\n \n .ao3-blocker-reason {\n margin-left: 5px;\n }\n \n .ao3-blocker-hide-reasons .ao3-blocker-reason {\n display: none;\n }\n \n .ao3-blocker-unhide .ao3-blocker-cut {\n display: block;\n }\n \n .ao3-blocker-fold {\n align-items: center;\n display: flex;\n justify-content: flex-start;\n }\n \n .ao3-blocker-unhide .ao3-blocker-fold {\n border-bottom: 1px dashed;\n margin-bottom: 15px;\n padding-bottom: 5px;\n }\n \n button.ao3-blocker-toggle {\n margin-left: auto;\n }\n";
// addMenu() - Add a custom menu to the AO3 menu bar to control our configuration options
function addMenu() {
// Define our custom menu and add it to the AO3 menu bar
const headerMenu = $("ul.primary.navigation.actions");
const blockerMenu = $("<li class=\"dropdown\"></li>").html("<a>AO3 Blocker Modified</a>");
headerMenu.find("li.search").before(blockerMenu);
const dropMenu = $("<ul class=\"menu dropdown-menu\"></ul>");
blockerMenu.append(dropMenu);
// Add the "Toggle Block Reason" option to the menu
const reasonButton = $("<li></li>").html(`<a>${GM_config.get("showReasons") ? "Hide" : "Show"} Block Reason</a>`);
reasonButton.on("click", () => {
if (GM_config.get("showReasons")) {
GM_config.set("showReasons", false);
} else {
GM_config.set("showReasons", true);
}
GM_config.save();
reasonButton.html(`<a>${GM_config.get("showReasons") ? "Hide" : "Show"} Block Reason</a>`);
});
dropMenu.append(reasonButton);
// Add the "Toggle Work Placeholder" option to the menu
const placeholderButton = $("<li></li>").html(`<a>${GM_config.get("showPlaceholders") ? "Hide" : "Show"} Work Placeholder</a>`);
placeholderButton.on("click", () => {
if (GM_config.get("showPlaceholders")) {
GM_config.set("showPlaceholders", false);
} else {
GM_config.set("showPlaceholders", true);
}
GM_config.save();
placeholderButton.html(`<a>${GM_config.get("showPlaceholders") ? "Hide" : "Show"} Work Placeholder</a>`);
});
dropMenu.append(placeholderButton);
// Add the "Toggle Block Alerts" option to the menu
const alertButton = $("<li></li>").html(`<a>${GM_config.get("alertOnVisit") ? "Don't Show" : "Show"} Blocked Work Alerts</a>`);
alertButton.on("click", () => {
if (GM_config.get("alertOnVisit")) {
GM_config.set("alertOnVisit", false);
} else {
GM_config.set("alertOnVisit", true);
}
GM_config.save();
alertButton.html(`<a>${GM_config.get("alertOnVisit") ? "Don't Show" : "Show"} Blocked Work Alerts</a>`);
});
dropMenu.append(alertButton);
// Add an option to show the config dialog
const settingsButton = $("<li></li>").html("<a>All Settings</a>");
settingsButton.on("click", () => {GM_config.open();});
dropMenu.append(settingsButton);
}
// Define the CSS namespace. All CSS classes are prefixed with this.
const CSS_NAMESPACE = "ao3-blocker";
// addStyle() - Apply the custom stylesheet to AO3
function addStyle() {
const style = $(`<style class="${CSS_NAMESPACE}"></style>`).html(STYLE);
$("head").append(style);
}
// getCut(work) - Move standard AO3 work information (tags, summary, etc.) to a custom element for blocked works. This will be hidden by default on blocked works but can be shown if thre user chooses.
function getCut(work) {
const cut = $(`<div class="${CSS_NAMESPACE}-cut"></div>`);
$.makeArray(work.children()).forEach((child) => {
return cut.append(child);
});
return cut;
}
// getFold(reason) - Create the work placeholder for blocked works. Optionally, this will show why the work was blocked and give the user the option to unhide it.
function getFold(reason) {
const fold = $(`<div class="${CSS_NAMESPACE}-fold"></div>`);
const note = $(`<span class="${CSS_NAMESPACE}-note"</span>`).text("This work is hidden! ");
fold.html(note);
fold.append(getReasonSpan(reason));
fold.append(getToggleButton());
return fold;
}
// getToggleButton() - Create a button that will show or hide the "cut" on blocked works.
function getToggleButton() {
const button = $(`<button class="${CSS_NAMESPACE}-toggle"></button>`).text("Unhide");
const unhideClassFragment = `${CSS_NAMESPACE}-unhide`;
button.on("click", (event) => {
const work = $(event.target).closest(`.${CSS_NAMESPACE}-work`);
if (work.hasClass(unhideClassFragment)) {
work.removeClass(unhideClassFragment);
work.find(`.${CSS_NAMESPACE}-note`).text("This work is hidden.");
$(event.target).text("Unhide");
} else {
work.addClass(unhideClassFragment);
work.find(`.${CSS_NAMESPACE}-note`).text("ℹ️ This work was hidden.");
$(event.target).text("Hide");
}
});
return button;
}
// getReasonSpan(reason) - Create the element that holds the block reason information on blocked works.
function getReasonSpan(reason) {
const span = $(`<span class="${CSS_NAMESPACE}-reason"></span>`);
let text = undefined;
if (reason.tag) {
text = `tags include <strong>${reason.tag}</strong>`;
} else if (reason.author) {
text = `authors include <strong>${reason.author}</strong>`;
} else if (reason.title) {
text = `title is <strong>${reason.title}</strong>`;
} else if (reason.summary) {
text = `summary includes <strong>${reason.summary}</strong>`;
} else if (reason.storyid) {
text = `storyid includes <strong>${reason.storyid}</strong>`;
}
if (text) {
span.html(`(Reason: ${text}.)`);
}
return span;
}
// blockWork(work, reason, config) - Replace the standard AO3 work information with the placeholder "fold", and place the "cut" below it, hidden.
function blockWork(work, reason, config) {
if (!reason) return;
if (config.showPlaceholders) {
const fold = getFold(reason);
const cut = getCut(work);
work.addClass(`${CSS_NAMESPACE}-work`);
work.html(fold);
work.append(cut);
if (!config.showReasons) {
work.addClass(`${CSS_NAMESPACE}-hide-reasons`);
}
} else {
work.addClass(`${CSS_NAMESPACE}-hidden`);
}
}
function matchTermsWithWildCard(term0, pattern0) {
const term = term0.toLowerCase();
const pattern = pattern0.toLowerCase();
if (term === pattern) return true;
if (pattern.indexOf("*") === -1) return false;
const lastMatchedIndex = pattern.split("*").filter(Boolean).reduce((prevIndex, chunk) => {
const matchedIndex = term.indexOf(chunk);
return prevIndex >= 0 && prevIndex <= matchedIndex ? matchedIndex : -1;
}, 0);
return lastMatchedIndex >= 0;
}
function isTagWhitelisted(tags, whitelist) {
const whitelistLookup = whitelist.reduce((lookup, tag) => {
lookup[tag.toLowerCase()] = true;
return lookup;
}, {});
return tags.some((tag) => {
return !!whitelistLookup[tag.toLowerCase()];
});
}
function findBlacklistedItem(list, blacklist, comparator) {
let matchingEntry = void 0;
list.some((item) => {
blacklist.some((entry) => {
const matched = comparator(item.toLowerCase(), entry.toLowerCase());
if (matched) matchingEntry = entry;
return matched;
});
});
return matchingEntry;
}
function equals(a, b) {
return a === b;
}
function contains(a, b) {
return a.indexOf(b) !== -1;
}
function getBlockReason(_ref, _ref2) {
const _ref$authors = _ref.authors,
authors = _ref$authors === undefined ? [] : _ref$authors,
_ref$title = _ref.title,
title = _ref$title === undefined ? "" : _ref$title,
_ref$tags = _ref.tags,
tags = _ref$tags === undefined ? [] : _ref$tags,
_ref$summary = _ref.summary,
summary = _ref$summary === undefined ? "" : _ref$summary,
_ref$storyid = _ref.storyid,
storyid = _ref$storyid === undefined ? [] : _ref$storyid;
const _ref2$authorBlacklist = _ref2.authorBlacklist,
authorBlacklist = _ref2$authorBlacklist === undefined ? [] : _ref2$authorBlacklist,
_ref2$titleBlacklist = _ref2.titleBlacklist,
titleBlacklist = _ref2$titleBlacklist === undefined ? [] : _ref2$titleBlacklist,
_ref2$tagBlacklist = _ref2.tagBlacklist,
tagBlacklist = _ref2$tagBlacklist === undefined ? [] : _ref2$tagBlacklist,
_ref2$tagWhitelist = _ref2.tagWhitelist,
tagWhitelist = _ref2$tagWhitelist === undefined ? [] : _ref2$tagWhitelist,
_ref2$summaryBlacklis = _ref2.summaryBlacklist,
summaryBlacklist = _ref2$summaryBlacklis === undefined ? [] : _ref2$summaryBlacklis,
_ref2$storyidBlacklist = _ref2.storyidBlacklist,
storyidBlacklist = _ref2$storyidBlacklist === undefined ? [] : _ref2$storyidBlacklist;
if (isTagWhitelisted(tags, tagWhitelist)) {
return null;
}
const blockedTag = findBlacklistedItem(tags, tagBlacklist, matchTermsWithWildCard);
if (blockedTag) {
return { tag: blockedTag };
}
const author = findBlacklistedItem(authors, authorBlacklist, equals);
if (author) {
return { author: author };
}
const blockedTitle = findBlacklistedItem([title.toLowerCase()], titleBlacklist, matchTermsWithWildCard);
if (blockedTitle) {
return { title: blockedTitle };
}
const summaryTerm = findBlacklistedItem([summary.toLowerCase()], summaryBlacklist, contains);
if (summaryTerm) {
return { summary: summaryTerm };
}
const blockedStoryid = findBlacklistedItem(storyid, storyidBlacklist, contains);
if (blockedStoryid) {
return { storyid: blockedStoryid };
}
return null;
}
const _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function getText(element) {
return $(element).text().replace(/^\s*|\s*$/g, "");
}
function selectTextsIn(root, selector) {
return $.makeArray($(root).find(selector)).map(getText);
}
function selectFromWork(container) {
return _extends({}, selectFromBlurb(container), {
title: selectTextsIn(container, ".title")[0],
summary: selectTextsIn(container, ".summary .userstuff")[0]
});
}
function selectFromBlurb(blurb) {
return {
authors: selectTextsIn(blurb, "a[rel=author]"),
tags: [].concat(selectTextsIn(blurb, "a.tag"), selectTextsIn(blurb, ".required-tags .text")),
title: selectTextsIn(blurb, ".header .heading a:first-child")[0],
summary: selectTextsIn(blurb, "blockquote.summary")[0],
storyid: selectTextsIn(blurb, ".header .heading a:first-child")
};
}
// checkWorks() - Scan all works on the page and block them if they match one of the conditions set by the user.
function checkWorks () {
const debugMode = true; // Set to true to enable extra logging
// Load our config information into a convenient JSON file.
const config = {
"showReasons": GM_config.get("showReasons"),
"showPlaceholders": GM_config.get("showPlaceholders"),
"alertOnVisit": GM_config.get("alertOnVisit"),
"authorBlacklist": GM_config.get("authorBlacklist").split(/,(?:\s)?/g).map(i=>i.trim()),
"titleBlacklist": GM_config.get("titleBlacklist").split(/,(?:\s)?/g).map(i=>i.trim()),
"tagBlacklist": GM_config.get("tagBlacklist").split(/,(?:\s)?/g).map(i=>i.trim()),
"tagWhitelist": GM_config.get("tagWhitelist").split(/,(?:\s)?/g).map(i=>i.trim()),
"summaryBlacklist": GM_config.get("summaryBlacklist").split(/,(?:\s)?/g).map(i=>i.trim()),
"storyidBlacklist": GM_config.get("storyidBlacklist").split(/,(?:\s)?/g).map(i=>i.trim())
};
// If this is a work page, save the element for future use.
const workContainer = $("#main.works-show") || $("#main.chapters-show");
let blocked = 0;
let total = 0;
if (debugMode) {
console.groupCollapsed("AO3 BLOCKER");
if (!config) {
console.warn("Exiting due to missing config.");
return;
}
}
// Loop through all works on the search page and check if they match one of the conditions.
$.makeArray($("li.blurb")).forEach((blurb) => {
blurb = $(blurb);
const blockables = selectFromBlurb(blurb);
const reason = getBlockReason(blockables, config);
total++;
if (reason) {
blockWork(blurb, reason, config);
blocked++;
if (debugMode) {
console.groupCollapsed(`- blocked ${blurb.attr("id")}`);
console.log(blurb.html(), reason);
console.groupEnd();
}
} else if (debugMode) {
console.groupCollapsed(` skipped ${blurb.attr("id")}`);
console.log(blurb.html());
console.groupEnd();
}
});
// If this is a work page, the work was navigated to from another site (i.e. an external link), and the user had block alerts enabled, show a warning.
if (config.alertOnVisit && workContainer && document.referrer.indexOf("//archiveofourown.org") === -1) {
const blockables = selectFromWork(workContainer);
const reason = getBlockReason(blockables, config);
if (reason) {
blocked++;
blockWork(workContainer, reason, config);
}
}
if (debugMode) {
console.log(`Blocked ${blocked} out of ${total} works`);
console.groupEnd();
}
}
addMenu();
addStyle();
setTimeout(checkWorks, 10);
}());

You could do
reference: blurb.querySelector(".header .heading a:first-child").href.split('/').at(-1)

I'm not sure I understood your requirement but I guess you want to return "12345" as a reference.
If so, please try this.
function selectFromBlurb(blurb) {
var refer = blurb.substring(0, blurb.lastIndexOf("/") + 1);
return {
reference: selectTextsIn(refer, "header .heading a:first-child")
};
console.log(reference)
}

Related

Asprise / scannerjs.javascript-scanner-web-twain-wia-browsers-scanner.js connection problem reactjs

i try to use scanner.js but the same error keeps on showing
i have a problem with websocket connection when i try using scanner.js from Asprise.
i installed scanner.js using npm i scanner.js and imported it in my react code. i even added the following script script in my html page and it does notwork.
import React from "react";
import scanner from 'scanner-js';
let scanRequest = {
"use_asprise_dialog": true, // Whether to use Asprise Scanning Dialog
"show_scanner_ui": true, // Whether scanner UI should be shown
"twain_cap_setting" : {
"ICAP_PIXELTYPE" : "TWPT_RGB", // Color
"ICAP_XRESOLUTION" : "100", // DPI: 100
"ICAP_YRESOLUTION" : "100",
"ICAP_SUPPORTEDSIZES" : "TWSS_USLETTER" // Paper size: TWSS_USLETTER, TWSS_A4, ...
},
"output_settings": [{
"type": "return-base64",
"format": "pdf",
"thumbnail_height": 200,
}]
};
/** Triggers the scan */
const scan = () => {
scanner.scan(displayImagesOnPage, scanRequest);
}
/** Processes the scan result */
const displayImagesOnPage = (successful, mesg, response) => {
if (!successful) { // On error
console.error('Failed: ' + mesg);
return;
}
if (successful && mesg != null && mesg.toLowerCase().indexOf('user cancel') >= 0) { // User cancelled.
console.info('User cancelled');
return;
}
let scannedImages = scanner.getScannedImages(response, true, false); // returns an array of ScannedImage
for (let i = 0;
(scannedImages instanceof Array) && i < scannedImages.length; i++) {
let scannedImage = scannedImages[i];
let elementImg = scanner.createDomElementFromModel({
'name': 'img',
'attributes': {
'class': 'scanned',
'src': scannedImage.src
}
});
(document.getElementById('images') ? document.getElementById('images') : document.body).appendChild(elementImg);
}
}
export const Scanner = () => {
return (
<div>
<h2>Scanner.js TEST</h2>
<button type="button" onClick={()=>scan()}>
Scan
</button>
<div id="images"></div>
</div>
);
};
export default Scanner;

Javascript How to get Nested Objects Correctly

I am building an Electron app that gets a certain kind of json file from the user and logs all the data from it. But I am getting an error about getting undefined from the quantity:
Json File:
{
"tiers": [
{
"trades": [
{
"wants": [
{
"item": "minecraft:string",
"quantity": {
"min": 15,
"max": 20
}
}
],
"gives": [
{
"item": "minecraft:emerald"
}
]
},
{
"wants": [
{
"item": "minecraft:emerald"
}
],
"gives": [
{
"item": "minecraft:arrow",
"quantity": {
"min": 8,
"max": 12
}
}
]
}
]
},
{
"trades": [
{
"wants": [
{
"item": "minecraft:gravel",
"quantity": 10
},
{
"item": "minecraft:emerald",
"quantity": 1
}
],
"gives": [
{
"item": "minecraft:flint",
"quantity": {
"min": 6,
"max": 10
}
}
]
},
{
"wants": [
{
"item": "minecraft:emerald",
"quantity": {
"min": 2,
"max": 3
}
}
],
"gives": [
{
"item": "minecraft:bow"
}
]
}
]
}
]
}
And this is the main.js:
const { app, BrowserWindow, ipcMain, dialog, ipcRenderer, globalShortcut } = require('electron');
const { autoUpdater } = require('electron-updater');
const path = require('path');
const Store = require('./classes/Store.js');
const { electron } = require('process');
const { setTimeout } = require('timers');
// import Vue from 'vue';
// import Vuetify from 'vuetify';
// import "vuetify/dist/vuetify.min.css";
// Vue.use(Vuetify);
let win;
let loadingScreen;
const store = new Store({
configName: 'settings',
defaults: {
windowBounds: {
width: 800,
height: 600,
x: 0,
y: 0,
},
isMaximized: false,
fullscreen: false
}
});
function createLoadingScreen() {
loadingScreen = new BrowserWindow(Object.assign({
width: 200,
height: 220,
frame: false,
transparent: true,
icon: 'build/icons/icon.png',
webPreferences: {
worldSafeExecuteJavaScript: true
}
}));
loadingScreen.setResizable(false);
loadingScreen.loadURL('file://' + __dirname + '/extraWindows/loadingScreen/loading.html');
loadingScreen.setOverlayIcon('build/icons/icon.png', "Route");
loadingScreen.on('closed', () => loadingScreen = null);
loadingScreen.webContents.on('did-finish-load', () => {
loadingScreen.show();
});
}
function createWindow() {
let width = store.get('windowBounds.width');
let height = store.get('windowBounds.height');
let x = store.get('windowBounds.x');
let y = store.get('windowBounds.y');
let isMaximized = store.get('isMaximized');
win = new BrowserWindow({
width,
height,
x,
y,
icon: 'build/icons/icon.png',
frame: false,
titleBarStyle: "hidden",
webPreferences: {
enableRemoteModule: true,
nodeIntegration: true,
webSafeExecuteJavaScript: true
},
show: false
})
win.setOverlayIcon('build/icons/icon.png', "Route");
if(isMaximized == true) {
win.maximize();
}
win.loadFile('index.html');
win.on('closed', function() {
win = null;
settingScreen = null;
});
win.webContents.on('did-finish-load', () => {
if(loadingScreen) {
loadingScreen.close();
win.show();
}
})
win.on('resize', () => {
store.set('windowBounds', win.getBounds());
});
win.on('move', () => {
store.set('windowBounds', win.getBounds());
})
win.on('maximize', () => {
store.set('isMaximized', true);
})
win.on('unmaximize', () => {
store.set('isMaximized', false);
})
win.on('show', () => {
win.setFullScreen(store.get('fullscreen'));
})
win.once('ready-to-show', () => {
autoUpdater.checkForUpdatesAndNotify();
})
}
function createSettings() {
settingScreen = new BrowserWindow({
width: 600,
height: 800,
frame: false,
parent: win,
modal: true,
titleBarStyle: "hidden",
webPreferences: {
enableRemoteModule: true,
nodeIntegration: true,
worldSafeExecuteJavaScript: true
},
show: false
})
settingScreen.loadFile('extraWindows/settingsScreen/settings.html');
settingScreen.on('close', (event) => {
event.preventDefault();
settingScreen.hide();
})
}
app.on('ready', () => {
createLoadingScreen();
setTimeout(() => {
createWindow();
createSettings();
}, 5000); // Set to 5000
});
app.on('window-all-closed', () => {
if(process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if(BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
})
app.whenReady().then(() => {
globalShortcut.register('CmdOrCtrl+O', () => {
win.webContents.send('openFile');
})
globalShortcut.register('CmdOrCtrl+D', () => {
win.webContents.send('closeFile');
})
})
// These are all of the ipc functions needed for Route to work
ipcMain.handle('viewSettings', (event, arg) => {
if(arg === "true") {
settingScreen.show();
} else if(arg === "false") {
settingScreen.hide();
}
});
ipcMain.handle('changeSettings', (event, arg) => {
if(arg === "fullScreen") {
if(win.isFullScreen() == false) {
win.setFullScreen(true);
store.set('fullscreen', true);
} else {
win.setFullScreen(false);
store.set('fullscreen', false);
}
// Fill in the data for fullscreen
} else if(arg === 'themechooser') {
// Fill in the data for themes
}
});
ipcMain.on('appVersion', (event) => {
event.sender.send('appVersion', { version: app.getVersion() });
});
ipcMain.on('restartApp', () => {
autoUpdater.quitAndInstall();
})
autoUpdater.on('updateAvailable', () => {
win.webContents.send('updateAvailable');
});
autoUpdater.on('updateDownloaded', () => {
win.webContents.send('updateDownloaded');
})
And this is the renderer.js:
const { app, ipcRenderer } = require('electron');
const Store = require('./classes/Store.js');
const remote = require('electron').remote;
const dialog = require('electron').remote.dialog;
const fs = require('fs');
const { S_IFDIR } = require('constants');
const { electron } = require('process');
const { version } = require('os');
let currentWindow = remote.getCurrentWindow();
let $ = function(selector) {
return document.querySelector(selector);
}
let projectArray = [];
// There can only be 5 projects max. Might add more.
let projectCount = 0;
document.querySelector('#tradeSetup').addEventListener('click', () => {
//Create a new setup.
alert("This works!");
});
let fileOpenerOptions = {
title: "Open Trade File",
defaultPath: "C:\\",
buttonLabel: "Start Coding",
properties: [ 'openFile' ],
filters: [
{ name: 'Json', extensions: ['json'] },
{ name: 'All FIles', extensions: ['*'] }
]
}
//Top bar buttons
function openFile() {
dialog.showOpenDialog(currentWindow, fileOpenerOptions).then(fileNames => {
if(fileNames == undefined || fileNames == null) {
console.log("No file selected.");
return;
} else {
let projectName = path.basename(fileNames.filePaths[0], path.extname(fileNames.filePaths[0]));
let rawFileData = fs.readFileSync(fileNames.filePaths[0]);
let fileData = JSON.parse(rawFileData);
console.log(fileData);
if(projectCount < 5) {
projectCount++;
createProject(projectName, fileData);
// Run code
} else if (projectCount == 5) {
alert('Support for more projects is not available yet!\nPlease wait until a later update to have more than 5 projects.');
}
}
});
}
function openSettings() {
ipcRenderer.invoke('viewSettings', "true");
}
function closeFile() {
if(document.querySelector('.activeProjectButton') == null) {
console.log("No project to close.");
} else {
let contine = confirm("Is this project the furthest project to the right? If not, please don't close it.\nThis is a bug that is being worked on.");
if(contine == true) {
document.querySelector('.activeProjectButton').remove();
document.querySelector('.activeWorkspace').remove();
projectCount--;
document.querySelectorAll('.inactiveProjectWorkspace').j--;
}
// Add a fun little secret for users
}
}
document.querySelector('#openFile').addEventListener('click', () => {
openFile();
});
document.querySelector('#openSettings').addEventListener('click', () => {
openSettings();
});
document.querySelector('#closeFile').addEventListener('click', () => {
closeFile();
})
// Create and switch projects
function createProject(name, projectData) {
// This is a beta feature for now. It is not finished
// Create the tab
let projectInProduction = document.createElement("button");
projectInProduction.id = "project" + projectCount + "Click";
projectInProduction.classList.add("invisButton");
projectInProduction.classList.add("inactiveProjectButton");
projectInProduction.classList.add("project" + projectCount);
projectInProduction.innerHTML += (name);
// Remove the welcome message
document.querySelector('.unHidden').classList.add('hidden');
document.querySelector('.unHidden').classList.remove('unHidden');
//Create the workspace
let workspaceInProduction = document.createElement("div");
workspaceInProduction.classList.add("inactiveWorkspace");
projectArray.push(projectData);
if(projectArray[projectCount - 1].tiers == null) {
alert("This is not a trade file!\nPlease use a trade file!");
} else {
$('.projects').appendChild(projectInProduction);
$('#jsonProjectContainer').appendChild(workspaceInProduction);
let table = document.createElement('table');
table.innerHTML += '<tr><th colspan="3">Buying</th><th colspan="2">Selling</th></tr>';
table.classList.add('table' + projectCount);
workspaceInProduction.appendChild(table);
let tiers = Object.keys(projectArray[projectCount - 1].tiers).length;
console.log(tiers);
for(let i = 0; i < tiers; i++) {
let tradesC = Object.keys(projectArray[projectCount - 1].tiers[i].trades).length;
for(let j = 0; j < tradesC; j++) {
let wants = Object.keys(projectArray[projectCount - 1].tiers[i].trades[j].wants);
let wantsC = Object.keys(projectArray[projectCount - 1].tiers[i].trades[j].wants).length;
let gives = Object.keys(projectArray[projectCount - 1].tiers[i].trades[j].gives);
for(let k = 0; k < wantsC; k++) {
let wantsItem = projectArray[projectCount - 1].tiers[i].trades[j].wants[k].item;
let wantsMin = projectArray[projectCount - 1].tiers[i].trades[j].wants[k].quantity["min"];
let wantsMax = projectArray[projectCount - 1].tiers[i].trades[j].wants[k].quantity["max"];
let givesItem = projectArray[projectCount - 1].tiers[i].trades[j].gives[0].item;
console.log("Wants: " + wants[k]);
console.log("Min: " + wantsMin);
console.log("Max: " + wantsMax);
console.log("Item: " + wantsItem);
console.log("Gives: " + gives);
console.log("Item: " + givesItem);
}
}
}
}
// Add a onlclick function to make switching projects work
j = projectCount;
document.getElementById('project' + projectCount + 'Click').addEventListener('click', function(j) {
let buttonIndex = j;
let buttonNodes = $('.projects').children;
let workspaceNodes = $('#jsonProjectContainer').children;
for(let i = 0; i < buttonNodes.length; i++) {
if(i == (j - 1)) {
buttonNodes[i].classList.add('activeProjectButton');
buttonNodes[i].classList.remove('inactiveProjectButton');
workspaceNodes[i].classList.add('activeWorkspace');
workspaceNodes[i].classList.remove('inactiveWorkspace');
} else {
buttonNodes[i].classList.remove('activeProjectButton');
buttonNodes[i].classList.add('inactiveProjectButton');
workspaceNodes[i].classList.remove('activeWorkspace');
workspaceNodes[i].classList.add('inactiveWorkspace');
}
}
}.bind(null, j));
}
// Title bar scripts
ipcRenderer.on('openFile', () => {
openFile();
})
ipcRenderer.on('closeFile', () => {
closeFile();
})
// App updates
ipcRenderer.send('appVersion');
ipcRenderer.on('appVersion', (event, arg) => {
ipcRenderer.removeAllListeners('appVersion');
//version.innerText = ;
});
const updateNotifier = document.getElementById('updateNotifier');
const updateAvailability = document.getElementById('updateAvailability');
const restartButton = document.getElementById('restartButton');
ipcRenderer.on('updateAvailable', () => {
ipcRenderer.removeAllListeners('updateAvailable');
updateAvailability.innerText = 'A new version of Route is available. Downloading now...';
updateNotifier.classList.remove('hidden');
});
ipcRenderer.on('update_downloaded', () => {
ipcRenderer.removeAllListeners('updateDownloaded');
updateAvailability.innerText = 'Update downloaded. It will be installed on restart. Restart to continue.';
restartButton.classList.remove('hidden');
updateNotifier.classList.remove('hidden');
});
function restartApp() {
ipcRenderer.send('restartApp');
}
And this is the index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>route - Minecraft Addon Tool</title>
<!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link href="index.css" type="text/css" rel="stylesheet" />
<link href="node_modules/#mdi/font/css/materialdesignicons.min.css" type="text/css" rel="stylesheet" />
</head>
<body>
<script>
// const electron = require('electron').remote;
const path = require('path');
const customTitleBar = require('custom-electron-titlebar');
const Menu = require('electron').remote.Menu;
const MenuItem = require('electron').remote.MenuItem;
let mainTitlebar = new customTitleBar.Titlebar({
backgroundColor: customTitleBar.Color.fromHex('#391B47'),
icon: 'build/icons/icon.png'
});
const menu = new Menu();
menu.append(new MenuItem({
label: 'Github',
click: () => {
currentWindow.webContents.on('new-window', require('electron').shell.openExternal('https://github.com/Gekocaretaker/route'));
}
}));
menu.append(new MenuItem({
label: 'Discord',
click: () => {
console.log("Hiding the link!");
}
}));
menu.append(new MenuItem({
label: 'File',
submenu: [
{
label: 'Open File',
accelerator: 'Ctrl+O',
click: () => {
openFile();
}
},
{
label: 'Close File',
accelerator: 'Ctrl+D',
click: () => {
closeFile();
}
},
{
label: 'New File',
accelerator: 'Ctrl+N',
click: () => {
console.log("This is not yet available.");
}
}
]
}))
mainTitlebar.updateMenu(menu);
</script>
<div class="grid-container">
<div class="buttons">
<div class="tooltip openFileContainer">
<button id="openFile" class="invisButton"><span class="mdi mdi-file mdi-48px"></span></button>
<div>File</div>
</div>
<div class="tooltip settingsContainer">
<button id="openSettings" class="invisButton"><span class="mdi mdi-cog-outline mdi-48px"></span></button>
<div>Settings</div>
</div>
<div class="tooltip closeProjectContainer">
<button id="closeFile" class="invisButton"><span class="mdi mdi-close mdi-48px"></span></button>
<div>Close Project</div>
</div>
</div>
<div class="projects">
<!-- <div class="project1">
<button class="invisButton activeProjectButton" id="project1Click">Project 1</button>
</div> -->
</div>
<div class="jsonEditor">
<!-- <div class="workSpace1 activeWorkSpace">
<h3>This is Workspace 1</h3>
</div> -->
<div id="jsonProjectContainer"></div>
<div class="unHidden">
<p id="welcomeMessage">Hello User! Welcome to Route. I hope you enjoy using this!</p>
</div>
<div id="updateNotifier" class="hidden">
<p id="updateAvailability"></p>
<button id="restartButton" onclick="restartApp()"></button>
</div>
</div>
<div class="sidebar">
<div class="tooltip tradeBuilder">
<button id="tradeSetup" class="invisButton"><span class="mdi mdi-apache-kafka mdi-48px"></span></button>
<div>Basic Trade</div>
</div>
<div class="tooltip whatNext">
<button id="whatsNext" class="invisButton"><span class="mdi mdi-help mdi-48px"></span></button>
<div>Whats Next?</div>
</div>
</div>
</div>
<script src="renderer.js"></script>
</body>
</html>
This is the error:
Uncaught (in promise) TypeError: Cannot read property 'min' of undefined
at createProject (renderer.js:126)
at renderer.js:48
And I am pretty sure the error comes from how I get "min". I have tried using ["min"], ['min'], .min, and as a last resort, [0].
I have the code hosted on github, if needing to be shared.
If you would debug your code, you would notice that the error occurs when j=1 and k=0. Then if you check the object, you notice that at that location there is no question property:
{
"tiers": [
{
"trades": [
{
/* ... */
},
{
"wants": [
{
"item": "minecraft:emerald"
/* no quantity here */
}
],
"gives": [
/* ... */
]
}
]
},
/* ... */
So you'll have to decide what you want to happen when there is no quantity property. You can for instance use the optional chaining operator to use a default value:
let wantsMin = projectArray[projectCount - 1].tiers[i].trades[j].wants[k].quantity.?min || 0;
let wantsMax = projectArray[projectCount - 1].tiers[i].trades[j].wants[k].quantity.?max || 0;
The above would give 0 as value for the min/max values that are missing. But all depends on what you want to happen in this scenario.
This is just an example on how you can circumvent the error, but might not be the right way to deal with it in light of the rest of your code. That is up to you to determine.
This code is to access or process the values that are in nested array.we are iterating with loops and checks the iterating values that either it is an array or not with .isArray if yes we fetch the value ,if no we return the value.
var arr=[['hi'],
['hello',['welcome','bye']],
['world']];
for(var i=0; i<arr.length; i++)
{
for(var j=0; j<arr.length; j++)
{
if(Array.isArray(arr[i][j]))
{
for(var k=0; k<arr.length; k++)
{
console.log(arr[i][j][k]);
}
}
else
{
console.log(arr[i][j]);
}
}
}

Building custom Quill Editor theme

I am trying to put together a custom Quill theme for my application that's based on the default Snow theme.
My project is built in ES6, and so I have had to adapt the Snow theme accordingly (mostly replacing instances of this with a variable name (let tooltip = this).
The area I'm having trouble in is displaying the link tooltip. I am super close in getting it to work (I can add links) but I am now stuck in displaying the preview for a link when the user puts the cursor on a hyperlink.
I have managed to narrow it down to the following line:
let [link, offset] = tooltip.quill.scroll.descendant(LinkBlot, range.index);
Range.index is the correct index of the user's cursor. But link is always null and offset is always -1, no matter if the user's cursor position is on or off a hyperlink.
Why won't the scroll.descendant function correctly retrieve the link that the user is on?
Complete theme code:
import extend from 'extend';
import Emitter from 'quill/core/emitter';
import BaseTheme, { BaseTooltip } from 'quill/themes/base';
import LinkBlot from 'quill/formats/link';
import { Range } from 'quill/core/selection';
const TOOLBAR_CONFIG = [
[{ header: ['1', '2', '3', false] }],
['bold', 'italic', 'underline', 'link'],
[{ list: 'ordered' }, { list: 'bullet' }],
['clean']
];
class ZSSnowTooltip extends BaseTooltip {
constructor(quill, bounds) {
super(quill, bounds);
this.preview = this.root.querySelector('a.ql-preview');
}
listen() {
super.listen();
let tooltip = this;
// on action add
tooltip.root.querySelector('a.ql-action').addEventListener('click', function(event) {
if (tooltip.root.classList.contains('ql-editing')) {
tooltip.save();
} else {
tooltip.edit('link', tooltip.preview.textContent);
}
event.preventDefault();
});
// on action remove
tooltip.root.querySelector('a.ql-remove').addEventListener('click', function(event) {
if (tooltip.linkRange !== null) {
tooltip.restoreFocus();
tooltip.quill.formatText(tooltip.linkRange, 'link', false, Emitter.sources.USER);
delete tooltip.linkRange;
}
event.preventDefault();
tooltip.hide();
});
// on selection change
tooltip.quill.on(Emitter.events.SELECTION_CHANGE, function(range) {
// if no range is selected
if (range === null) {
return;
}
// if range length is 0, try to get a link, if there is a link, show preview box
if (range.length === 0) {
let [link, offset] = tooltip.quill.scroll.descendant(LinkBlot, range.index); // link IS ALWAYS NULL
if (link !== null) {
tooltip.linkRange = new Range(range.index - offset, link.length());
let preview = LinkBlot.formats(link.domNode);
tooltip.preview.textContent = preview;
tooltip.preview.setAttribute('href', preview);
tooltip.show();
tooltip.position(tooltip.quill.getBounds(tooltip.linkRange));
return;
}
} else {
delete tooltip.linkRange;
}
tooltip.hide();
});
}
show() {
super.show();
this.root.removeAttribute('data-mode');
}
}
class ZSSnowTheme extends BaseTheme {
constructor(quill, options) {
if (options.modules.toolbar !== null && options.modules.toolbar.container === null) {
options.modules.toolbar.container = TOOLBAR_CONFIG;
}
super(quill, options);
}
extendToolbar(toolbar) {
this.tooltip = new ZSSnowTooltip(this.quill, this.options.bounds); //eslint-disable-line
if (toolbar.container.querySelector('.ql-link')) {
this.quill.keyboard.addBinding({ key: 'K', shortKey: true }, function(range, context) { //eslint-disable-line
toolbar.handlers['link'].call(toolbar, !context.format.link); //eslint-disable-line
});
}
}
}
ZSSnowTheme.DEFAULTS = extend(true, {}, BaseTheme.DEFAULTS, {
modules: {
toolbar: {
handlers: {
link: function(value) { // eslint-disable-line
if (value) {
let range = this.quill.getSelection(),
tooltip,
preview;
if (range === null || range.length === 0) {
return;
}
preview = this.quill.getText(range);
if (/^\S+#\S+\.\S+$/.test(preview) && preview.indexOf('mailto:') !== 0) {
preview = `mailto:${preview}`;
}
tooltip = this.quill.theme.tooltip;
tooltip.edit('link', preview);
} else {
this.quill.format('link', false);
}
}
}
}
}
});
ZSSnowTooltip.TEMPLATE =
`<span class="title">
Bezoek link
</span>
<a class="ql-preview" target="_blank" href="about:blank"></a>
<input type="text" />
<span> - </span>
<a class="ql-action">
<i class="mdi"></i>
<span class="ql-action-label"></span>
</a>
<a class="ql-remove">
<i class="mdi mdi-delete"></i>
Verwijder
</a>`;
export default ZSSnowTheme;

can not find out if the div element is already set in body in chrome extension

in my chrome extension I got an div, which I will add to the body of the current tab. I am listening to chrome.tabs.onUpdated. If this event is called, I execute a script inside content_scripts. In this function there I´ll wait till the document is ready with jQuery $(document).ready(...).
I try to access
$("#div").length
and sometimes it returns 1 and sometimes 0. It should added to the body, if it´s not already there.
For some strange reasons, the onUpdated event is called twice on each page reload. Actually I found no way to check safely if the div was already added.
Edit: My Code:
inject.js:
var crendentials;
var mailInfo;
function doLogin(username, password)
{
function verifyLogin(username, password)
{
$.get("www.example.com&login&username=" + username + "&password=" + password,
function (data)
{
if (!isNaN($.trim(data)))
{
crendentials = new Array();
crendentials[0] = username;
crendentials[1] = password;
chrome.storage.sync.set({ key: "example_toolbar", value: username + ";;;" + password});
chrome.storage.sync.set({ key: "example_toolbar_verified", value: 1});
}
else
{
chrome.storage.sync.set({ key: "example_toolbar_verified", value: 0});
}
}
);
}
if (typeof username === "undefined" || username === null || username === ""
|| typeof password === "undefined" || password === null || password === "")
{
var crentest;
chrome.storage.sync.get("example_toolbar",
function (value)
{
console.log("value von doLogin()", value.example_toolbar);
crentest = value.example_toolbar;
}
);
if (typeof crentest !== "undefined" && crentest !== null && crentest !== "")
{
chrome.storage.sync.get("example_toolbar",
function (value)
{
crendentials = value.example_toolbar.split(";;;");
}
);
}
}
else
{
verifyLogin(username, password);
}
}
function getMailInfos(callback)
{
if (typeof mailInfo === "undefined")
{
$.get("http://www.example.com&mailapi=showmails",
function (data)
{
mailInfo = new Array();
var infos = data.split("|");
mailInfo.unread = infos[0];
mailInfo.total = infos[1];
callback();
}
);
}
else
{
callback();
}
}
function getMails(callback)
{
if (typeof mailInfo === "undefined")
{
getMailInfos(function ()
{
callback(mailInfo.unread);
}
);
}
else
{
callback(mailInfo.unread);
}
}
function renderText(textstr)
{
var divText = document.createElement("div");
addClass(divText, "toolbarText");
var text = document.createTextNode(textstr);
divText.appendChild(text);
toolbar.appendChild(divText);
}
var mailAmountDiv;
function renderMail(callback)
{
var mailIco = document.createElement("div");
addClass(mailIco, "mailIcon");
mailAmountDiv = document.createElement("div");
mailAmountDiv.id = "mails_unread";
addClass(mailAmountDiv, "mailAmount");
mailIco.appendChild(mailAmountDiv);
getMails(function (value)
{
var mailAmount = document.createTextNode(value);
mailAmountDiv.appendChild(mailAmount);
toolbar.appendChild(mailIco);
renderPlaceholderSmall();
renderText(translations.notAttended + ": " + getNotRead());
}
);
}
function createToolbar(change)
{
$(document).ready(function()
{
console.log("ist vorhanden: ", $("#Example-Toolbar").length);
if ($("#Example-Toolbar").length > 0)
{
// already created, stop working here
return;
}
doLogin();
toolbar = document.createElement("div");
toolbar.id = "Example-Toolbar";
renderMail(function()
{
renderPlaceholderLarge();
renderSearch();
renderPlaceholderSmall();
renderRightIcons();
$("body").css({"margin-top": "23px", "z-index": -1});
//document.body.insertBefore(toolbar, document.body.childNodes[0]);
$(toolbar).prependTo("body");
}
);
}
);
}
background.js:
function tabListener(tabId, changeInfo, tab)
{
// exec script on current focused tabId
chrome.tabs.executeScript(tabId,
{
code: 'createToolbar();'
}
);
}
chrome.tabs.onUpdated.addListener(tabListener);
manifest.json (only neccessary parts):
"background": {
"scripts": [
"background.js"
]
},
"permissions": [
"tabs",
"http://*/",
"https://*/",
"file:///*/*",
"storage"
],
"content_scripts": [{
"matches": ["*://*/*"],
"css": ["jquery-ui.css", "style.css"],
"js": ["jquery-2.0.3.min.js", "jquery-ui.min.js", "inject.js"],
"run_at": "document_start"
}]

jquery my else if part not working... what is wrong?

I am doing a DOM manipulation using jQuery's map function. Using this I am trying to append an element to a form.
It works fine only one time; by that mean I am getting the result only in the if portion, I can't get any value from the else if portion. What is wrong with my function, or is my approachwrong?
My data:
"fields":[
{
"id":"firstname",
"label":"First Name",
"name":"fname",
"type":"text",
"value":""
},
{
"id":"email",
"label":"Email",
"name":"email",
"type":"text",
"value":""
},
{
"id":"countries",
"label":"Country",
"name":"countries",
"type":"select",
"options":[
{
"value":"",
"text":"Select Country"
},
{
"value":"in",
"text":"India",
"selected":"true"
},
{
"value":"us",
"text":"United Stated"
},
{
"value":"uk",
"text":"United Kingdom"
},
{
"value":"cn",
"text":"Canada"
}
]
},
{
"id":"submit",
"name":"submit",
"type":"submit",
"value":"Submit"
}
]
My function:
var processModules = function (mData) {
$.map(mData, function (val,i) {
$(val.container).append(
$(val.type === 'content' || val.type === 'navigation' ?
$('<div />',{
'class':val.attributes['class'],
id:val.attributes.id})
.append(val.title ? $('<h2 />',{text:val.title}) : "")
.append(val.subtitle ? $('<h3>',{text:val.subtitle}) : "")
:
val.type === 'form' ? $('<form />',{
id:val.attributes.id,
'class':val.attributes['class'],
action:val.action,
name:val.name
})
.append($('<legend />',{text:val.title}))
.append(
$.map(val.fields, function (val,i) {
var element;
if(val.id) {
console.log(val.id); // getting values and appending elements
}
if (val.label) {
element = $('<label />',{text:val.label}); // am not getting any value here..
}
if (val.type) {
element = $('<input />',{id:val.id}) // I am only getting value here..
}
} )
)
: ""));
} )
}
What is the issue? Can anyone help me?
else if only gets called if the previous if/else if statements weren't. For example:
if (true) {
// This code gets run
}
else if (true) {
// This code never will
}
With that in mind, change your if statements to be like the following:
if(val.id) {
console.log(val.id);
}
if (val.label) {
console.log(val.label);
}
if (val.type) {
console.log(val.type);
}
Your code works as expected, your would not get to the else part if the first if evaluates to true. Once if(val.id) returns true all the rest would be skipped

Categories

Resources