The document.body.innerHTML.replace() replaces the url in the address bar - firefox-addon

I am trying to make an extension as part of which i want certain words in the web pages to be highlighted. The document.body.innerHTML.replace() replaces the url in the address bar as well. So the moment this code gets exwecuted the page doesnt get loaded properly..
Is there a way around this problem?
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget;
var str="the";
var regex;
var regex = new RegExp(str, "g");
doc.body.innerHTML = doc.body.innerHTML.replace(regex,'<b>'+str+'</b>');
}
The listener is registered as follows in a browser.xul overlay:
window.addEventListener("load", function() {
myExtension.init();
}, false);
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, false);
},

onPageLoad: function(aEvent) {
if(aEvent.originalTarget.nodeName=="#document"){
var doc = aEvent.originalTarget;
var str="the";
var regex;
var regex = new RegExp(str, "g");
doc.body.innerHTML = doc.body.innerHTML.replace(regex,'<b>'+str+'</b>');
}
}
The if condition in the function happens to do the trick..
:)

Related

indexeddb on IOS devices

I have a problem with an indexeddb query with index when running on IOS devices.
$.indexedDB(dbName).objectStore(tablename).index("INDICE").each(function(itemLocal) {
itemLocal.delete();
}, [VALORINDICE]).then(function() {
callback();
}, function() {
console.log("error");
});
The problem is if there is more than one record that matches the index, it does not eliminate them, it eliminates the first one and leaves. But if for example I put console.log (itemLocal) instead of itemLocal.delete() if it shows all those that match the index. Any suggestions of something that may be leaking?
I have tried with this code and I get the same error(code without api jquery)
var request = indexedDB.open(DATABASE_NAME);
request.onsuccess = function(event) {
var db = request.result;
var transaction = db.transaction(["TABLE"], "readwrite");
var table = transaction.objectStore("TABLE");
var index = table.index("INDEX");
var req = index.openCursor();
req.onsuccess = function() {
var cursor = req.result;
if (cursor) {
console.info(cursor.value);
cursor["delete"]();
cursor["continue"]();
}
};
req.onerror = function(e) {
console.error(e, req);
};
};
request.onerror = function(e) {
console.error(e, request);
};

OpenUI5: Where is the data gone, loaded by sap.ui.model.odata.v2.ODataModel()?

I have been googling and testing around for quite a few days with no success. If someone could give me a hint to point me into the right direction, then I would greatly appreciate that.
What is my target: to get some data from an OData service and show it in an UI5 oTable. Later on, I will have to do the CRUD-operations, but for now the aim is just to show the data successfully.
What I have got so far: I have an MVC project. I have created an OpenUI5Controller.cs, whose purpose is to represent an ODataService:
public class OpenUI5Controller : Controller
{
private MyEntities myEntities = new MyEntities();
public JsonResult GetAllContragents()
{
try
{
IQueryable<Contragent> contragents = myEntities.Contragent.OrderBy(x => x.Code);
// for now, take the first 100 only
contragents = contragents.Take(100);
var jsonData = new
{
rows = contragents.ToList()
//rows = "123"
};
var res = Json(jsonData, JsonRequestBehavior.AllowGet);
return res;
}
catch (Exception e)
{
LoggingService.WriteLog("Error in OpenUI5Controller.GetAllContragents()", e);
return null;
}
}
}
After that, I try to consume the data like this:
var oModel = new sap.ui.model.odata.v2.ODataModel('/OpenUI5/GetAllContragents', {
//maxDataServiceVersion: '2.0',
json: true,
skipMetadataAnnotationParsing: true,
// none of those callbacks is ever triggered, even the requestFailed...!?
requestSent: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
requestFailed: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
requestCompleted: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
batchRequestCompleted: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
useBatch : false
});
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
var vfewgvfewgv4 = oModel.getProperty('contragents');
var vfewgvfewgv5 = oModel.getProperty('/contragents');
var vfewgvfewgv6 = oModel.getProperty('Contragents');
var vfewgvfewgv7 = oModel.getProperty('/Contragents');
debugger;
When stopping at this breakpoint, I see this in the Chrome Developer Tools:
Moving further, I came accross this and tried to read() those contragents:
oModel.read('/Contragents', {
success: function (event) {
debugger;
// event.root I guess should be the received data as jsonString
// As I guess, I will have to get it and give it to oModel.oData manually, or am I wrong? I guess this would cause update(), delete()... calls to fail later on. Anyways...
sap.ui.getCore().setModel(oModel); // https://archive.sap.com/discussions/thread/3746588 - seems not to work like this
if (withJsonModel !== true) { https://help.sap.com/saphelp_uiaddon20/helpdata/en/12/32241b99d7437ba3614698d53dfa4b/content.htm
oTable.setModel(oModel);
oTable.bindRows("/");
//oTable.bindRows("/rows");
oTable.placeAt('tblContragents', "only");
}
},
error: function (event) {
debugger;
}
});
Here, neither success, nor error callback gets ever triggered.
After this read() attempt, I have again:
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
var vfewgvfewgv4 = oModel.getProperty('contragents');
var vfewgvfewgv5 = oModel.getProperty('/contragents');
var vfewgvfewgv6 = oModel.getProperty('Contragents');
var vfewgvfewgv7 = oModel.getProperty('/Contragents');
and I see this:
After that, I have oTable = new sap.ui.table.Table(...);
Finally, I try this:
sap.ui.getCore().setModel(oModel);
//oTable.setModel(oModel); // or maybe should be this one directly?
oTable.bindRows("/Contragents");
oTable.placeAt('tblContragents', "only");
As a result, I get an empty table.
I suppose I should tell you what I see in Fiddler as well: I see this request: 1 200 HTTP localhost:55714 /OpenUI5/GetAllContragents/$metadata
As a result in the TextView of the response section, I see the data as json, that I need to show in the table.
How to make it work and show the data in the table?
edit from 02.02.2017: I have 1% of progress. After some more and more testing and googling, I decided to try it like this.
First of all, some time ago (can't really remember when), after seeing a good example for OdataServices, I decided to create a dedicated controller like this:
public class ContragentsController : ODataController
{
private MyEntities db = new MyEntities();
//public System.Web.Mvc.JsonResult GetContragents()
public string GetContragents()
{
try
{
IQueryable<Contragent> contragents = db.Contragent.OrderBy(x => x.Code);
// for now, give me first 100
contragents = contragents.Take(100);
var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var rows = jsSerializer.Serialize(contragents.ToList());
//var jsonData = new
//{
// rows = model
//};
//var res = new System.Web.Mvc.JsonResult();
//res.Data = jsonData;
//res.JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet;
return rows;
}
catch (Exception e)
{
//...some errorLogging
return null;
}
}
After that, I changed the call to ODataModel() like this:
var oModel = new sap.ui.model.odata.v2.ODataModel(BASE_HREF + 'odata/', {
//maxDataServiceVersion: '2.0',
json: true,
skipMetadataAnnotationParsing: true,
// those callbacks still do not get called at all
requestSent: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
requestFailed: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
requestCompleted: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
batchRequestCompleted: function (a, b, c) {
debugger;
var trgrwg = oModel.getData();
var vfewgvfewgv = oModel.getProperty('/');
var vfewgvfewgv2 = oModel.getProperty('/rows');
var vfewgvfewgv3 = oModel.getProperty('rows');
},
useBatch : false
});
The whole drama is that SapUI5 runs a request for $metadata, before making the actual request to odata/Contragents and so on. As expected in this case, I see in Fiddler, that the server 404-s to that request: http://localhost:55714/odata/Contragents/$metadata and it doesn't reach the moment to make the request to Contragents. I know, that I will have to change the source of the library somewhere in order to prevent this $metadata request from running, which I don't want to do. So in Fiddler's Composer, I tried the following: localhost:55714/odata/$metadata and it returned some xml with the desired metadata (maybe indeed it is important, but I haven't understood yet why). Next step was to modify the call to sap.ui.model.odata.v2.ODataModel(); as shown above. The great thing after all that is the fact, that oModel.read('/Contragents', {...}); showed signs of life! Now, the success callback gets called and in event.root I get those contragents as json string. And then what? I tried oModel.setData(JSON.parse(event.root)); but it gave me this error:
Also, if I manage to get it working this way, I don't quite understand, will the CRUD methods of oModel work? oModel.setData()-ing is something familliar to me from the time when I was playing around with JSONModel():
oModel = new sap.ui.model.json.JSONModel();
oModel.setData(dataForGrid); // this works like a charm
But using JSONModel() means, that I cannot use the insert(), update()... methods of sap.ui.model.odata.v2.ODataModel(), because JSONModel(); does not provide us with them, which is normal, as long as I get dataForGrid via a standard $.ajax() call.
edit2: While debugging, I noticed, that the method ContragentsController.GetContragents(); gets called twice and in the console, I see this error message:
edit3: Following the good example for ODataService, I added a "selection" method to the controller like this:
// GET: odata/Contragents(5)
[EnableQuery]
public SingleResult<Contragent> GetContragents([FromODataUri] string key)
{
return SingleResult.Create(db.Contragent.Where(contragent => contragent.Code == key));
}
In Fiddler, it 404-s and does not get called at all no matter if i Compose it like this: http://localhost:55714/Contragents(2) or like this: http://localhost:55714/odata/Contragents(2)
Couple of minutes later, I've got couple of % progress. I looked even closer in the tutorial and I noticed something, which made me change the "selection" method to this:
// GET: odata/Contragents(5)
[EnableQuery]
public SingleResult<Contragent> Get([FromODataUri] string key)
{
return SingleResult.Create(db.Contragent.Where(contragent => contragent.Code == key));
}
Now, when I Compose this request: http://localhost:55714/odata/Contragents(2), it now does not 404, but does 406 Not Acceptable. I came across this error code some time ago and I didn't understand well what is the reason for it and how is it related to ODataServices.
I just reminded myself what does 406 mean and it turns out, that every method on the controller must return a json result as string. Because, SapUI5 sets Accept-Type to "application/json".

addEventListener error in IE8

I'm getting an error message in ie8: Object doesn't support property or method 'addEventListener'. How can I fix this? I've seen adding an else statementand changing addEventListener to attachEvent. However, I am a bit green in the land of js and not sure where that should go, I did try a few ways.
$(document).ready(function() {
// Off canvas menu
var $slider = document.querySelector('#slider');
var $toggle = document.querySelector('.toggle-nav');
var $toggle2 = document.querySelector('nav .toggle-nav');
// var $link = document.querySelector('.link > a');
$toggle.addEventListener('click', function() {
var isOpen = $slider.classList.contains('slide-in');
$slider.setAttribute('class', isOpen ? 'slide-out' : 'slide-in');
$('#slider').animate({'right': '100%'}, 400);
});
$toggle2.addEventListener('click', function() {
var isOpen = $slider.classList.contains('slide-in');
$slider.setAttribute('class', isOpen ? 'slide-out' : 'slide-in');
$('#slider').animate({'right': '0'}, 300);
});
var toggleDataAttr = function(parentElem, toggleElem, opt1, opt2, dataAttr) {
var toggleElem = parentElem.querySelector(toggleElem);
toggleElem.setAttribute(dataAttr, toggleElem.getAttribute(dataAttr) === opt1 ? opt2 : opt1);
};
var toggle_li = document.querySelectorAll('li');
for (var i = 0; i < toggle_li.length; i++) {
toggle_li[i].onclick = function() {
toggleDataAttr(this, '.toggleContent', 'closed', 'open', 'data-state');
toggleDataAttr(this, '.toggleIcon', 'down', 'up', 'data-icon');
};
}
});
addEventListener() is not supported in IE8 and lower (more info here: http://www.w3schools.com/jsref/met_document_addeventlistener.asp), instead you need to use attachEvent() in these browsers.
You can use it like this:
if(element.addEventListener()) {
element.addEventListener('click', myFunction(), true);
} else if(element.attachEvent()) {
element.attachEvent('click', myFunction());
}
This way to do it makes it multi-browser compatible.

How to create multiple instances of IIFE Javascript module?

I'm dealing with a huge javascript codebase that I'm trying to reorganize. I'm not really an expert and I just started studying good javascript coding practices. So, one thing I'm trying to do is to divide all the code in modules. In this particular case I'm trying to create a module that would help me to optimize video embeds. I would like to pass the module an id and receive some html code or an image out of it.
I'm not putting the whole code here, but it's enough for the example:
var videoIframe = (function($) {
'use strict';
var id,
setVideoId = function(videoId) {
id = videoId;
console.log(id);
},
getVideoThumbnail = function(videoId) {
setVideoId(videoId);
},
test = function() {
console.log(id)
},
getVideoEmbedCode = function() {
};
return {
test: test,
getVideoThumbnail: getVideoThumbnail
};
})(jQuery);
In another module I assign it to two variables:
var video1 = videoIframe;
var video2 = videoIframe;
video1.getVideoThumbnail(123);
video2.getVideoThumbnail(456);
video1.test();
video2.test();
And, of course, I'm not getting what I expected. After the second getVideoThumbnail call, it always prints 456.
Doing some research I understood that I'm creating a singleton, a single instance, and I'm only changing values inside that instance. I think I need a constructor for my module, but I'm not sure how to create it in combination with the IIFE pattern. And is it the right approach?
And is it the right approach?
No. IIFEs are for things you want to do exactly once.
If you want to do something multiple times, then use a regular function and call it multiple times.
var videoIframe = (function($) {
function videoIframe() {
'use strict';
var id,
setVideoId = function(videoId) {
id = videoId;
console.log(id);
},
getVideoThumbnail = function(videoId) {
setVideoId(videoId);
},
test = function() {
console.log(id)
},
getVideoEmbedCode = function() {
};
return {
test: test,
getVideoThumbnail: getVideoThumbnail
};
}
return videoIframe;
})(jQuery);
var video1 = videoIframe();
var video2 = videoIframe();
video1.getVideoThumbnail(123);
video2.getVideoThumbnail(456);
video1.test();
video2.test();
The problem is that you are initializing object when assigning to videoIframe variable:
var videoIframe = (function($) {
// ...
})(jQuery);
You can try with:
var videoIframe = (function($) {
// ...
});
var video1 = videoIframe(jQuery);
var video2 = videoIframe(jQuery);
Just keep videoIframe as a function that returns your IIFE, instead of reusing the singleton. I kept the IIFE so the id and the inner functions keep being encapsulated and hence, not reachable if they're not in the returned interface object. If you are planning to create alot of these, it might be more efficient to just use a constructor and a prototype, so the inner functions don't get recreated for every instance.
var videoIframe = function() {
'use strict';
return (function() {
var id,
setVideoId = function(videoId) {
id = videoId;
console.log(id);
},
getVideoThumbnail = function(videoId) {
setVideoId(videoId);
},
test = function() {
console.log(id)
},
getVideoEmbedCode = function() {
};
return {
test: test,
getVideoThumbnail: getVideoThumbnail
};
}());
};
I did some minor modification. Hope it will be helpful
var videoIframe = (function($) {
'use strict';
var id;
function _setVideoId(videoId) {
id = videoId;
alert(id);
};
function _getVideoThumbnail(videoId) {
_setVideoId(videoId);
};
function _test(){
console.log(id)
}
function _getVideoEmbedCode() {
};
return {
test: _test,
getVideoThumbnail: _getVideoThumbnail
};
})(jQuery);
Now you can call like this
videoIframe.getVideoThumbnail(123);
videoIframe.getVideoThumbnail(561);
jsfiddle

An observer for page loads in a custom xul:browser

In my firefox extension I'm creating a xul:browser element. I want to have an observer that intercepts any url changes within the embedded browser and opens the url in a new browser tab (in the main browser). I'd also like new windows spawned by the xul:browser window to open in a tab instead of a new browser window.
I've created an observer which works, but I don't yet know how to apply that observer only to the xul:browser element.
function myFunction(){
var container = jQuery("#container")[0];
var new_browser_element = document.createElement('browser');
container.appendChild(new_browser_element);
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.addObserver(myObserver, "http-on-modify-request", false);
}
var myObserver = {
observe: function(aSubject, aTopic, aData){
if (aTopic != 'http-on-modify-request'){
aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
// alert(aSubject.URI.spec);
// Now open url in new tab
}
},
QueryInterface: function(iid){
if (!iid.equals(Components.interfaces.nsISupports) &&
!iid.equals(Components.interfaces.nsIObserver))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
}
};
You could try:
var myObserver = {
observe: function(aSubject, aTopic, aData){
if (aTopic == 'http-on-modify-request')
{
aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
var url = aSubject.URI.spec;
var postData ;
if (aSubject.requestMethod.toLowerCase() == "post")
{
var postText = this.readPostTextFromRequest(request);
if (postText)
{
var dataString = parseQuery(postText);
postData = postDataFromString(dataString);
}
}
var oHttp = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
var interfaceRequestor = oHttp.notificationCallbacks.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow);
//check if it is one of your mini browser windows
if (jQuery(DOMWindow).hasClass('mini_browser'))
{
openInTab(url, postData);
var request = aSubject.QueryInterface(Components.interfaces.nsIRequest);
request.cancel(Components.results.NS_BINDING_ABORTED);
}
}
},
QueryInterface: function(iid){
if (!iid.equals(Components.interfaces.nsISupports) &&
!iid.equals(Components.interfaces.nsIObserver))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
readPostTextFromRequest : function(request) {
var is = request.QueryInterface(Components.interfaces.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Components.interfaces.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
// Seek locks the file so, seek to the beginning only if necko hasn't read it yet,
// since necko doesn't seek to 0 before reading (at lest not till 459384 is fixed).
if (ss && prevOffset == 0)
ss.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
dump("Failed to Query Interface for upload stream.\n");
}
}
return null;
},
readFromStream : function(stream, charset, noClose)
{
var sis = Components.classes["#mozilla.org/binaryinputstream;1"]
.getService(Components.interfaces.nsIBinaryInputStream);
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
};
function openInTab(url, postData)
{
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var recentWindow = wm.getMostRecentWindow("navigator:browser");
if (recentWindow)
{
// Use an existing browser window, open tab and "select" it
recentWindow.gBrowser.selectedTab = recentWindow.gBrowser.addTab(url, null, null, postData);
}
}
function parseQuery() {
var qry = this;
var rex = /[?&]?([^=]+)(?:=([^&#]*))?/g;
var qmatch, key;
var paramValues = {};
// parse querystring storing key/values in the ParamValues associative array
while (qmatch = rex.exec(qry)) {
key = decodeURIComponent(qmatch[1]);// get decoded key
val = decodeURIComponent(qmatch[2]);// get decoded value
paramValues[key] = val;
}
return paramValues;
}
function postDataFromString(dataString)
{
// POST method requests must wrap the encoded text in a MIME
// stream
var stringStream = Components.classes["#mozilla.org/io/string-input-stream;1"]
.createInstance(Components.interfaces.nsIStringInputStream);
if ("data" in stringStream) // Gecko 1.9 or newer
stringStream.data = dataString;
else // 1.8 or older
stringStream.setData(dataString, dataString.length);
var postData = Components.classes["#mozilla.org/network/mime-input-stream;1"].
createInstance(Components.interfaces.nsIMIMEInputStream);
postData.addHeader("Content-Type", "application/x-www-form-urlencoded");
postData.addContentLength = true;
postData.setData(stringStream);
return postData;
}
I'll update this to fill in the blanks in a bit.
edit: see http://forums.mozillazine.org/viewtopic.php?p=2772951#p2772951 for how to get the source window of a request.
Request cancellation code from http://zenit.senecac.on.ca/wiki/index.php/Support_For_OpenID.
see http://mxr.mozilla.org/mozilla-central/source/netwerk/base/public/nsIRequest.idl for details on nsIRequest.
See http://forums.mozillazine.org/viewtopic.php?p=2404533#p2404533 and https://developer.mozilla.org/en/XUL/Method/addTab for the definition of addTab.
parseQuery comes from http://blog.strictly-software.com/2008/10/using-javascript-to-parse-querystring.html.
See https://developer.mozilla.org/en/Code_snippets/Post_data_to_window#Preprocessing_POST_data for how to process post data in a form suitable for addTab.
ReadPostFromText and ReadTextFromStream both come from firebug (though slightly modified)

Resources