I am trying to make a simple extension that creates an array that persists between pages and tabs and stores every image link with a specific class from the web page. When I click on the extension button a small html page generates the preview of each image that was stored in the array with a link to the anchor tag around it.
Hello, I am new to chrome extensions and I am trying to make a basic image stripper that throws all images with the matching class into an array from all tabs when each page is loaded. Here is my code.
manifest.json
{
"name": "Link Viewer",
"version": "1",
"manifest_version" : 2,
"browser_action" :
{
"default_popup" : "history.html",
"default_icon" : "icon.png"
},
"background" : {"scripts" : ["persistent.js"]},
"content_scripts" :
[
{
"matches" : ["http://*/*"],
"js" : ["injection.js"]
}
]
}
history.html
<h1>Image Viewer</h1>
<div id="list">
<!-- Show Listed Images Here -->
</div>
injection.js
// Executes every page load
var elements = document.getElementsByClassName("img");
var imageLinks = [];
for(var i = 0; i < elements.length; i++)
{
imageLinks.push(elements[i].firstChild.src);
}
chrome.extension.sendRequest(imageLinks);
persistent.js
// This script gets run once when the browser is started
// Declare Persistent Image Array
var gifArray = [];
// Create an event listener for when requests are returned from the injection script
chrome.extension.onRequest.addListener
(
function(linksReturned)
{
// Loop through each returned link
for(var i = 0; i < linksReturned.length; i++)
{
var exists = false;
// loop through each link in the array and make sure it doesn't exist
for(var x = 0; x < gifArray.length; x++)
{
if(gifArray[x] == linksReturned[i])
{
gifArray.splice(x,1); // Remove that index from the array
exists = true;
break;
}
}
if(exists == false)
{
gifArray.push(linksReturned[i]);
}
}
// Links are stored and ready to be displayed on web page
}
);
// Popup HTML page when someone clicks on HTML button
window.onload = function()
{
var div = document.getElementById("list");
// Loop through each GIF and add to the list
for(var i = 0; i < gifArray.length; i++)
{
// Create the anchor element
var a = document.createElement("a");
// Create the image element
var img = document.createElement("img");
img.setAttribute("src",gifArray[i]);
// Put the image inside of the anchor
a.appendChild(img);
// Put the anchor inside the div
div.appendChild(a);
}
}
What am I doing wrong? How can I have a global list of every image with the class img indexed?
the code window.onload = { .... } in persistent.js doesn't work for your popup.
You must separate it by persistent.js and popup.js, and popup.js must be included into the history.html as a script.
Like this,
history.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<h1>Image Viewer</h1>
<div id="list">
<!-- Show Listed Images Here -->
</div>
</body>
</html>
popup.js
// Popup HTML page when someone clicks on HTML button
window.onload = function()
{
chrome.extension.sendRequest({type: "getImageLinks"}, function(response) {
var div = document.getElementById("list");
// Loop through each GIF and add to the list
for(var i = 0; i < response.gifArray.length; i++)
{
// Create the anchor element
var a = document.createElement("a");
// Create the image element
var img = document.createElement("img");
img.setAttribute("src", response.gifArray[i]);
// Put the image inside of the anchor
a.appendChild(img);
// Put the anchor inside the div
div.appendChild(a);
}
});
}
persistent.js
// This script gets run once when the browser is started
// Declare Persistent Image Array
var gifArray = [];
// Create an event listener for when requests are returned from the injection script
chrome.extension.onRequest.addListener
(
function(request, sender, sendResponse) {
if (request.type == 'storeImageLinks')
{
var linksReturned = request.imageLinks;
for(var i = 0; i < linksReturned.length; i++)
{
var exists = false;
// loop through each link in the array and make sure it doesn't exist
for(var x = 0; x < gifArray.length; x++)
{
if(gifArray[x] == linksReturned[i])
{
exists = true;
break;
}
}
if(exists == false)
{
gifArray.push(linksReturned[i]);
}
}
// Links are stored and ready to be displayed on web page
}
else if (request.type == 'getImageLinks')
{
sendResponse({gifArray: gifArray});
}
}
);
injection.js
// Executes every page load
var elements = document.getElementsByClassName("img");
var imageLinks = [];
for(var i = 0; i < elements.length; i++)
{
imageLinks.push(elements[i].firstChild.src);
}
chrome.extension.sendRequest({type: "storeImageLinks", imageLinks : imageLinks});
Here is my demo extension. (crx)
Extension files in archive (rar)
To try it,
open this page
click the exntension icon
you will see the google logo on the popup.
Related
I need to show images in another window. I have 2 HTMLs files:
The parent HTML has a button in HTML loading pic data dynamically from a JSON object, after looping on it:
//JASON object loop to generate a button to open each picture in a table
tabCell.innerHTML += 'value="Open picture" onclick="OpenPopup('+myBooks[[col[j]]+')" />';
In script part:
// open the popup and send the picture base64 image
var popup;
function OpenPopup(picData) {
popup = window.open("base64popup.html?picData="+picData, "Popup", "width=300,height=100");
SendToPopup(picData);
};
function SendToPopup(picData) {
if (popup != null && !popup.closed) {
popup.focus();
} else {
alert("Popup has been closed.");
}
}
//this is the popup html file
The popup page:
<html>
<script type="text/javascript">
//on load it receive the request param
window.onload = function loadPic(){
var pictureSource = getParameterByName('picData');
var divContainer = document.getElementById("approval_report");
//it adds the data in HTML to show it with encoding
divContainer.innerHTML +='<img src=data:image/jpeg;base64,'"'+pictureSource+'"/>';
};
//function to get param
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
</script>
<body>
<div id="approval_report" />
</body>
</html>
This result is displaying only the first part of the image.
Any idea how to show it all?
I can change the idea of the popup also, i need to show this picture in another section then the main table.
I would like to remove all tags that start with href="http: and leave the text being linked in place for each of them.
There are other tags in my html file that I don't want changed at all. Again, I only want the tags that start with http stripped with the text being linked staying in place.
Essentially I want all external links stripped from the html document and the internal links to remain intact.
Any help with the right Find What: and Replace with: information would be appreciated!
You could remove all tags that don't contain the current host:
const links = Array.from(document.getElementsByTagName('a'))
links.forEach(elm => {
!elm.href.includes(window.location.host) && elm.parentNode.removeChild(elm);
})
google
about
no need for JQuery
A solution could be something like
jQuery( document ).ready( function($) {
//stores all a tags in an array.
var aTags = document.getElementsByTagName("a");
var re = new RegExp("^http://");
var length = aTags.length;
for(var i = 0; i < length; i++) {
if( aTags[i].href.test(re) ) {
aTags[i].href = "https://" //reset to something else if true?
//OR
aTags[i].href.replace("http://", "https://"); //replace with https
}
}
});
The following JavaScript should replace all links with the text, they contain:
var links = document.getElementsByTagName("a");
var regEx = /^https?:\/\//;
for (var i = 0; i < links.length; i++)
{
var elem = links[i];
if (elem.href.test(regEx))
{
var node = document.createTextNode(elem.textContent);
elem.parentElement.replaceChild(node, elem);
}
}
It loops through all links and if they start with 'http://' or 'https://', a textnode is created with the text, and that textnode replaces the link.
I am trying to drag an Image from Google Chrome or Internet Explorer and Drop into my Flex Project but I am unable to get Image directly from temp folder like Mozilla Firefox,
For Example I am using the following codes go get drag drop images from system temp folder in case of Mozilla Firefox:
this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onNativeDragDrop);
private function onNativeDragDrop(vEvent:NativeDragEvent)
{
var dropFiles:Array = vEvent.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
if(dropFiles && dropFiles.length > 0)
{
var original:File = File(dropFiles[0]);
var nativePath:String = original.nativePath;
}
}
In nativePath i am getting the path where the image is initially stored like : "C:\Users\User_Name\AppData\Local\Temp\ubeh2wbl.bmp"
But In case of Google Chrome or Internet Explorer I am getting NULL in nativePath.
So I Don't know where Google Chrome or Internet Explorer initially storing the images.
Does anyone have an idea where it is storing or how to solve this problem ?
I just tried this, and when you drag an image from Chrome over the an AIR app, it comes in as the following formats:
file promise list
url
text
html
The file promise list is empty, so we'll focus on the others.
Here is the code I used which falls back through several formats to try and get a dragged image or image path:
private function onNativeDragDrop(e:NativeDragEvent):void
{
var img:DisplayObject; //the image (or first image) that was dragged
//IF IT'S A BITMAP (The easiest, so check it first)
if (e.clipboard.hasFormat(ClipboardFormats.BITMAP_FORMAT)) {
var bmd:BitmapData = BitmapData(e.clipboard.getData(ClipboardFormats.BITMAP_FORMAT));
img = new Bitmap(bmd);
addChild(img);
trace("It's a bitmap");
}
//IF IT'S FILE(S) that are dragged, try this next
if (!img && e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) {
var dropfiles:Array;
var file:File;
dropfiles = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
for each (file in dropfiles)
{
//isImagePath is defiend below
if (isImagePath(file.nativePath)) {
img = loadImage(file.nativePath); //load image function is defined below
break; //let's just load the first image
}
}
}
//IF IT's A URL that was dragged, try this next
if (!img && e.clipboard.hasFormat(ClipboardFormats.URL_FORMAT)) {
var url:String = String(e.clipboard.getData(ClipboardFormats.URL_FORMAT));
trace("It's a url: ", url);
if (isImagePath(url)) {
trace("it's a URL image path");
img = loadImage(url);
}
}
//IF IT's HTML that was dragged, try this next
if (!img && e.clipboard.hasFormat(ClipboardFormats.HTML_FORMAT)) {
var html:String = String(e.clipboard.getData(ClipboardFormats.HTML_FORMAT));
trace("its HTML: ", html);
//use regex to get all the <img> tags from the html
var imgs:Array = html.match(/(<img.*?>)/g);
//if one or more was found
if (imgs.length) {
trace("Image tag(s) found");
var imgPath:String;
for (var i:int = 0; i < imgs.length; i++) {
//use regex to get the src value from the img tag
imgPath = imgs[i].match(/src="(.*?)"/)[1];
img = loadImage(imgPath);
break; //let's just load the first image
}
}
}
//IF IT's raw text that dragged, try this next
if (!img && e.clipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)) {
var txt:String = String(e.clipboard.getData(ClipboardFormats.TEXT_FORMAT));
trace("its text: ", txt);
if (isImagePath(txt)) {
img = loadImage(txt);
}
}
}
private var imgTypes:Vector.<String> = new < String > ["jpg", "gif", "png"];
private function isImagePath(path:String):Boolean {
if (path.lastIndexOf(".") > -1) {
var ext:String = path.substr(path.lastIndexOf(".")).toLowerCase();
return new RegExp(imgTypes.join("|")).test(ext);
}
return false;
}
private function loadImage(path):Loader {
var l:Loader = new Loader();
l.load(new URLRequest(path));
addChild(l);
return l;
}
I have a main folder with index.html file for my html app. I have written a code in index.html of main folder to access the file (index.html) present in the sub folder as follows,
SubFile
When i click on the above link, it is not navigating to the subfile and instead the link of main folder index.html file changes to mainfolder/index.html#!/subfolder/index.html
I even tried changing the name of subfolder file but no success. What could be the problem?
I also want to navigate back to the main folder index.html from subfolder as follow,
Mainfile
But it is also not working. How can I achieve this as well?
Edited:
The file my-app.js is creating the issue. The code of my-app.js is as follows,
// Initialize your app
var myApp = new Framework7({
animateNavBackIcon: true,
// Enable templates auto precompilation
precompileTemplates: true,
// Enabled pages rendering using Template7
swipeBackPage: false,
swipeBackPageThreshold: 1,
swipePanel: "left",
swipePanelCloseOpposite: true,
pushState: true,
pushStateRoot: undefined,
pushStateNoAnimation: false,
pushStateSeparator: '#!/',
template7Pages: true
});
// Export selectors engine
var $$ = Dom7;
// Add main View
var mainView = myApp.addView('.view-main', {
// Enable dynamic Navbar
dynamicNavbar: false
});
$$(document).on('pageInit', function (e) {
$(".swipebox").swipebox();
$("#ContactForm").validate({
submitHandler: function(form) {
ajaxContact(form);
return false;
}
});
$('a.backbutton').click(function(){
parent.history.back();
return false;
});
$(".posts li").hide();
size_li = $(".posts li").size();
x=4;
$('.posts li:lt('+x+')').show();
$('#loadMore').click(function () {
x= (x+1 <= size_li) ? x+1 : size_li;
$('.posts li:lt('+x+')').show();
if(x == size_li){
$('#loadMore').hide();
$('#showLess').show();
}
});
$("a.switcher").bind("click", function(e){
e.preventDefault();
var theid = $(this).attr("id");
var theproducts = $("ul#photoslist");
var classNames = $(this).attr('class').split(' ');
if($(this).hasClass("active")) {
// if currently clicked button has the active class
// then we do nothing!
return false;
} else {
// otherwise we are clicking on the inactive button
// and in the process of switching views!
if(theid == "view13") {
$(this).addClass("active");
$("#view11").removeClass("active");
$("#view11").children("img").attr("src","images/switch_11.png");
$("#view12").removeClass("active");
$("#view12").children("img").attr("src","images/switch_12.png");
var theimg = $(this).children("img");
theimg.attr("src","images/switch_13_active.png");
// remove the list class and change to grid
theproducts.removeClass("photo_gallery_11");
theproducts.removeClass("photo_gallery_12");
theproducts.addClass("photo_gallery_13");
}
else if(theid == "view12") {
$(this).addClass("active");
$("#view11").removeClass("active");
$("#view11").children("img").attr("src","images/switch_11.png");
$("#view13").removeClass("active");
$("#view13").children("img").attr("src","images/switch_13.png");
var theimg = $(this).children("img");
theimg.attr("src","images/switch_12_active.png");
// remove the list class and change to grid
theproducts.removeClass("photo_gallery_11");
theproducts.removeClass("photo_gallery_13");
theproducts.addClass("photo_gallery_12");
}
else if(theid == "view11") {
$("#view12").removeClass("active");
$("#view12").children("img").attr("src","images/switch_12.png");
$("#view13").removeClass("active");
$("#view13").children("img").attr("src","images/switch_13.png");
var theimg = $(this).children("img");
theimg.attr("src","images/switch_11_active.png");
// remove the list class and change to grid
theproducts.removeClass("photo_gallery_12");
theproducts.removeClass("photo_gallery_13");
theproducts.addClass("photo_gallery_11");
}
}
});
document.addEventListener('touchmove', function(event) {
if(event.target.parentNode.className.indexOf('navbarpages') != -1 || event.target.className.indexOf('navbarpages') != -1 ) {
event.preventDefault(); }
}, false);
// Add ScrollFix
var scrollingContent = document.getElementById("pages_maincontent");
new ScrollFix(scrollingContent);
var ScrollFix = function(elem) {
// Variables to track inputs
var startY = startTopScroll = deltaY = undefined,
elem = elem || elem.querySelector(elem);
// If there is no element, then do nothing
if(!elem)
return;
// Handle the start of interactions
elem.addEventListener('touchstart', function(event){
startY = event.touches[0].pageY;
startTopScroll = elem.scrollTop;
if(startTopScroll <= 0)
elem.scrollTop = 1;
if(startTopScroll + elem.offsetHeight >= elem.scrollHeight)
elem.scrollTop = elem.scrollHeight - elem.offsetHeight - 1;
}, false);
};
})
What shall i remove from it to solve my problem?
#!/subfolder/index.html
This make me feel that you are using a single page application framework/library, like Angular or something related. So maybe your problem is not in the html but in your javascript code.
Please remove all javascript and check it will work fine then revert all js one by one and test you will find the conflict javascript resolve that conflict. it will work fine.
So I wonder what it takes to make changes made by google apps script to a document reversible.
In particular I am working on a script that applies custom styles to selected elements from a document in Google Docs. It's not a hard thing to do. The problem is that the changes made by the script are not reflected in the history of the document and thus cannot be undone. There is no notion of a reversible editing session either as far as I can tell.
So is there a way to undo the changes made by a script?
function onOpen() {
DocumentApp.getUi()
.createMenu('Extras')
.addItem('Apply code style', 'applyCodeStyle')
.addToUi();
}
function applyCodeStyle() {
var selection = DocumentApp.getActiveDocument().getSelection();
if (selection) {
var elements = selection.getSelectedElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
// Only modify elements that can be edited as text; skip images and other non-text elements.
if (element.getElement().editAsText) {
var text = element.getElement().editAsText();
// Bold the selected part of the element, or the full element if it's completely selected.
if (element.isPartial()) {
text.setBold(element.getStartOffset(), element.getEndOffsetInclusive(), true);
} else {
text.setBold(true);
}
}
}
}
}
The closest I can imagine it to create a backup copy of your file in a specific folder every 5 minutes or so when you are modifying it so you have at least a copy of this doc version. Not ideal but it works...
Here is a piece of code that does it, starting from your code I just added the timer/copy stuff, you can try it by changing the folder ID.
EDIT : added a try/catch for first execution without error.
function applyCodeStyle() {
var selection = DocumentApp.getActiveDocument().getSelection();
try{
var x = new Date().getTime()/60000-new Date(Utilities.jsonParse(ScriptProperties.getProperty('lastBKP'))).getTime()/60000 ;
}catch(e){
ScriptProperties.setProperty('lastBKP', Utilities.jsonStringify(new Date()));
var x = 0
}
Logger.log(x+' minutes')
if (selection) {
if(x > 5){
var docId = DocumentApp.getActiveDocument().getId();
DriveApp.getFileById(docId).makeCopy(DriveApp.getFolderById('0B3qSFd3iikE3NWd5TmRZdjdmMEk')).setName('backup_of_'+DocumentApp.getActiveDocument().getName()+'_on_'+Utilities.formatDate(new Date(),'GMT','yyyy-MMM-dd-HH-mm'));
Logger.log("file copied because new Date().getTime()/3600-new Date(Utilities.jsonParse(ScriptProperties.getProperty('lastBKP'))).getTime()/3600 ="+x);
ScriptProperties.setProperty('lastBKP', Utilities.jsonStringify(new Date()));
}
var elements = selection.getSelectedElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element.getElement().editAsText) {
var text = element.getElement().editAsText();
if (element.isPartial()) {
text.setBold(element.getStartOffset(), element.getEndOffsetInclusive(), true);
} else {
text.setBold(true);
}
}
}
}
}