I am creating an Ad Blocker. I am just trying to Automatically on safari extension of "Content Blocker". I went through examples but did't found any solution. Is there any way to "ON" extension or manually we have to start it?
On iOS, Safari Content Blockers are disabled by default.
There is no way to automatically enable them from your app. You must instruct the user to:
Open the Settings app.
Go to Safari > Content Blockers.
Toggle on your Content Blocker extension.
On macOS (as of 10.12), a similar rule applies: Content Blocker extensions (bundled with your app) are disabled by default, and must be toggled on by the user in Safari Preferences > Extensions.
Assuming you want to test your "personal AdBlock program", first prepare a dummy HTML, with this line <div class="ads">hello</div>,
next apply your "personal AdBlock program", assuming it is JavaScript/CSS based and not proxy-like, you either hide, or remove the element (Node) from the DOM.
for example:
document.querySelector('div[class*="ads"]') -- this is nice and (very) generic way to find the element.
this is how to hide "the ads"
document.querySelector('div[class*="ads"]').style.display="none";
or, to make it stronger, related to other rules on the page, make it a local style + important notifier: document.querySelector('div[class*="ads"]').style.cssText="display:none !important;" ;
you can also remove the element (Node) from the DOM:
var e = document.querySelector('div[class*="ads"]') follow by:
e.parentNode.removeChild(e);
now, you probably want to see that "YOUR ADBLOCK" worked,
later (after the page has loaded, and your javascript code runned) type:
console.log(null === document.querySelector('div[class*="ads"]') ? "removed(success)" : "still here(failed)")
note that for this example (to make things simple) I assume there is only one div with that class in the page (avoiding loops :) ).
if you've just going to hide the element, you should query its current (most updated) style-condition, using a native method exist under window:
console.log("none" === window.getComputedStyle(document.querySelector('div[class*="ads"]')) ? "hidden(success)" : "still here(failed)")
Enjoy!
Related
Something that drives me nuts in the developper tools of Chrome (106) and Firefox (105) is the fact that whenever some text logged to the console via console.log(text) happens to contain a hyperlink, this link is not only turned clickable (I can live with it even when I usually prefer to have just plain text) but is abbreviated, if it is a long link. So when I want to control what precise link is in some variable, I cannot just write e.g. console.log(img.src), because some of the interesting information of the link is hidden.
You can try yourself with
var href = 'https://stackoverflow.com/search?q=%5Bgoogle-chrome-devtools%5D+%5Bconsole.log%5D+%5Bfirefox-developer-tools%5D+%5Bhyperlink%5D+automatic+detection&someMoreStuffTomakeTheLinkLonger';
console.log(href);
In both, Firefox and Chrome, the output for me contains some '...', e.g. in Firefox I obtain as output:
https://stackoverflow.com/search?q=%5Bgoogle-chrome-devtools…link%5D+automatic+detection&someMoreStuffTomakeTheLinkLonger
thus hiding the part after "-devtools". (Chrome hides a slightly different part). The console is mostly a debugging tool. I log things because I want to see them, not hide them. I always need to either hover with the mouse and wait for the tooltip (doesn't allow me to copy fractions of the link) or to right click copy the link and paste it somewhere where I can see it completely. Or take a substring to remove the "https://" in the front. But note that the variable isn't necessarily a single hyperlink, but can be any text containing several such hyperlinks. I didn't find a way to force console.log to just print plain text all content. Did anybody meet this problem as well and find a workaround?
I made this a community wiki answer, because the main insight is not from myself but from the comments. Feel free to improve.
The console.log() function allows several arguments, which allows also a formatted output similar to printf in some languages. The possibilities of formatting can be found in the documentation of console.log() on MDN. In any case, this formatted output provides a solution at least for Chrome, as #wOxxOm pointed out in the comments:
console.log('%O', href) // works in Chrome
This is rather surprising, because %O is described at MDN as
"Outputs a JavaScript object. Clicking the object name opens more information about it in the inspector".
It seems there is no 'clicking' in Chrome when the object is a string.
There is also %s for string output, but this just gives the standard behavior of replacing links in both browsers. And for Firefox none of the above two formatting options works. There one really has to replace the protocol "https://" by something that is not recognized as link. A space behind ':' seems enough, so "https: //". It turns out, that one can also insert a formatting string "https:%c//", which can even be empty, and thus yield an output which is the complete link and can be copied as well:
console.log(href.replace(/(https?:)/, "$1%c"), ""); // works in Firefox
In particular the FF solution is cumbersome, and there might also be several links within one console-output. So it is useful to define one's own log-function (or if one prefers, redefine console.log, but note the remark at the end)
function isChrome() {...} // use your favorite Chrome detection here
function isFirefox() {...} // use your favorite Firefox detection here
function plainLog() {
const msg = arguments[0];
if (isChrome() && arguments.length == 1 && typeof msg == "string") {
return console.log("%O", msg);
}
if (isFirefox() && arguments.length == 1 && typeof msg == "string") {
const emptyStyle = ""; // serves only as a separator, such that FF doesn't recognize the link anymore
const reg = /(https?:)\/\//g;
const emptyStyles = []; // we need to insert one empty Style for every found link
const matches = msg.matchAll(reg);
for (let match of matches) {
emptyStyles.push(emptyStyle);
}
return console.log(msg.replace(reg, '$1%c//'), ...emptyStyles);
}
return console.log(...arguments);
}
For browser detection isChrome() and isFirefox() see e.g. here on SO.
One can of course extend the redefinition also to the other console functions (console.info, console.warn, etc.)
The downside of the redefinition of console.log is that usually every output of the console shows also the last entry of the call stack as a practical link to the source of the logging. But due to the redefintion, this link is now always to the same place, namely the file and line number where plainLog() is defined and calls console.log(), instead of the place where the new log command plainLog() was called. This new problem is described on SO here, but the solution (see comment) is again a bit involved and also not completely satisfying to serve as a replacement for the built-in console.log . So if links appear only rarely in the logging, it's probably better to switch to the redefined plainLog() only for these links.
I am trying to add a yes/no message box to a google sheet that will display on an iPad. I have tried all the things below but none of them display the message. My goal is if the user changes a field the macro will change other fields if the user says it is ok. I can get this to work on a windows machine with no issues but when I try it on an ipad the message never appears. At this point I am just trying to get a message box to appear. This is what I have tried
1.
function onEdit(e) {
Browser.msgBox("test");
}
Result: The macros times out
2.
function onEdit(e) {
var html = HtmlService.createHtmlOutputFromFile('Page')
.setWidth(400)
.setHeight(300);
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showModalDialog(html, 'My custom dialog');
}
Page.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>
I enabled the trigger for onEdit to get it to work and it works on the windows machine without issues but when run on the iPad I get:
Exception: You do not have permission to call Ui.showModalDialog. Required permissions: https://www.googleapis.com/auth/script.container.ui
So next I tried:
3.
function myFunction(){
Logger.log("myFun")
var html = HtmlService.createTemplateFromFile( 'Page' )
.evaluate()
.setWidth( 800 )
.setHeight( 400 );
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showModalDialog( html, 'My page title' );
}
function onEdit(){
ScriptApp.newTrigger('myFunction')
.forSpreadsheet(SpreadsheetApp.getActive())
.onEdit()
.create();
}
Using the same page.html, this time in executions it looks like it runs but no box appears on the ipad(it does work on windows). I also tried spreadsheetApp.getUi().alert and prompt, these had the same results.
And Yes I have to use the iPad, I can not use another type of tablet.
Issue:
"Exception: You do not have permission to call Ui.showModalDialog. Required permissions: googleapis.com/auth/script.container.ui"
Fix:
What you can do is installing the trigger instead of using a simple trigger. The image below shows the difference between an installed (above) and a simple (below) trigger using the same code.
Output:
Note:
Don't use reserved function names on installed triggers to avoid it being executed twice like what's shown above. Change onEdit to something like promptUI or something else.
If the above fix isn't enough to show the dialog box, then we need to confirm if the issue might just be on the safari browser (if you are using one) since it worked on your other devices which I assumed are not using safari. You can try using an alternative browser in your device such as Google Chrome and see if the same issue persists. I recommended doing this since i'm seeing a number of issues between showModalDialog and safari
EDIT:
I have seen these related posts pointing out that there are some limitations on mobile apps. See the references below.
Also, some answers suggests that you need to access the spreadsheet via browser (google chrome desktop mode) and then trigger the script there.
References:
Add a script trigger to Google Sheet that will work in Android mobile app
google speadsheet api onOpen does not work on mobile ios
Executing Google Apps Script Functions from Mobile App
How to get scripts to work with phones and tablets
I'm trying to write a script that will automatically open a webpage http://www.legislation.gov.uk/new/uksi and then click on all the links in the table "All New Legislation".
So far I've managed to get it to open the page but no luck with clicking.
Here's my script so far:
activate application "Safari"
open location "http://www.legislation.gov.uk/new/uksi"
to clickID()
do JavaScript "document.getElementById(id=per).click();" in document 1
end tell
The following example AppleScript code will open the targetURL in a new Safari window, wait for the page to finish loading, retrieve all URLs on the target page, search them for URLs pointing the various Statutory Instruments published today, and then open each one in a new tab of the same window the targetURL was opened.
set targetURL to "http://www.legislation.gov.uk/new/uksi"
set theseURLs to {}
set grepSearchPattern to ".*\\.uk/uksi/.*\\|.*\\.uk/ssi/.*\\|.*\\.uk/wsi/.*\\|.*\\.uk/nisi/.*"
set jsStatements to "var a = document.links; var x = ''; var i; for (i = 0; i < a.length; i++) { x = x + a[i].href + '|'; };"
tell application "Safari"
make new document with properties {URL:targetURL}
activate
end tell
tell application "System Events"
repeat until exists ¬
(buttons of UI elements of groups of toolbar 1 of window 1 of ¬
process "Safari" whose name = "Reload this page")
delay 1
end repeat
end tell
tell application "Safari"
set allURLs to (do JavaScript jsStatements in document 1)
end tell
try
set theseURLs to paragraphs of (do shell script "tr '|' '\\12' <<< " & ¬
allURLs's quoted form & " | grep " & grepSearchPattern's quoted form)
end try
if (length of theseURLs) is greater than 0 then
tell application "Safari" to tell front window
repeat with thisURL in theseURLs
set current tab to (make new tab with properties {URL:thisURL})
end repeat
set current tab to first tab
end tell
else
display dialog " Nothing published on this date." buttons {"OK"} ¬
default button 1 with title "All New Legislation" with icon note
end if
Hint: Mouse over and horizontal/vertical scroll to see full code.
Notes:
The do JavaScript1 command create a pipe delimited string of all URLs on the page of the targetURL.
The do shell script command takes the pipe delimited string of all URLs and replaces the pipe characters with newline characters, using tr, so grep can return the URLs that match the grepSearchPattern.
The grepSearchPattern variable currently only searches for Statutory Instruments, as I assume that is all that will show under All New Legislation on the page the targetURL opens to, because of /new/uksi in the targetURL, and what I've observed at that URL since you posted the question. If you also want links for other types of legislation, the grepSearchPattern variable can be adjusted to accommodate.
1 Using the do JavaScript command requires Allow JavaScript from Apple Events to be checked on the Safari > Develop menu, which is hidden by default and can be shown by checking [√] Show Develop menu in menu bar in: Safari > Preferences… > AdvancedIf you are not allowed to enable that setting, the URLs can be collected for processing in another manner, however it uses the lynx third party utility.
Opening the links without the use of the do JavaScript command:
The following example AppleScript code will use lynx to retrieve the URLs from the targetURL, search them for URLs pointing the various Statutory Instruments published today, and if some have been published will open the targetURL in a new Safari window, wait for the page to finish loading, and then open each one in a new tab of the same window the targetURL was opened.
set targetURL to "http://www.legislation.gov.uk/new/uksi"
set theseURLs to {}
set lynxCommand to "/usr/local/bin/lynx --dump -listonly -nonumbers -hiddenlinks=ignore"
set grepSearchPattern to ".*\\.uk/uksi/.*\\|.*\\.uk/ssi/.*\\|.*\\.uk/wsi/.*\\|.*\\.uk/nisi/.*"
try
set theseURLs to paragraphs of ¬
(do shell script lynxCommand & space & targetURL's quoted form & ¬
" | grep " & grepSearchPattern's quoted form)
end try
if (length of theseURLs) is greater than 0 then
tell application "Safari"
make new document with properties {URL:targetURL}
activate
end tell
tell application "System Events"
repeat until exists ¬
(buttons of UI elements of groups of toolbar 1 of window 1 of ¬
process "Safari" whose name = "Reload this page")
delay 1
end repeat
end tell
tell application "Safari" to tell front window
repeat with thisURL in theseURLs
set current tab to (make new tab with properties {URL:thisURL})
end repeat
set current tab to first tab
end tell
else
display dialog " Nothing published on this date." buttons {"OK"} ¬
default button 1 with title "All New Legislation" with icon note
end if
Hint: Mouse over and horizontal/vertical scroll to see full code.
Notes:
In the lynxCommand variable, change /usr/local/bin/lynx to the appropriate /path/to/lynx. lynx can be installed using Homebrew
The grepSearchPattern variable currently only searches for Statutory Instruments, as I assume that is all that will show under All New Legislation on the page the targetURL opens to, because of /new/uksi in the targetURL, and what I've observed at that URL since you posted the question. If you also want links for other types of legislation, the grepSearchPattern variable can be adjusted to accommodate.
Note: The example AppleScript code is just that and sans any included error handling does not contain any additional error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors.
I just published a Google Chrome extension which loads background images into new, empty tabs. The plugin is found here in the Chrome Web Store.
For detecting new and empty tabs, I need to ask for "tab" permissions in the extension's manifest.json. This, however, gives the extension the permission to read the browser's history. Not all users will want this and we don't actually need it. Is there a way to detect empty tabs without this permission requirement? Currently our check looks like this:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if (changeInfo.status == "loading" && tab.url == 'chrome://newtab/')
{ /* load background into tab */ }
});
If you want to customize the new tab page you should add this to your manifest:
"chrome_url_overrides": {
"newtab": "newtab.html"
}
Then place the script you are currently injecting into new tab pages as a <script> tag in the newtab.html file. That won't cause that permission message.
I'm developing a Firefox extension and need some help with it.
My extension is overlayed and uses XBL binding to add new items to the user interface.
Is it possible to convert this extension to a bootstrap type?
I'm trying to add a button to the findbar.
Used XBL to override the findbar interface.
To start with the bootstrap I included "findbar{ -moz-binding:... }" rule to the style.css and register this sheet on startup()
(with nsIStyleSheetService.loadAndRegisterSheet()).
In this case my button is added to the bar without restart.
But when I disable or remove the addon I need to restart the browser so that the button disappear.
I tried to remove it on shutdown() in the bootstrap.js using:
var fb=window.gFindBar.getElement("findbar-container")
var but=window.gFindBar.getElement("the-button")
fb.removeChild(but)
But this didn't remove it. I debugged the code and all the elements (fb, but) were found and removed but it didn't touch the real findbars in any tab I had or opened.
So I tried to unregister the stylesheet which bind my XBL to the findbar. This time the findbar just didn't open in the current tabs.
But in new tabs it opened and without the button (a little better...).
Also I've found that the findbar didn't open in the opened tabs because of a strange error:
"this.browser is undefined".
This error pointed to the findbar.xml line 533 where the code tried to run _unpdateCaseSensitivity() but it couldn't get the "gFindBar._browser" prorperty.
Maybe it's because this property wasn't loaded for the original findbar object from the browser start (it was used by the overriden findbar object)...
So this is the point I stuck on...
And the question now is:
How can I delete the button without restart and so that the findbar opens?
From the Findbar Tweak addon I extracted this method to add new checkbox to the findbar (and changed it for my needs):
var findbar=window.gFindBar
var container = findbar.getElement("findbar-container")
var button = $('<toolbarbutton>')
button.setAttribute('anonid', 'test-find-tabs')
button.setAttribute('label', 'Test')
button.setAttribute('type', 'checkbox')
button.addEventListener('command', test,false)
container.insertBefore(button, findbar.getElement('find-case-sensitive').nextSibling)
But for my final purpose it needs some additional editings. So for now I'll leave this problem. Maybe a wise thought will occur me later. Cause a good idea often comes in mind after we change the focus from the problem and then return to it...