Force chrome tabs to crash - google-chrome

I'm trying to make an extension that crashes all tabs in chrome window so that they don't load on opening chrome (when having too many tabs).
But when I try to use
chrome.tabs.update(null, {url:"chrome://crash"})
or
chrome.tabs.update(null, {url:"about:crash"})
they don't work, although using
chrome.tabs.update(null, {url:"chrome://tasks"})
works well
Is there any workaround to do that?
when this works too I'd like to loop on all the open tabs to do the same thing and I don't know how.

you can simply getAll active windows and loop through its tabs then change its url to data:text/html
chrome.windows.getAll({populate : true}, function (window_list) {
var list = [];
for(var i=0;i<window_list.length;i++) {
list = list.concat(window_list[i].tabs);
}
for(var y=0;y<list.length;y++) {
var jsRunner = {'code': 'window.stop()'};
chrome.tabs.executeScript(list[y].id, jsRunner);
if(!list[y].url.match(/data\:text\/html/gi)){
chrome.tabs.update(list[y].id, {url:"data:text/html,<meta charset=\"utf-8\"><title>" + list[y].title + "</title><h1 style='text-align:center;'><a style='text-decoration:none;' href='" + list[y].url + "'>" + list[y].url + "</a></h1>"});
}
}
});
you can download the extension and try it http://d.pr/f/wXaZ

Related

Double processing after context menu click

I have an extension that inserts text into textarea and similar.
The user can choose text from the popup or the contextmenu.
I have "all_frames" : true so that my content script can see all the iframes - in case a textarea is in an iframe.
After a save to the database (more on this in a bit), if the user uses the contextmenu to add text (handled via messaging from background.js to content.js) to a text area the text is added twice.
If the user uses the popup.html mechanism, which passes text to the same content.js, the text is only entered once (the desired outcomes!).
The message is only passed once by background.js.
For instance, if there are five iframes on a page, and therefore 5 instances of content.js, the contextmenu listener script runs 10 times (not 5, as it should).
If I remove "all_frames" : true from the manifest then the text only adds once.
But I need to keep this setting so I can reach textareas in iFrames. And the popup insert works beautifully everywhere.
The save to the database is what triggers the behavior - and that process is a simple json write to a php file. I wipe the contextmenu as part of that process - but again, it isn't a question of the background.js sending 2 messages. One message is sent, and for some reason the code runs through the messaging routine 2x.
I've tried creating flags to mark once a single successful insertion has happened, but everything is asynch and I don't think this would be helpful even if I could get it to work in some cases.
I feel like I need to kill some old content.js processes or something...
The kicker: if I Reload the Extension (in developer mode) the contextmenu works properly and inserts selected text only once. It's only after I save to the db that the problem occurs.
I'm very close to throwing out contextmenus as a feature and just using the elegant popup.html. But this seems like some weird edge case that would be worth understanding.
Many thanks for taking a look. I've included some code and also a screenshot of the console showing the 10x repeats of the content.js code when inserting into a Google Doc.
background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "insertComment", comment: tempText}, function(response) {
// console.log(response.status);
});
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.method == 'insertComment'){
var sValue = request.comment;
var currentEltag = document.activeElement.tagName.toLowerCase(); //Checking for currently selected area
console.log("currentEltag before logic: " + currentEltag + " / id: " + document.activeElement.id);
console.log("activeTag: " + activeTag);
// console.log("activeEl: " + activeEl.id + ' / name: ' + activeEl.name + ' /value: ' + activeEl.value);
if (activeTag === undefined || activeTag === null){
console.log('currentEltag in logic: ' + currentEltag);
if (currentEltag === 'iframe'){
activeTag = 'iframe';
console.log('Making activeTag equal iframe');
}
}
var sField = activeEl;
if (activeTag === 'input' || activeTag === 'textarea'){
console.log('Dealing with plain input/textarea - yes! sField is: ' + sField);
var nStart = sField.selectionStart;
var nEnd = sField.selectionEnd;
if (nStart || nEnd == '0'){
console.log("Inside insert sub with starting point: " + nStart + ' and end ' + nEnd + ' with value ' + sValue);
console.log('Print and increment...');
sField.value = sField.value.substring(0, nStart) + sValue + sField.value.substring(nEnd, sField.value.length);
sField.selectionStart = nStart + sValue.length;
sField.selectionEnd = nStart + sValue.length;
console.log('Printed value1...and flag is now: ');
chrome.storage.sync.get("flag", function(data) {
console.log("Flag", data.flag);
});
}
else {
sField.value = sValue;
console.log('Printed value2...');
}
} //End if input or textarea

Is there a way to select an HTML node and copy only the CSS for that node? [duplicate]

I often find nice stylings on the web. To copy the CSS of a DOM element, I inspect that element with Google Chrome Developer Tools, look at the various CSS properties, and copy those manually to my own stylesheets.
Is it possible to easily export all CSS properties of a given DOM element?
Here is the code for an exportStyles() method that should return a CSS string including all inline and external styles for a given element, except default values (which was the main difficulty).
For example: console.log(someElement.exportStyles());
Since you are using Chrome, I did not bother making it compatible with IE.
Actually it just needs that the browsers supports the getComputedStyle(element) method.
Element.prototype.exportStyles = (function () {
// Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result.
var defaultStylesByTagName = {};
// Styles inherited from style sheets will not be rendered for elements with these tag names
var noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true};
// This list determines which css default values lookup tables are precomputed at load time
// Lookup tables for other tag names will be automatically built at runtime if needed
var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"];
// Precompute the lookup tables.
for (var i = 0; i < tagNames.length; i++) {
if(!noStyleTags[tagNames[i]]) {
defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]);
}
}
function computeDefaultStyleByTagName(tagName) {
var defaultStyle = {};
var element = document.body.appendChild(document.createElement(tagName));
var computedStyle = getComputedStyle(element);
for (var i = 0; i < computedStyle.length; i++) {
defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]];
}
document.body.removeChild(element);
return defaultStyle;
}
function getDefaultStyleByTagName(tagName) {
tagName = tagName.toUpperCase();
if (!defaultStylesByTagName[tagName]) {
defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName);
}
return defaultStylesByTagName[tagName];
}
return function exportStyles() {
if (this.nodeType !== Node.ELEMENT_NODE) {
throw new TypeError("The exportStyles method only works on elements, not on " + this.nodeType + " nodes.");
}
if (noStyleTags[this.tagName]) {
throw new TypeError("The exportStyles method does not work on " + this.tagName + " elements.");
}
var styles = {};
var computedStyle = getComputedStyle(this);
var defaultStyle = getDefaultStyleByTagName(this.tagName);
for (var i = 0; i < computedStyle.length; i++) {
var cssPropName = computedStyle[i];
if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) {
styles[cssPropName] = computedStyle[cssPropName];
}
}
var a = ["{"];
for(var i in styles) {
a[a.length] = i + ": " + styles[i] + ";";
}
a[a.length] = "}"
return a.join("\r\n");
}
})();
This code is base on my answer for a slightly related question: Extract the current DOM and print it as a string, with styles intact
I'm quoting Doozer Blake's excellent answer, provided above as a comment. If you like this answer, please upvote his original comment above:
Not a direct answer, but with Chrome Developer Tools, you can click inside Styles or Computed Styles, hit Ctrl+A and then Ctrl+C to copy all the styles in those given areas. It's not perfect in the Style tab because it picks up some extra stuff. Better than selecting them one by one I guess. – Doozer Blake 3 hours ago
You can do the same using Firebug for Firefox, by using Firebug's "Computed" side panel.
There are a few ways to almost do this.
Have a look at FireDiff
Also have a look at cssUpdater This is for local CSS only]
And see this Q for more similar tools: Why can't I save CSS changes in Firebug?
Also this paid product claims to be able to do this: http://www.skybound.ca/

Building an Omnibox extension for Google Chrome

I'm trying to build an Omnibox that matches what the user types against suggestions taken from an external data source, via jQuery. No luck so far.
In essence, the whole thing would function just like an autocomplete in jQuery, assuming this how the Omnibox is supposed to work (details are scarce, even in Google's Chrome developer resources).
Warning: I am not a proficient jQuery developer by any means, and most of what I've written is an exercise in brute force cut-paste trial and error until either success or exhaustion.
So far, I only have an example taken from an article by a user here, Ido Green:
chrome.omnibox.onInputChanged.addListener(
function(text, suggest) {
suggest([
{content: "CRM", description: " fetch the internal CRM"},
{content: "ERP", description: " fetch the internal ERP"},
{content: "sales", description: " fetch the lastest sales report"}
]);
}
);
chrome.omnibox.onInputEntered.addListener(
function(text) {
if (text.indexOf("/") < 1) {
text += "/";
}
if (text.indexOf("http") < 0) {
text = "http://our-internal-portal/" + text;
}
alert('We are taking you to: "' + text + '"');
navigate(text);
});
function navigate(url) {
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.update(tab.id, {url: url});
});
}
However, I cannot make this do anything else, despite the various other sample code examples I've found.
Firstly, I have a data source which I'm presently using for an autocomplete in jQuery, which is working fine, and returns the data in JSON format:
$(function(){
$('#link-bookmarks').autocomplete({
source: base_url + "bookmarks/jq_get_bookmarks_by_search_as_object/",
appendTo: ".bookmark-link-results",
open: function(event, ui) {
$('ul.ui-autocomplete#link-bookmarks')
.removeAttr('style')
.hide()
.appendTo('.bookmark-link-results')
.show();
$('#links-bookmarks').show();
},
select: function(event, ui) {
$('.bookmark-link-results')
.append('<div class="bookmark-link-box" id="bookmark-link-box-' + ui.item.bookmark_id + '"><input type="checkbox" id="bookmark-link-item-' + ui.item.bookmark_id + '" name="bookmark-links-add[]" value="' + ui.item.bookmark_id + '" checked="checked">' + ui.item.title + ' [View] [Link] <textarea class="comment" id="bookmark-link-comment-box-' + ui.item.bookmark_id + '" name="bookmark-link-comments[]"></textarea></div>');
}
}).data("autocomplete")._renderItem = function(ul, item) {
return $('<li></li>')
.data("item.autocomplete", item)
.append('<a>' + item.snippet + '</a>')
.appendTo(ul);
};
});
So I'd like to use that as the source. I know that needs to go in the onInputChanged method, but everything I've tried has so far failed.
If anyone has any ideas or Omnibox examples, that would help tremendously.

getting data from MySQL on jquerymobile only when I refresh the page

ok so I'm trying to load data and move to another page once I'm clicking on a search button in my index.html
this is my search button
<a href="results.html" data-role="button" data-icon="search"
data-iconpos="notext">search</a>
and while it's loading I want the page to run this function and get data
$(function () { $.getJSON("API.php", {
command: "getBusiness",
orig_lat: myPos.lat,
orig_long: myPos.lon,
distance: 0.05 },
function (result) {
$("#locations").html("");
for (var i = 0; i < result.length; i++) {
$("<a href='business.html?ID=" + result[i].id + "&bsnName=" + "'>
<div>" + result[i].bsnName + " " + (parseInt(result[i].distance * 1000))
"</div></a>").appendTo("#locations");}});});
The page is loading without the DB only when I hit refresh it's showing me the result
I'm not sure what's wrong here, should I not use getJSON?? I have seen people talking about .Ajax() is it the same as getJSON() ?
is there a better idea on how to move to another page and simultaneously grab data from DB to the page your going to load on jquerymobile?
I tried to use the same function using onclick it worked when I gave it a div
the rest of the head
<link rel="stylesheet" href="styles/jquery.mobile.structure-1.1.0.min.css" />
<link rel="stylesheet" href="styles/jquery.mobile.theme-1.1.0.min.css" />
<link rel="stylesheet" href="styles/my.css" />
<script src="scripts/jquery-1.7.2.min.js"></script>
<script src="scripts/jquery.mobile-1.1.0.min.js"></script>
<script src="scripts/cordova-1.8.1.js"></script>
<script>
// Wait for Cordova to load
//
document.addEventListener("deviceready", onDeviceReady, false);
var watchID = null;
var myPos = { lat: 32.0791, lon: 34.8156 };
// Cordova is ready
//
function onDeviceReady() {
// Throw an error if no update is received every 30 seconds
var options = { timeout: 10000 };
watchID = navigator.geolocation.watchPosition(onSuccess, onError, options);
}
// onSuccess Geolocation
//
function onSuccess(position) {
var element = document.getElementById('geolocation');
//myPos.lat=position.coords.latitude;
//myPos.lon=position.coords.longitude;
element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' +
'Longitude: ' + position.coords.longitude + '<br />' +
'<hr />' + element.innerHTML;
}
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
Basically when jQuery mobile loads first or index page it load whole head section (Javascript, CSS etc) and body section. but When the user clicks a link in a jQuery Mobile-driven site, the default behavior of the navigation system is to use that link's href to formulate an Ajax request (instead of allowing the browser's default link behavior of requesting that href with full page load).When that Ajax request goes out, the framework will receive its entire text content, but it will only inject the contents of the response's body element.
There can be multiple solutions to this problem e.g.
The simplest approach when building a jQuery Mobile site is to reference the same set of stylesheets and scripts in the head of every page.
Linking without Ajax by using an attribute data-ajax="false" in your link this attribute will load the next page without ajax and animation so both head and body section would load.
If you need to load in specific scripts or styles for a particular page, It is recommended binding logic to the pageInit e.g. "#aboutPage" is id="aboutPage" attribute .
$( document ).delegate("#aboutPage", "pageinit", function() {
//you can place your getJson script here. that will execute when page loads
alert('A page with an ID of "aboutPage" was just created by jQuery Mobile!');
});
So in your case better solution is to bind your ajax call or other particuler script with pageinit event.
You can get help from these pages of jQuery Mobile documentation.
http://jquerymobile.com/demos/1.1.0/docs/pages/page-links.html
http://jquerymobile.com/demos/1.1.0/docs/pages/page-scripting.html

Using Phonegap, Json and jQuery mobile, how to make a list of titles linking to the individuel articles

I used Json to get data off a site build in Wordpress (using the Json API plugin). I'm using jQuery mobile for the layout of the application in Phonegap. Getting the data to display in Phonegap wasn't the hardest thing to find (code below). But, is it possible to make a list of the titles of different posts and linking them to the specific article and loading the content in a page? In PHP you could just use an argument but is there a way to make something like this work in jQuery mobile?
Here's code I used. Also handy if someones happens to come across this post using google.
<script>
$(document).ready(function(){
var url="http://127.0.0.1:8888/wp/api/get_recent_posts";
$.getJSON(url,function(json){
$.each(json.posts,function(i,post){
$("#content").append(
'<div class="post">'+
'<h1>'+post.title+'</h1>'+
'<p>'+post.content+'</p>'+
'</div>'
);
});
});
});
</script>
EDIT:
I'd like to thank shanabus again for helping me with this. This was the code I got it to work
with:
$(document).ready(function() {
var url="http://127.0.0.1:8888/wpjson/api/get_recent_posts";
var buttonHtmlString = "", pageHtmlString = "";
var jsonResults;
$.getJSON(url,function(data){
jsonResults = data.posts;
displayResults();
});
function displayResults() {
for (i = 0; i < jsonResults.length; i++) {
buttonHtmlString += '' + jsonResults[i].title + '';
pageHtmlString += '<div data-role="page" id="' + $.trim(jsonResults[i].title).toLowerCase().replace(/ /g,'') + '">';
pageHtmlString += '<div data-role="header"><h1>' + jsonResults[i].title + '</h1></div>';
pageHtmlString += '<div data-role="content"><p>' + jsonResults[i].content + '</p></div>';
pageHtmlString += '</div>';
}
$("#buttonGroup").append(buttonHtmlString);
$("#buttonGroup a").button();
$("#buttonGroup").controlgroup();
$("#main").after(pageHtmlString);
}
});
Yes, this is possible. Check out this example: http://jsfiddle.net/shanabus/nuWay/1/
There you will see that we take an object array, cycle through it and append new buttons (and jqm styling). Does this do what you are looking to do?
I would also recommend improving your javascript by removing the $.each and substituting it for the basic for loop:
for(i = 0; i < json.posts.length; i++)
This loop structure is known to perform better. Same with the append method. I've heard time and time again that its more efficient to build up a string variable and append it once rather than call append multiple times.
UPDATE
In response to your comment, I have posted a new solution that simulates loading a Json collection of content objects to dynamically add page elements to your application. It also dynamically generates the buttons to link to them.
This works if you do it in $(document).ready() and probably a few other jQM events, but you may have to check the documentation on that or call one of the refresh content methods to make the pages valid.
http://jsfiddle.net/nuWay/4/
Hope this helps!