I am using vue.js and jspdf to generate pdf. without updating the jspdf package my app broke.
I uninstalled the package as a workaround however, can't seem to figure what about this package broke the app.
Here is the error:
Uncaught TypeError: this.thenCore is not a function
at Promise.y.then (webpack-internal:///./node_modules/jspdf/dist/jspdf.min.js:123)
at Promise.<anonymous> (adrum-latest.js:29)
at Promise.catch (<anonymous>)
at z (webpack-internal:///./node_modules/vue-analytics/dist/vue-analytics.js:1)
at S (webpack-internal:///./node_modules/vue-analytics/dist/vue-analytics.js:1)
at Function.Vue.use (webpack-internal:///./node_modules/vue/dist/vue.esm.js:5102)
at eval (webpack-internal:///./src/main.js:53)
at Module../src/main.js (app.js:21185)
at __webpack_require__ (app.js:767)
at fn (app.js:130)
Vue component below that contains jspdf code
<template><!--download href="`${filePath}`"-->
<a class="export-card" #click="downloadImage()">
<span class="export-card-image"><font-awesome-icon :icon="[iconWeight, icon]"/></span>
<span class="export-card-type">{{cardText}}</span>
</a>
</template>
<script>
import htmlToImage from 'html-to-image';
import download from 'downloadjs';
import printJS from 'print-js';
import jsPDF from 'jspdf';
import {mapActions,mapState} from 'vuex';
export default {
name: 'ExportCard',
props: {
icon: String,
iconWeight: String,
cardText: String,
filePath: String,
},
computed: mapState({
selectedMediaType: state => state.brandBuilderEditor.selectedMediaType,
selectedImage: state => state.brandBuilderEditor.selectedImage,
selectedDesign: state => state.brandBuilderEditor.selectedDesign,
state: state => state,
}),
methods: {
...mapActions([
'toggleLoader'
]),
uploadFile(file) {
const url = 'https://api.cloudinary.com/v1_1/uwm/upload';
const xhr = new XMLHttpRequest();
const fd = new FormData();
xhr.open('POST', url, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// Reset the upload progress bar
/*
document.getElementById('progress').style.width = 0;
*/
// Update progress (can be used to show progress indicator)
xhr.upload.addEventListener('progress', (e) => {
/* var progress = Math.round((e.loaded * 100.0) / e.total);
document.getElementById('progress').style.width = progress + "%"; */
console.log(`fileuploadprogress data.loaded: ${e.loaded},
data.total: ${e.total}`);
});
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// File uploaded successfully
const response = JSON.parse(xhr.responseText);
console.log('response', response);
download(`https://res.cloudinary.com/uwm/video/upload/eo_10,o_50,l_${response.public_id.replace('/', ':')},so_0/v1566662844/videos/missworld.mp4`, 'my-video.mp4');
}
};
fd.append('upload_preset', 'jlw-test');
fd.append('tags', 'browser_upload'); // Optional - add tag for image admin in Cloudinary
fd.append('file', file);
xhr.send(fd);
},
getFileName() {
let mediaType = '';
switch (this.selectedMediaType) {
case 1:
mediaType = 'flyer';
break;
case 2:
mediaType = 'social-banner';
break;
case 3:
mediaType = 'video';
break;
case 4:
mediaType = 'presentation';
break;
case 6:
mediaType = 'pricing';
break;
default:
mediaType = 'flyer';
}
return `my-${mediaType}`;
},
downloadImage() {
// Only allow the loader and scaling of the template if the export type is not email.
if(this.cardText !== 'Send to Contact') {
this.toggleLoader();
// This allows the Title card scale to be a scale of 1 instead of the viewport size.
document.getElementById('item-container').classList.add('fullscale');
}
// create the target item for the scale check
const targetScale = document.getElementById('item-container');
// Set the target check to an interval
const interval = setInterval(scaleTemplateCheck, 250);
let fileName = this.getFileName();
const _this = this;
function scaleTemplateCheck() {
// This gets the current scale of the title card.
const compStyle = window.getComputedStyle(targetScale);
const transformValue = compStyle.getPropertyValue('transform');
// If the interval does not produce the scale of 1 result redo the interval and once the scale of 1 is confirmed proceed to the htmlToImage checks
if(transformValue !== 'matrix(1, 0, 0, 1, 0, 0)') {
return;
}
clearInterval(interval);
// Checks the scale for the various export types
if (_this.cardText === '.PNG') {
htmlToImage.toPng(document.getElementById('item-container'), { backgroundColor: '#fff', quality: 1 })
.then((dataUrl) => {
download(dataUrl, `${fileName}.png`);
if (_this.selectedMediaType !== 2) {
// This allows the Title card scale to be a scale of 1 instead of the viewport size.
document.getElementById('item-container').classList.remove('fullscale');
} _this.toggleLoader();
});
} else if (_this.cardText === '.JPG') {
htmlToImage.toJpeg(document.getElementById('item-container'), { backgroundColor: '#fff', quality: 1 })
.then((dataUrl) => {
download(dataUrl, `${fileName}.jpg`);
if (_this.selectedMediaType !== 2) {
document.getElementById('item-container').classList.remove('fullscale');
} _this.toggleLoader();
});
} else if (_this.cardText === '.mp4') {
htmlToImage.toPng(document.getElementById('item-container'), { backgroundColor: '#fff', quality: 1 })
.then((dataUrl) => {
_this.uploadFile(dataUrl);
});
} else if (_this.cardText === '.PDF') {
const filename = `${fileName}.pdf`;
htmlToImage.toJpeg(document.getElementById('item-container'), { backgroundColor: '#fff', quality: 1 })
.then((canvas) => {
// eslint-disable-next-line new-cap
const pdf = new jsPDF('p', 'mm', 'letter');
if (_this.selectedMediaType === 1 || _this.selectedMediaType === 6) {
pdf.addImage(canvas, 'JPEG', 8, 8, 200, 258);
} else if ((_this.selectedMediaType === 2)) {
pdf.addImage(canvas, 'JPEG', 8, 8, 200, 200);
}
pdf.save(filename);
if (_this.selectedMediaType !== 2) {
document.getElementById('item-container').classList.remove('fullscale');
}
_this.toggleLoader();
});
} else if (_this.cardText === 'Print') {
htmlToImage.toJpeg(document.getElementById('item-container'), { backgroundColor: '#fff' })
.then((dataUrl) => {
console.log('dataUrl', dataUrl)
function VoucherSourcetoPrint(source) {
return "<html><head><script>function step1(){\n" +
"setTimeout('step2()', 10);}\n" +
"function step2(){window.print();window.close()}\n" +
"</scri" + "pt></head><body onload='step1()'>\n" +
"<img src='" + source + "' style='max-width:100%'/></body></html>";
}
const Pagelink = "about:blank";
const pwa = window.open(Pagelink, "_new");
pwa.document.open();
pwa.document.write(VoucherSourcetoPrint(dataUrl));
pwa.document.close();
if (_this.selectedMediaType !== 2) {
document.getElementById('item-container').classList.remove('fullscale');
}
_this.toggleLoader();
});
} else if (_this.cardText === 'Download') {
window.open(_this.selectedDesign.item.medias[0].uri);
}
}// end of if statement
},
},
};
</script>
<style lang="scss" scoped>
.export-card {
display: flex;
flex-direction: column;
align-items: center;
background-color: $off-white;
border-radius: $b360-border-radius-base;
border: $b360-border-width-thin $border-color-light solid;
#include rem('padding', 19px 0px 18px);
text-decoration: none;
box-shadow: none;
transition: $b360-motion-selection;
cursor: pointer;
&:hover {
border-color: $b360-color--gray__medium;
box-shadow: 0 0 6px $shadow-color;
}
}
.export-card-image {
#include rem('font-size', 30px);
color: $brand-teal;
line-height: 0;
}
.export-card-type {
font-size: $b360-font-size--base;
line-height: 1;
#include rem('margin-top', 15px);
color: $text-base-color;
}
</style>
I think you getting the error because you instrumented appdynamic to your application. You can comment-out appdynamics configuration and your application should be run. I noticed that appdynamics do deep monitoring in libraries, so it will pick up all silly methods and implementation functions.
I don't know why the app broke, however it seems that you're using jsPDF to create a PDF with an image.
Since you're already using Cloudinary, why not use it to transform the image to PDF?
This is an image - https://res.cloudinary.com/demo/sample
This is how you turn it into a PDF - https://res.cloudinary.com/demo/sample.pdf
This is with transformations - https://res.cloudinary.com/demo/c_crop,w_400,g_auto/sample.pdf
If you are getting following error, It is due to appdynamic.
To fix this issue, add following configuration to your appdynamic code.
<script charset="UTF-8" type="text/javascript">
window["adrum-start-time"] = new Date().getTime();
(function (config) {
config.appKey = "YOUR-KEY";
...
config.spa = {"spa2": true};
config.isZonePromise = true;
})(window["adrum-config"] || (window["adrum-config"] = {}));
</script>
Related
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)
}
I have more than 150k records in my table. what mistake I'm doing?
Function I'm calling.
const exportPDF = () => {
var doc;
if (download_fields.length < 9) {
doc = new jsPDF('p', 'mm', [297, 210]);
}
else {
doc = new jsPDF('l', 'pt', [12000, 12000]);
}
const data = download_data.map(elt => {
let download_arr = []
download_fields.forEach(e => { Object.entries(elt).forEach(entry => <>{e === entry[0] ? download_arr.push(entry[1]) : null}</>) })
// console.log(download_arr)
return (
download_arr
)
});
doc.autoTable(download_headers, data, {
margin: { top: 15 },
styles: { fontSize: 14, halign: 'center' },
theme: "grid",
didParseCell: function (data) {
if (data.row.index === 0 && data.section !== 'body') {
data.cell.styles.fillColor = [0, 102, 204];
data.cell.styles.lineWidth = 2;
}
}
});
doc.save(`${file_name}.pdf`);
}
Line where I'm creating data is taking more time to execute. Till then I'm unable to do any other task on the screen (freeze).
Talking time is fine if we find any solution to do other work while it's generating PDF parallelly.
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;
I want to create a PWA which acts as a bar- and QR-code scanner. For detecting QR-codes I use jsQR (see: https://github.com/cozmo/jsQR), for barcodes, I want to use QuaggaJS (see: https://serratus.github.io/quaggaJS/). To select the type of code that should be detected, I have some radio buttons on my site, which call the function "triggerScannerInitialisation()" (see below). Scanning QR-codes is working already, but scanning barcodes causes some problems. The camera image is not loaded properly. If I run the same code on testing site that only uses QuaggaJS, scanning barcodes works as it should do. I assume that opening two camera streams from the same camera may cause a problem. Can anyone give me a hint on how to use both with the same camera stream?
// variables for stopping scanner types on next run
let stopJsQrOnNextRun = true;
function triggerScannerInitialisation() {
// get the selected code type
let codeTypeSelector = document.querySelector('input[name="code_type_selector"]:checked').value;
switch (codeTypeSelector) {
case 'barcode':
stopJsQrOnNextRun = true;
startQuaggaJs();
break;
case 'qr':
stopQuaggaJs();
stopJsQrOnNextRun = false;
startJsQr();
break;
default:
return false;
}
}
function startQuaggaJs() {
document.getElementById("barcode_camera_div").hidden = false;
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#barcode_camera_div'),
constraints: {
width: 480,
height: 320,
facingMode: "environment"
},
},
decoder: {
readers: [
"code_128_reader",
"ean_reader",
"ean_8_reader",
"code_39_reader",
"code_39_vin_reader",
"codabar_reader",
"upc_reader",
"upc_e_reader",
"i2of5_reader"
],
debug: {
showCanvas: true,
showPatches: true,
showFoundPatches: true,
showSkeleton: true,
showLabels: true,
showPatchLabels: true,
showRemainingPatchLabels: true,
boxFromPatches: {
showTransformed: true,
showTransformedBox: true,
showBB: true
}
}
},
}, function (err) {
if (err) {
console.log(err);
return
}
console.log("Initialization finished. Ready to start");
Quagga.start();
});
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
Quagga.onDetected(function (result) {
console.log("Barcode detected and processed : [" + result.codeResult.code + "]", result);
});
}
function stopQuaggaJs() {
// stop quagga JS
Quagga.stop();
document.getElementById("barcode_camera_div").hidden = true;
}
function startJsQr() {
let video = document.createElement("video");
let canvasElement = document.getElementById("canvas");
let canvas = canvasElement.getContext("2d");
let loadingMessage = document.getElementById("loadingMessage");
function drawLine(begin, end, color) {
canvas.beginPath();
canvas.moveTo(begin.x, begin.y);
canvas.lineTo(end.x, end.y);
canvas.lineWidth = 4;
canvas.strokeStyle = color;
canvas.stroke();
}
// Use facingMode: environment to attemt to get the front camera on phones
navigator.mediaDevices.getUserMedia({video: {facingMode: "environment"}}).then(function (stream) {
video.srcObject = stream;
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
video.play();
console.log("JSQR triggered");
requestAnimationFrame(tickQRcode);
});
function tickQRcode() {
loadingMessage.innerText = "⌛ Video laden...";
if (video.readyState === video.HAVE_ENOUGH_DATA) {
loadingMessage.hidden = true;
canvasElement.hidden = false;
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
let imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
let code = jsQR(imageData.data, imageData.width, imageData.height, {
inversionAttempts: "dontInvert",
});
if (code) {
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
codeFound(code.data, 'qr');
}
}
if (!stopJsQrOnNextRun) {
requestAnimationFrame(tickQRcode);
} else {
stopJsQr();
}
}
function stopJsQr() {
// stop the stream
video.srcObject.getTracks().forEach(function (track) {
if (track.readyState === 'live') {
track.stop();
}
});
// remove HTML element properties
let canvasElement = document.getElementById('canvas');
canvasElement.setAttribute('hidden', 1);
canvasElement.removeAttribute('height');
canvasElement.removeAttribute('width');
}
}
Thank you for your help!
Our app is no longer able to use the tns core function addCssFile(). The function is not called at all.
I tried altering one of the addCssFile() calls by calling a made up filename. It does not trigger any errors and the code seems to skip right over it. We made no changes to this script but suddenly this function does absolutely nothing.
I added the import addCssFile portion to the code just now, and it says "module has no exported member"
import * as applicationSettings from 'tns-core-modules/application-settings';
import { localize } from 'nativescript-localize';
import { ToastDuration, Toasty } from 'nativescript-toasty';
import { fromObject } from 'tns-core-modules/data/observable';
import { Page, topmost } from 'tns-core-modules/ui/frame';
import {addCssFile} from 'tns-core-modules/ui/core/view';
const source = fromObject({});
source.set('settingsItems', [
{ name: localize('ColorSchemeMenu.ob'), enabled: true },
{ name: localize('ColorSchemeMenu.bw'), enabled: true },
{ name: localize('ColorSchemeMenu.rw'), enabled: true },
{ name: localize('ColorSchemeMenu.py'), enabled: true }
]);
export function onNavigatingTo(args: any) {
const page = args.object;
page.bindingContext = source;
}
export function settingsItemTapped(args: any) {
const button = args.object;
const homePage = button.page.navigationContext.homePage as Page;
const currentTheme = applicationSettings.getString('theme', 'blue');
if (button.text === localize('ColorSchemeMenu.ob')) {
//Orange
homePage.addCssFile('themes/orange.css');
applicationSettings.setString('theme', 'orange');
} else if (button.text === localize('ColorSchemeMenu.bw')) {
// Blue
homePage.addCssFile('themes/blue.css');
applicationSettings.setString('theme', 'blue');
} else if (button.text === localize('ColorSchemeMenu.rw')) {
// Red
homePage.addCssFile('themes/red.css');
applicationSettings.setString('theme', 'red');
} else if (button.text === localize('ColorSchemeMenu.py')) {
// Purple
//homePage.addCssFile('themes/purple.css');
homePage.addCssFile('themes/needstofail.css');
applicationSettings.setString('theme', 'purple');
}
console.log('\n\ncolor scheme has been set to: ', applicationSettings.getString('theme'), '\n\n');
new Toasty(
`${localize('ColorSchemeMenu.changedMsg')} ${button.text}`,
ToastDuration.SHORT
).show();
//transition back to settings page after selecting color scheme
topmost().navigate({
moduleName: 'home/home-page',
animated: true,
transition: {
name: 'slideRight'
}
});
}
export function homeBtnTapped(args: any) {
topmost().navigate({
moduleName: 'home/home-page',
animated: true,
transition: {
name: 'slideRight'
}
});
}
Clicking any of the buttons on the settings page should add the css info to the home page and alter the object colors. The app recognizes that the buttons are pressed, but no css changes occur. Manually changing the css file of the home page does alter the appearance of the page.
You can use application.addCss as below by using file-system.
import * as application from 'tns-core-modules/application/application';
const fs = require('tns-core-modules/file-system');
if (button.text === localize('ColorSchemeMenu.ob')) {
//Orange
pageCss = fs.path.join(fs.knownFolders.currentApp().path, 'themes/orange.css');
fs.File.fromPath(pageCss).readText().then((res) => {
application.addCss(res);
});
applicationSettings.setString('theme', 'orange');
} else if (button.text === localize('ColorSchemeMenu.bw')) {
// Blue
applicationSettings.setString('theme', 'blue');
} else if (button.text === localize('ColorSchemeMenu.rw')) {
// Red
applicationSettings.setString('theme', 'red');
} else if (button.text === localize('ColorSchemeMenu.py')) {
applicationSettings.setString('theme', 'purple');
}