making safari extension in context menu. When over image mouse right click, how i know image url? - safari

Making safari extension imageSearch By google.
Here is my source.
injected.js
document.addEventListener("contextmenu", handleContextMenu, false);
function handleContextMenu(event) {
safari.self.tab.setContextMenuEventUserInfo(event, event.target.nodeName);
}
global.html
<!DOCTYPE HTML>
<script type="text/javascript" src="jquery.js"></script>
<script>
safari.application.addEventListener("contextmenu", handleContextMenu, false);
function handleContextMenu(event) {
var query = event.userInfo;
if (query === "IMG") {
event.contextMenu.appendContextMenuItem("imageSearch", "Search Google with this image");
}
}
safari.application.addEventListener("command", performCommand, false);
function performCommand(event) {
if (event.command === "imageSearch") {
/*How I get image Url??? */
var imageUrl="";
/*
var url = "http://images.google.com/searchbyimage?image_url="+imageUrl;
var tab = safari.application.activeBrowserWindow.openTab("foreground");
tab.url = url;
*/
}
}
My goal is..
if mouse rightclick add "Search by Google With This Image" int the context menu. (clear)
and click "Search by Google With This Image" google it. (???)
so i want to know image url.
What should I do?

You could try this:
store the whole node into the event's userInfo:
function handleContextMenu(event) {
safari.self.tab.setContextMenuEventUserInfo(event, event.target);
}
add some global javascript variable to your global.html (e.g. var lastClickedImg),
change your handleContextMenu function to store the event.userInfo in function handleContextMenu to this variable:
function handleContextMenu(event) {
var query = event.userInfo;
if (query.nodeName === "IMG") {
lastClickedImg = query;
event.contextMenu.appendContextMenuItem("imageSearch", "Search Google with this image");
}
}
in your function performCommand you will easily get the image's url from lastClickedImg:
lastClickedImg.src

You can find image URL by placing an event listener for contextmenu in an injected script.
function contextMenuHandler(event)
{
var url = event.target.src;
safari.self.tab.setContextMenuEventUserInfo(event, url);
}
document.body.addEventListener("contextmenu", contextMenuHandler, false);
And then recovering the image src in command event
var imageUrl = event.userInfo;
You should also do some validation to make sure it's an image.

Related

How to preview image in element ui?

I am using element ui el-image. And I want to preview my image when clicked with (:preview-src-list). But When I click first time it doesnt preview anything. just add's my downloaded image. So I need to click 2 times. But I want to click 1 time.
Here is my template code:
<el-image :src="src"
:preview-src-list="srcList"
#click="imgClick"></el-image>
ts code:
src = null;
srcList = [];
product = 'shoe1';
imgClick() {
prevImg(product).then(resp => {
const url = window.URL.createObjectURL(new Blob([resp.data]));
this.srclist = [url];
});
}
#Watch("product")
changed(value) {
getProductImage(value).then(resp => {
const url = window.URL.createObjectURL(new Blob([resp.data]));
this.src = url;
}).catc(e => {
alert(e);
});
}
mounted() {
this.changed(product);
}
I think these things happen because when you click on that image it will trigger clickHandler:
...
clickHandler() {
// don't show viewer when preview is false
if (!this.preview) {
return;
}
...
}
...
From source
And the preview is the computed property:
...
preview() {
const { previewSrcList } = this;
return Array.isArray(previewSrcList) && previewSrcList.length > 0;
}
...
From source
So nothing happened in the first click but after that you set preview-src-list and click it again then it works.
If you code is synchronous you can use event like mousedown which will trigger before click event.
<el-image
:src="url"
:preview-src-list="srcList"
#mousedown="loadImages">
</el-image>
Example
But if you code is asynchronous you can use refs and call clickHandler after that.
...
// fetch something
this.$nextTick(() => {
this.$refs.elImage.clickHandler()
})
...
Example

Vue router - with links in a template string

I import some text strings from a translation API. Some of these strings contain HTML - also links. Some of these links must link to internal router links. For example some link. Clicking this link will ofcourse work - but it reloads the app, instead of pushing the link within the SPA.
What's the best method to make imported/external links act like vue-router links?
You really should be rendering the links with <router-link> if you want the clicks to be handled by vue-router instead of by reloading the page.
Otherwise you can intercept the clicks (via delegation) and navigate to the new route manually:
<div #click="onClick">
<!-- Render the HTML in here -->
Link
</div>
onClick(e) {
if (e.target.tagName === 'A') {
e.preventDefault();
// Manually navigate to the route
this.$router.push(e.target.href);
}
}
Although it is an old question I ran into the same problem yesterday and might help for future reference.
Trying the way #Decade Moon answered did not solve my problem as the href tag of an anchor comes with the window.location.origin.
So if I was at https://www.example.com/about and want to navigate to the homepage I was getting this URL https://www.example.com/about/https://www.example.com which it was not the expected result.
So my solution was to pass a data attribute in my template string:
const toHomepage = `<span data-href="/">Link to Homepage</span>`;
And then in my component:
<p #click="linkTo" v-html="link"></p>
See that the v-html directive will output my template string.
linkTo(e) {
if (e.target.dataset.href) {
this.$router.push(e.target.dataset.href);
}
}
A more sophisticated version of Decade's answer based on https://dennisreimann.de/articles/delegating-html-links-to-vue-router.html:
function onClick(event: MouseEvent) {
let target = event.target as HTMLElement
while (target && target.tagName !== 'A') {
target = target.parentNode as HTMLElement
}
const href = (target as HTMLLinkElement).href
if (target && target.matches("a:not([href*='://'])") && href) {
const { altKey, ctrlKey, metaKey, shiftKey, button, defaultPrevented } = event
if (metaKey || altKey || ctrlKey || shiftKey) { return }
if (defaultPrevented) { return }
if (button !== undefined && button !== 0) { return }
if (target && target.getAttribute) {
const linkTarget = target.getAttribute('target') as string
if (/\b_blank\b/i.test(linkTarget)) return
}
const url = new URL(href)
const to = url.pathname
if (window.location.pathname !== to && event.preventDefault) {
event.preventDefault()
router.push(to)
}
}

ArcGIS Online WebMap authentication timeout

I have an ArcGIS Online public account and add WebMap to my website.
My ArcGIS Online WebMap looks like this ESRI's sample: LINK
And I am trying to add my WebMap to my website like this ESRI's reference page. You will see there is a map in the center of page: LINK
My WebMap is displayed on my webpage well. When I access my webpage, my WebMap asks my ID and Password. If I entered it, then it shows my map.
However, my question is, if I moved to different page and then come back to map page, it asks again. Is it possible to set a timeout so I don't have to sign in everytime I access the page?
The reason I asked this question is that to find out if there were a way to reduce my code simple and work on code in front-end.
I've researched OAuth that ESRI provided and I ended up using esri/IdentityManager. There were references to use esri/IdentityManager package; however there were no sample code to using it with personal WebMap which used arcgisUtils.createMap
So here is sample code that I worked:
require([
"dojo/parser",
"dojo/ready",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/dom",
"esri/map",
"esri/urlUtils",
"esri/arcgis/utils",
"esri/dijit/Legend",
"esri/dijit/LayerList",
"esri/graphic",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/TextSymbol",
"esri/geometry/Point",
"esri/dijit/Scalebar",
"dojo/_base/unload",
"dojo/cookie",
"dojo/json",
"esri/config",
"esri/IdentityManager",
"esri/layers/FeatureLayer",
"dojo/domReady!"
], function (
parser,
ready,
BorderContainer,
ContentPane,
dom,
Map,
urlUtils,
arcgisUtils,
Legend,
LayerList,
Graphic,
PictureMarkerSymbol,
TextSymbol,
Point,
Scalebar,
baseUnload,
cookie,
JSON,
esriConfig,
esriId,
FeatureLayer
) {
var mapOptions = {
basemap: "topo",
autoResize: true, // see http://forums.arcgis.com/threads/90825-Mobile-Sample-Fail
center: [currentPosition.lng, currentPosition.lat],
zoom: 15,
logo: false
};
// cookie/local storage name
var cred = "esri_jsapi_id_manager_data";
// store credentials/serverInfos before the page unloads
baseUnload.addOnUnload(storeCredentials);
// look for credentials in local storage
loadCredentials();
parser.parse();
esriConfig.defaults.io.proxyUrl = "/proxy/";
//Create a map based on an ArcGIS Online web map id
arcgisUtils.createMap('PUT-YOUR-ESRI-KEY', "esriMapCanvas", { mapOptions: mapOptions }).then(function (response) {
var map = response.map;
// add a blue marker
var picSymbol = new PictureMarkerSymbol(
'http://static.arcgis.com/images/Symbols/Shapes/RedPin1LargeB.png', 50, 50);
var geometryPoint = new Point('SET YOUR LAT', 'SET YOUR LONG');
map.graphics.add(new Graphic(geometryPoint, picSymbol));
//add the scalebar
var scalebar = new Scalebar({
map: map,
scalebarUnit: "english"
});
//add the map layers
var mapLayers = new LayerList({
map: map,
layers: arcgisUtils.getLayerList(response)
}, "esriLayerList");
mapLayers.startup();
//add the legend. Note that we use the utility method getLegendLayers to get
//the layers to display in the legend from the createMap response.
var legendLayers = arcgisUtils.getLegendLayers(response);
var legendDijit = new Legend({
map: map,
layerInfos: legendLayers
}, "esriLegend");
legendDijit.startup();
});
function storeCredentials() {
// make sure there are some credentials to persist
if (esriId.credentials.length === 0) {
return;
}
// serialize the ID manager state to a string
var idString = JSON.stringify(esriId.toJson());
// store it client side
if (supports_local_storage()) {
// use local storage
window.localStorage.setItem(cred, idString);
// console.log("wrote to local storage");
}
else {
// use a cookie
cookie(cred, idString, { expires: 1 });
// console.log("wrote a cookie :-/");
}
}
function supports_local_storage() {
try {
return "localStorage" in window && window["localStorage"] !== null;
} catch (e) {
return false;
}
}
function loadCredentials() {
var idJson, idObject;
if (supports_local_storage()) {
// read from local storage
idJson = window.localStorage.getItem(cred);
}
else {
// read from a cookie
idJson = cookie(cred);
}
if (idJson && idJson != "null" && idJson.length > 4) {
idObject = JSON.parse(idJson);
esriId.initialize(idObject);
}
else {
// console.log("didn't find anything to load :(");
}
}
});

Upload html file to Tinymce read content and set content of editor

I will implement a function that display a file browser where i can upload a html file to read the html documents content and than past this content to editor.
How can i set a toolbar button that opens a file browser, that allows only html file uploads with max file size of 2MB.
Can i read content of file without to save it, like file_get_contents() on php.
I created my own TinyMCE plugin for that.
If you don't know how plugins work, create a new folder named htmlFileImport under the TinyMCE plugins directory. If you are calling tinymce.min.js, then inside this folder create a file named plugin.min.js, otherwise name it plugin.js then paste this code inside
tinymce.PluginManager.add('htmlFileImport', function(editor, url) {
editor.addButton('htmlFileImport', {
text: "Import HTML File",
icon: false,
onclick: function() {
if(editor.getContent() == ""){
editor.showFileDialog();
}
else{
editor.showReplaceContentConfirmDialog();
}
}
});
editor.showReplaceContentConfirmDialog = function(){
eval(editor.dialogConfirmReplaceContentId).Open();
eval(editor.dialogConfirmReplaceContentId).setzIndex(101);
}
editor.showInvalidHtmlFileDialod = function(){
eval(editor.dialogInvalidHtmlFileId).Open();
eval(editor.dialogInvalidHtmlFileId).setzIndex(101);
}
editor.showFileDialog = function(){
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.style.display = 'none';
fileSelector.onchange = function(e) {
var file = fileSelector.files[0];
if (file) {
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (event) {
var bodyHtml = event.target.result;
var bodyOpen = bodyHtml.indexOf('<body');
if(bodyOpen == -1)
bodyOpen = bodyHtml.indexOf('< body');
var bodyClose = bodyHtml.indexOf('</body>') + 6;
if(bodyClose == -1)
bodyClose = bodyHtml.indexOf('</ body>') + 7;
if(bodyOpen != -1 && bodyClose != -1){
bodyHtml = bodyHtml.substring(bodyOpen, bodyClose);
var divHtml = document.createElement('div');
divHtml.style.display = 'none';
divHtml.innerHTML = bodyHtml;
editor.setContent(divHtml.innerHTML);
}
else{
editor.showInvalidHtmlFileDialod();
}
}
reader.onerror = function (evt) {
editor.showInvalidHtmlFileDialod();
}
}
};
fileSelector.click();
}
});
dialogConfirmReplaceContentId and dialogInvalidHtmlFileId are custom properties I previously added to my editor in the init function, you will certainly have your own mechanism, but I let this code so you can understand what's going on.
Then to include this new plugin, just add it during your editor's creation by adding the configuration like this:
tinymce.init({
plugins: [
'yourOtherPlugins htmlFileImport'
],
toolbar1: 'yourOtherPlugins htmlFileImport',
.....
});
For allowing only HTML file, you have no way to ensure the user will import this file's type. You can check if file name's extension is .html or .htm or you can do like I did: if I can't find any <body> tag inside then I consider this is not a valid HTML.
You can check the file size by simply calling file.size
You are new on StackOverflow so just to tell you that when you ask a question, you have to show that you tried something and did some research before posting. Here we don't post like if it was a simple Google search. We post question when we are stuck, after trying.

SimpleCart.js search functionality

Have been using simpleCart for a while and it works great and i know it has a search function in it but it only seems to search certain elements my question is this, i would like to know if it can be set up to search within the contents of html files? as all the items are stored in Html pages for simple cataloging.
try this: JS
function filter(e){
search = e.value.toLowerCase();
console.log(e.value)
document.querySelectorAll('.item_name').forEach(function(row){
text = row.innerText.toLowerCase();
if(text.match(search)){
row.style.display="block"
} else {
row.style.display="none"
}
// need to count hidden items and if all instances of .kb-items are hidden, then hide .kb-item
var countHidden = document.querySelectorAll(".item_name[style='display: none;']").length;
console.log(countHidden);
})
}
function detectParent()
{
var collectionref=document.querySelectorAll(".simpleCart_shelfItem");
collectionref.forEach(group=>{
var itemcollection=group.getElementsByClassName("item_name");
var hidecounter=0;
for(var j=0;j<itemcollection.length;j++)
{
if(itemcollection[j].style.display==='none')
{
hidecounter++;
}
}
if(hidecounter===itemcollection.length)
{
group.style.display="none";
}else{
group.style.display="block";
}
});
}
And HTML:
<input type="text" onkeyup="filter(this);detectParent();"/>