How can I use jQuery and Javascript from firefox add-on? - javascript

I can't create a new element in the page. I check the page and domain when the page is onload, that's work, but I don't know how can I create a new element in the correct window page.
window.addEventListener("load", function() { myExtension.init(); }, false);
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
onPageLoad: function(aEvent) {
var unsafeWin = aEvent.target.defaultView;
if (unsafeWin.wrappedJSObject) unsafeWin = unsafeWin.wrappedJSObject;
var locationis = new XPCNativeWrapper(unsafeWin, "location").location;
var hostis = locationis.host;
//alert(hostis);
if(hostis=='domain.com')
{
var pathnameis=locationis.pathname;
if(pathnameis=='/index.php')
{
$("#left .box:eq(0)").after('<div id="organic-tabs" class="box"></div>'); // this code somewhy doesn't working, but if I copy to FireBug it't work.
}
}
}
}
My question is: How can I use Javascript and jQuery from firefox addon when I want to manipulate html in the correct window content? What is need from here
$("#left .box:eq(0)").after('<div id="organic-tabs" class="box"></div>');
for working.

This code has a bunch of issues. For one, appcontent is not the browser, gBrowser is. So it should be:
init: function() {
gBrowser.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
Then, using wrappedJSObject is absolutely unnecessary (and also not safe the way you do it).
var wnd = aEvent.target.defaultView;
var locationis = wnd.location;
Finally, you are trying to select an element in the browser document (the document that your script is running in), not in the document loaded into the tab. You need to give jQuery an explicit context to work on:
$("#left .box:eq(0)", wnd.document)
But you shouldn't use jQuery like that, it defines a number of global variables that might conflict with other extensions. Instead you should call jQuery.noConflict() and create an alias for jQuery within myExtension:
var myExtension = {
$: jQuery.noConflict(true),
....
myExtension.$("#left .box:eq(0)", wnd.document)

Here is a template you can use that incorporates your sample code. I also added an additional statement so you could see another use of jQuery. Important points:
You must load jQuery before you can use it. You should myplace the jQuery library file you want to use in Chrome, for example, in the chrome/content directory.
Use window.content.document as the context for every jQuery
operation on the contents of the Web page
Use this as the context of a successful search result to help you
insert code in the correct spot.
window.addEventListener('load', myExtension.init, false);
var myExtension = {
jq : null,
init : function() {
var app;
// Load jQuery
var loader = Components.classes["#mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://myExtension/content/jquery-1.5.2.min.js");
myExtension.jq = jQuery.noConflict();
// Launch extension
if ((app = document.getElementById("appcontent"))) {
app.addEventListener("DOMContentLoaded", myExtension.run, true);
}
},
run : function() {
// make sure this is the correct Web page to change
var href = event.originalTarget.location.href;
if (href && href.match(/http:\/\/(www\.)?domain\.com\/(index\.php)/i)) {
changeScreen();
}
},
changeScreen : function() {
// make changes to the screen
// note the "window.content.document) in the first jQuery selection
myExtension.jq("#left .box:eq(0)", window.content.document).after('');
// note the use of "this" to use the search results as the context
myExtension.jq("#right", window.content.document).each(function() {
myExtension.jq("tr td", this).append('MATCH!');
});
}
}

Related

Call user defined jQuery function with JS

I use a jQuery window libray https://github.com/humaan/Modaal
which triggers events this way $("class of element").modaal({arg1, arg2,...});
--- I updated my question here to make it more general and used an iframe / Html instead of an external svg ---
To trigger an element e.g. in an external Html which is loaded within an iframe, I applied the following code to the iframe:
<iframe src="External.html" id="mainContent" onload="access()"></iframe>
which calls this function:
function access() {
var html = document.getElementById("mainContent").contentDocument.getElementById("IDofDIVelement");
html.addEventListener('click', function() {clicker();});
}
function clicker()
{
// console.log('hooray!');
$("#mainContent").contents().find("IDofDIVelement").modaal({});
//return false;
}
Actually it will only work on every second click. Any idea what I did not consider properly?
Best
You do not need to wait windows loading but iframe only:
$(function() {
$("#mainContent").bind("load",function(){
var myIframeElement = $(this).contents().find(".modaal");
myIframeElement.modaal({
content_source: '#iframe-content',
type: 'inline',
});
});
});
The reason why it did not work was that the iframe was not completely loaded, while jQuery tried to attach the function. As $(document).ready(function(){} did not work, the workaround was to initialize it with
$( window ).on( "load",function() {
$("#mainContent").contents().find("IDofDIVelement").modaal({});
});
This worked properly to attach the functionallity to an element within the iframe.
Actually modaal will vanish the envent handler after the overlay was opened and closed again.
So maybe someone wants to trigger an iframe element for modaal, too, here is a setup which would solve this issue.
(It can be optimised by #SvenLiivaks answer):
$(window).on("load", function() {
reload();
});
function reload() {
var length = $("#iframeID").contents().find("#IDofDIVelement").length;
// The following check will return 1, as the iframe exists.
if (length == 0) {
setTimeout(function() { reload() }, 500);
} else {
$("#iframeID").contents().find("#IDofDIVelement").modaal({
content_source: '#modalwrapper',
overlay_close: true,
after_close: function reattach() {
reload();
}
});
}
}

cache a DOM element inside an instantaneus function with JQuery [duplicate]

I am having some trouble accessing cached DOM element from the namespace variable. My FeedManager config variable is like this:
var FeedManager = {
config : {
$feedContainer : $('#feedContainer'),
feedUrl : 'http://rss......',
feedLimit : 10
},....
Here the $feedContainer is the ul element in the html. I wanted to add li elements built from the feed. I have a funciton init() inside FeedManager object. But somehow it can not add the child element.
init: function(){
var feed = new google.feeds.Feed(FeedManager.config.feedUrl);
......
......
// this is not working
FeedManager.config.$feedContainer.append(li);
but if inside init() function,I again get the feedContainer element ,it works !
var feedContainer = $('#feedContainer');
feedContainer.append(li);
What can be the problem? and how can I use cached dom element initialzied in my config object.
You'd need to make sure the $('#feedContainer') has already been loaded.
An analogous example:
<script type="text/javascript">
$(function() {
var Manager = {
config: {
$p: $("p#hello")
},
init: function() {
var label = Manager.config.$p.html();
console.log(label);
}
};
Manager.init();
});
</script>
Is your #feedContainer element present in your HTML or is it fetched later? If it is fetched later than you can't cache the element, you'd have to use just a selector string like
feedContainer: '#feedContainer'`
in your FeedManager object and then use something like
$(FeedManager.config.feedContainer).append(li);
If it is present in HTML then make sure that you define your FeedManager object after the DOM is ready, ie. inside of a
$(document).ready(function () {
// ...
});
or $(function () { ... });

How do I make my click catcher work?

I'm trying to create a simple click catcher where if you click .image-class the javascript will take the href from another element with a class name of .btn and send you to it's destination. Though I keep getting errors on lines 7 & 10 saying that undefined is not a function. How do I make this work?
<script>
var ClickCatcher=
{
init:function(){
var link = jQuery('.btn')[1].href;
var imgCatch = jQuery('.image-class');
imgCatch.addEventListener("click", ClickCatcher.clickListener, false);
},
clickListener:function(){
window.location = link;
}
};
ClickCatcher.init();
</script>
You can do this with jquery with a simple click event
jQuery('.image-class').on('click', function (){
window.location = jQuery('.btn').eq(1).attr('href');
});
But if you still want to write in the way you have you can do:
var ClickCatcher = {
init: function () {
jQuery('.image-class').on('click', function (){
window.location = jQuery('.btn').eq(1).attr('href');
});
}
};
ClickCatcher.init();
Just make sure to fire the init method after dom load.
update: One issue with it is that you have coded your target etc in the code rather then pass it, so its going to be hard to reuse, you'd be better off doing:
var ClickCatcher = {
init: function ($button, loc) {
$button.on('click', function (){
window.location = loc;
});
}
};
ClickCatcher.init(jQuery('.image-class'), jQuery('.btn').eq(1).attr('href'));
That way the internal working is seperate from the dom (as you are passing the dom dependencies to the function.
#atmd showed a very good way of doing this. If you just want to know what your mistake was though. It is wa an error in your jQuery stament to get the btn href
jQuery('.btn')[1].href
you need to call the attr function and then get the href attr. and use .eq(1) to reduce the set to the first btn
jQuery('.btn').eq(1).attr('href);

using $(this) inside jquery plugin

Here is my plugin code below.
$.fn.myplugin = function(options) {
var defaults = {
my_data_title11:"",
my_div:".getslow",
}
var settings = $.extend({}, defaults, options);
return this.each(function(){
console.log(options.my_data_title);
});
}
I am calling this plugin from an external page like this...
$('#o_vari,#0_var2').myplugin({
my_data_title11:$(this).attr("id"),my_div:'.getfast'
});
but it is displaying undefined. I am aware my_data_title11:$(this).attr("id") is not recognizing $(this) the calling statement, I even tried putting this exteral variable , but still the same problem.
From the way you have written the code, I'm assuming you wants to print o_vari and 0_var2... but that is not the case because in the context in which you have used $(this).att('id'), this does not refer to the o_varx element.
So if you want the desired output try
$('#o_vari,#0_var2').each(function () {
$(this).myplugin({
my_data_title: this.id,
my_div: '.getfast'
});
})
Demo: Fiddle

why is my element not targeted when reload through AJAX

I'm using object literals on my project. I'm targeting selecting with jquery. It works fine the first time but when the part I'm targeting is reloaded with AJAX I can't target those element anymore. But I look into firebug they're there...
I'm even doing console.log() to test if my code works and it works but it just doesn't want to pick those. So in order for it to work, I have to refresh the entire browser.
Do you know what's the deal with AJAX dom reload and selectors.
I think it's something to do with the DOM reloading and redrawing itself or something along those lines...
Here is my code:
Module.editWishlistTitle = {
wishListContent: $('.mod-wish-list-content'),
title: $('.title').find('h2'),
titleTextField: $('#wishlist-title-field'),
titleInnerContainer: $('.title-inner'),
editTitleForm: $('.edit-title-form'),
submitCancelContainer: $('.submit-cancel'),
notIE9: $.browser.msie && $.browser.version < 9,
edit: function () {
var fieldTxt = this.titleTextField.val(),
editForm = this.editTitleForm,
titleParent = this.titleInnerContainer,
fieldCurrentTitle = this.title.text();
this.titleTextField.val(fieldCurrentTitle);
this.submitCancelContainer.removeClass('hidden');
if (!this.notIE9) {
editForm.css('opacity', 0).animate({ opacity: 1 }).removeClass('hidden');
titleParent.addClass('hidden').animate({ opacity: 0 });
console.log(editForm);
} else {
editForm.removeClass('hidden');
titleParent.addClass('hidden');
}
}
init: function () {
var self = this;
console.log(this.editTitleForm);
//edit
this.wishListContent.delegate('.edit-title a', 'click', function (e) {
self.edit();
e.preventDefault();
});
};
If you are replacing an element on the page, you are destroying the original reference to the element. You need to redo the reference to point to the new element.
Create a new method in your code that (re)initializes the references you need. Instead of adding them in the odject, set them in the method.
Basic idea:
Module.editWishlistTitle = {
wishListContent: $('.mod-wish-list-content'),
title: $('.title').find('h2'),
//titleTextField: $('#wishlist-title-field'),
...
...
initReferences : function(){
this.titleTextField = $('#wishlist-title-field');
},
...
...
init: function () {
this.initReferences();
...
...
And when your Ajax call comes back you just need to call initReferences again.
After DOM ready, if you inject any data / class / id will not be available in DOM, so better you use live or delegate to get your new data access.
http://api.jquery.com/delegate/
Best to use delegate, that will take care your new data loaded after dom ready, that way you can avoid to refresh /reload your page.

Categories