Currently my chrome extension is displaying a paragraph (first one), but wanted to iterate all paragraphs in an HTML and display those.
chrome.tabs.query( {
active: true,
lastFocusedWindow: true
},
function(array_of_Tabs) {
chrome.tabs.executeScript(tab.id, {code: "chrome.runtime.sendMessage(document.getElementsByTagName('p')[0].innerHTML);"});
});
chrome.runtime.onMessage.addListener(function(request) {
document.getElementsByTagName('html')[0].innerHTML = request;
});
I wanted to add something like this in the above js. Pls advice.
let paragraphs = document.getElementsByTagName("p");
for(let i = 0; i < paragraphs.length; i++) {
console.log(paragraphs[i].innerText) // Will print the content of each paragraph
}
You can join all the innerHTML's and message that.
chrome.tabs.query({
active: true,
lastFocusedWindow: true
},
function(array_of_Tabs) {
chrome.tabs.executeScript(tab.id, {
code: `chrome.runtime.sendMessage([...document.getElementsByTagName('p')].reduce(function(agg, elem) {agg.push(elem.innerHTML); return agg; }, []).join("\n<br>"));`
});
});
chrome.runtime.onMessage.addListener(function(request) {
document.getElementsByTagName('html')[0].innerHTML = request;
});
Related
Here's a GIF demo, using a test extension.
I'm using this test extension to test out chrome.browserAction.setBadgeText(). I've noticed that when navigating, the badge text is flickering. All I am doing is clicking any hyperlinks on a webpage, so there's no page refreshing, nor navigating Back.
Is there a way to keep it from flickering? If not, is there a way to keep it persistent for as long as possible?
Code in question:
var SetBadge = function () {
chrome.windows.getCurrent({
populate: true
}, function (win) {
for (let i = 0; i < win.tabs.length; ++i) {
if (win.tabs[i].active) {
chrome.browserAction.setBadgeText({
text: "8",
tabId: win.tabs[i].id
});
}
}
});
};
chrome.webNavigation.onCommitted.addListener(() => {
SetBadge();
});
chrome.webRequest.onSendHeaders.addListener(() => {
SetBadge();
});
chrome.webRequest.onBeforeRedirect.addListener(() => {
SetBadge();
});
chrome.tabs.onActivated.addListener(() => {
SetBadge();
});
chrome.webRequest.onCompleted.addListener(() => {
SetBadge();
});
This is an extract of my plugin (full version):
CKEDITOR.plugins.add('dndck4', {
lang: 'en',
requires: 'widget',
init: function (editor) {
editor.widgets.add('dndck4', {
dialog: 'atomProperties',
pathName: 'atom',
editables: {
caption: {
selector: '.dnd-caption-wrapper',
pathName: 'caption',
allowedContent: 'a[href]; strong; em'
}
},
...
downcast: function(el) {
var caption = '';
if (this.data.usesCaption) {
caption = this.editables.caption.getHtml();
}
var html = Drupal.dndck4.downcastedHtml(this.data, caption);
return CKEDITOR.htmlParser.fragment.fromHtml(html);
},
It worked well, until another JS does something apparently harmless:
editor.on('change', function() {
// Let CKEditor handle updating the linked text element.
editor.updateElement();
});
It breaks my widget based plugin (this.editables is an empty object). Of course I can just check this.editables to avoid error in the next line caption = this.editables.caption.getHtml(); but I'd like to know what happened and why.
I am doing an app that store some data in the IndexedDB, but I want to load first some data that is in my json file.
Here is my json file:
{
"ciudades":[
{
"ciudad":"Asuncion",
"latitud":-25.2985296,
"longitud":-57.6710677
},
{
"ciudad":"Caaguazu",
"latitud":-25.465034,
"longitud":-56.0183859
},
{
"ciudad":"Ciudad del Este",
"latitud":-25.4933441,
"longitud":-54.6710438
},
{
"ciudad":"San Pedro",
"latitud":-24.1586759,
"longitud":-56.636503
},
{
"ciudad":"Pedro Juan Caballero",
"latitud":-22.5450875,
"longitud":-55.7618963
}
]
}
you follow step
step 1 read mozilla site
step 2 create indexedDB
var ciudades = [
{
"ciudad":"Asuncion",
"latitud":-25.2985296,
"longitud":-57.6710677
},
{
"ciudad":"Caaguazu",
"latitud":-25.465034,
"longitud":-56.0183859
},
{
"ciudad":"Ciudad del Este",
"latitud":-25.4933441,
"longitud":-54.6710438
},
{
"ciudad":"San Pedro",
"latitud":-24.1586759,
"longitud":-56.636503
},
{
"ciudad":"Pedro Juan Caballero",
"latitud":-22.5450875,
"longitud":-55.7618963
}
];
var IDBSetting = {
name: "indexedDBName",
version: 1,
tables: [{
tableName: "ciudades",
keyPath: "seq",
autoIncrement: true,
index: ["ciudad", "latitud", "longitud],
unique: [false, false, false]
}]
};
! function() {
console.log("indexeDB init");
var req = indexedDB.open(IDBSetting.name, IDBSetting.version);
req.onsuccess = function(event) {
console.log("indexedDB open success");
};
req.onerror = function(event) {
console.log("indexed DB open fail");
};
//callback run init or versionUp
req.onupgradeneeded = function(event) {
console.log("init onupgradeneeded indexedDB ");
var db = event.target.result;
for (var i in IDBSetting.tables) {
var OS = db.createObjectStore(IDBSetting.tables[i].tableName, {
keyPath: IDBSetting.tables[i].keyPath,
autoIncrement: IDBSetting.tables[i].autoIncrement
});
for (var j in IDBSetting.tables[i].index) {
OS.createIndex(IDBSetting.tables[i].index[j], IDBSetting.tables[i].index[j], {
unique: IDBSetting.tables[i].unique[j]
});
}
}
}
}();
step 3 addData
var IDBFuncSet = {
//write
addData: function(table, data) {
var req = indexedDB.open(IDBSetting.name, IDBSetting.version);
req.onsuccess = function(event) {
try {
console.log("addData indexedDB open success");
var db = req.result;
var transaction = db.transaction([table], "readwrite");
var objectStore = transaction.objectStore(table);
var objectStoreRequest = objectStore.add(data);
} catch (e) {
console.log("addDataFunction table or data null error");
console.log(e);
}
objectStoreRequest.onsuccess = function(event) {
//console.log("Call data Insert success");
}
objectStoreRequest.onerror = function(event) {
console.log("addData error");
}
};
req.onerror = function(event) {
console.log("addData indexed DB open fail");
};
}
}
for(var i in ciudades){
IDBFuncSet.addData("ciudades",ciudades[i]);
}
step 4 getData
IDBFuncSet.getAllData = function(arr, table) {
try {
var req = indexedDB.open(IDBSetting.name, IDBSetting.version);
req.onsuccess = function(event) {
var db = req.result;
var transaction = db.transaction([table], "readonly");
var objectStore = transaction.objectStore(table);
var objectStoreRequest = objectStore.openCursor();
objectStoreRequest.onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
arr.push(cursor.value);
cursor.continue();
} else {
}
}
};
req.onerror = function(event) {
console.log("getAllData indexed DB open fail");
};
} catch (e) {
console.log(e);
}
}
var ciudadesArr = [];
IDBFuncSet.getAllData(ciudadesArr, "ciudades");
console.log(ciudadesArr);
I hope this helps
Here's how I've done mine, thanks to the android-indexeddb package.
angular.module('yourApp', ['indexedDB'])
.config(function($indexedDBProvider) {
$indexedDBProvider
.connection('dbName')
.upgradeDatabase(1, function(event, db, tx) {
var objStore = db.createObjectStore('storeOne', { keyPath: 'stop_id' });
objStore.createIndex('store_id', 'store_id', { unique: false });
})
// the next upgradeDatabase() function is necessary if you
// wish to create another datastore
.upgradeDatabase(2, function(event, db, tx) {
var secondObjectStore = db.createObjectStore('storeTwo', { keyPath: 'my_id' });
secondObjectStore.createIndex('another_id', 'another_id', { unique: false });
});
})
Then in my controller:
angular.module('yourApp')
.controller('homeCtrl', ['$scope', '$http', '$indexedDB', function($scope, $http, $indexedDB) {
$scope.objects = [];
var loadJSON = function(file_name) { ... //load the json file in here}
$indexedDB.openStore('storeOne', function(store) {
var loaded = loadJSON('file_name.json');
store.upsert(loaded).then(function(e) {
console.log('added successfully');
});
});
$indexedDB.openStore('times', function(store) {
var loaded = loadJSON('file_name.json');
store.upsert(loaded).then(function(e) {
console.log('added successfully');
});
});
}]);
Check out the project page to learn more of the tricks up this package's sleeves.
Although this angular-indexeddb page supports queries, for advanced queries like joins, you might wanna consider ydn-db
Getting some pretty nice workflow with both packages.
For the loadJSON() function, it could be something like this:
var loadJSON = function(file_name) {
var data;
$.ajax({
url: '../data/' + file_name,
dataType: 'json',
async: false,
success: function(res_data) {
data = res_data;
console.log('Loaded ' + file_name + ' nicely');
},
error: function(err) {
console.log('error happened');
}
});
return data;
}
There is File API, but that doesn't seem to be a solid standard yet.
What I do at the moment, is have the user open the file, copy it's contents to Clipboard, and paste it into a TextArea element on my web page.
In JavaScript I add a listener to the TextArea's change event and parse the text content into JSON, which is then written to indexedDB.
Okay, im going slightly insane trying to display data from a json file in 2 seperate views/collections.
I will paste my entire code here and try to explain where i am now, and what i need done.
Its probably a very small thing i just need to do in order for it to work, but i cant see it..
Here is a screen shot of how my page looks like now, as you can see the data is being loaded, i just cant get it into the views properly..
In my Collection class i call parse:
parse:function(response, options) {
return options.parseField ? response[options.parseField] : response;
},
i call sync: (not sure its needed at all)
sync: function(method, model, options) {
options.contentType = "application/json";
options.cache = false;
options.dataType = "json";
return Backbone.sync(method, model, options);
},
Then near the bottom, i create 2 new collections and use fetch to get the specific json data i need for each collection like so:
var links = new App.Collections.Links();
links.fetch({
parseField: 'links_1',
success: function () {
console.log(links.toJSON());
return links.toJSON();
}
});
var links2 = new App.Collections.Links();
links2.fetch({
parseField: 'links_2',
success: function () {
console.log(links2.toJSON());
return links2.toJSON();
}
});
I do console.log and can see that my json data is getting loaded just fine, but its not getting rendered ?
What am i doing wrong here..
For sake of debugging and understanding i have included my entire js file below.
(function() {
// Helper functions
// Defining namespacing rules
window.App = {
Models: {},
Collections: {},
Views: {}
};
// Setting global template function, for simpel declaration later on by setting template('name'); for the built in template function.
window.template = function(id) {
return _.template( $('.' + id).html() );
};
// Capitalize first letter in a link by adding .capitalize(); to the string.
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
};
// Extending Backbone
//Modellen
App.Models.Link = Backbone.Model.extend({
defaults: {
navn : 'i haz a name!',
link : 'http://www.lolcats.com/',
counter : 0
}
});
//Collection
App.Collections.Links = Backbone.Collection.extend({
model: App.Models.Link,
url: 'data1.json',
parse:function(response, options) {
return options.parseField ? response[options.parseField] : response;
},
sync: function(method, model, options) {
options.contentType = "application/json";
options.cache = false;
options.dataType = "json";
return Backbone.sync(method, model, options);
},
// Sort the models 'highest first'
comparator: function(link) {
return -link.get('counter');
}
});
//Singel view
App.Views.LinkView = Backbone.View.extend({
tagnavn: 'li',
template: template('Links'),
initialize: function() {
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this);
},
events: {
'click .edit' : 'retLink',
'click .delete' : 'destroy',
'click .LinkUrl' : 'addCounter'
},
retLink: function() {
var newLinkNavn = prompt('What should the new name be?', this.model.get('navn'));
if ( !newLinkNavn ) return;
newLinkNavn = newLinkNavn.capitalize();
this.model.set('navn', newLinkNavn);
var newLinkUrl = prompt('What should the new url be?', this.model.get('link'));
if ( !newLinkUrl ) return;
this.model.set('link', newLinkUrl);
},
destroy: function() {
this.model.destroy();
},
// Increment the counter then user clicks it
addCounter: function(e) {
e.preventDefault();
var newCounter = this.model.get('counter');
this.model.set('counter', newCounter + 1);
},
remove: function() {
this.$el.remove();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()) );
return this;
}
});
//Collection View
App.Views.LinksView = Backbone.View.extend({
tagName: 'ul',
className: 'liste',
initialize: function() {
_.bindAll(this);
this.collection.on('add', this.addOne, this);
this.collection.on('reset', this.render);
// Render view when a user has changed a model
this.collection.bind('change', this.render, this);
$('.navnClass').focus();
this.load();
this.render();
},
load: function() {
this.collection.fetch({
add: true,
success: this.loadCompleteHandler,
error: this.errorHandler
});
},
loadCompleteHandler : function(){
this.render();
},
errorHandler : function(){
throw "Error loading JSON file";
},
render: function() {
// Empty the UL before populating it with the new models and sorting it.
this.$el.empty();
this.collection.sort();
this.collection.each(this.addOne, this);
return this;
},
addOne: function(link) {
var linkView = new App.Views.LinkView({ model: link });
this.$el.append(linkView.render().el);
}
});
// Create link view
App.Views.AddLink = Backbone.View.extend({
el: '#addLink',
events: {
'submit' : 'submit'
},
submit: function(e) {
e.preventDefault();
var linkNavn = $(e.currentTarget).find('.navnClass').val(),
linkNum = $(e.currentTarget).find('.linkClass').val();
// Tildel link navn en værdi, hvis det er tomt
if ( ! $.trim(linkNavn)) {
linkNavn = 'I haz a name!';
}
// Tildel link url en værdi, hvis det er tomt
if( ! $.trim(linkNum)) {
linkNum = 'http://www.lolcats.com/';
}
// Tilføj http:// foran værdi, hvis den ikke indeholder det i forvejen.
if( linkNum.indexOf( "http://" ) == -1 ) {
addedValue = 'http://',
linkNum = addedValue + linkNum;
}
// nulstil og sæt fokus på link navn feltet.
$(e.currentTarget).find('.navnClass').val('').focus();
$(e.currentTarget).find('.linkClass').val('');
this.collection.add({ navn:linkNavn, link: linkNum });
}
});
// new links collection
// populate collection from external JSON file
// change navn to match the link heading
var links = new App.Collections.Links();
links.fetch({
parseField: 'links_1',
success: function () {
console.log(links.toJSON());
return links.toJSON();
}
});
var links2 = new App.Collections.Links();
links2.fetch({
parseField: 'links_2',
success: function () {
console.log(links2.toJSON());
return links2.toJSON();
}
});
// new collection view (add)
var addLinkView = new App.Views.AddLink({ collection: links });
// new collection view
var linksView = new App.Views.LinksView({ collection: links });
$('.links').html(linksView.el);
// new collection view
var linksView2 = new App.Views.LinksView({ collection: links2 });
$('.links2').html(linksView2.el);
})();
Could you try this:
var links2 = new App.Collections.Links();
links2.on("reset", function(collection){
console.log("reset event", collection);
}
links2.fetch({
parseField: 'links_2',
wait:true, #wait for the server to respond
success: function (collection, response) {
console.log(collection, response);
}
});
a return in the success call doesn't do anything (it would return to the $.ajax object). I've added a wait because it would call the successcall instantly if it passes the clientside validation (you have none, so it would always call success first).
You say it doesn't render anything. But to render something you need a View. I don't see a view in your code.
Here's a quick example of the view:
var Link = new Backbone.View.extends({
el: $('body'),
initialize: function(){
this.listenTo(this.collection, 'reset', this.render, this)
},
render: function(){
this.$el.empty();
this.collection.each(function(item){
this.$el.append(item.get('id') + '<br />');
});
}
})
var view = new Link({collection: links2});
All,
I've moved on to using the ui autocomplete rather than the plugin, took me a while to figure out extra params based on an example I found here, but that part works.
I'm having problems with dealing with the return data. In the code below I can alert out the title being returned, but I get a drop down of 'UNDEFINED' in the browser.
Thanks in advance.
$('#DocTitle').autocomplete({
source: function(request, response) {
$.ajax({
url: "index.pl",
dataType: "json",
data: {
Title: request.term,
maxRows: 10
},
success: function(data) {
response($.map(data, function(item) {
alert(item.TITLE);
return {
TITLE: item.TITLE
}
}))
}
})
}
});
I am using jquery UI autocomplete as follows and it is working quite fine for me. You may try on the similar lines.
$('input[type=text][name=City]').autocomplete({
source: function(request, response) {
$.getJSON($('input#CitySuggestionsLink').val(), {
term: request.term,
stateId: $('select#StateName option:selected').attr('value')
}, response);
},
search: function() {
// custom minLength
var term = this.value;
if (term.length < 1) {
return false;
}
},
delay: 200,
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
return false;
}
});