How to check jQuery plugin and functions exists? - javascript

I have a plugin in some pages but in some other pages I don't want it so I didn't reference its script file.
How to check if the plugin functions exist before using it.
In my case I am using this plugin: and I use it like this:
$('#marquee-inner div').marquee('pointer').mouseover(function() {
$(this).trigger('stop');
}).mouseout(function() {
$(this).trigger('start');
}).mousemove(function(event) {
if ($(this).data('drag') == true) {
this.scrollLeft = $(this).data('scrollX') + ($(this).data('x') - event.clientX);
}
}).mousedown(function(event) {
$(this).data('drag', true).data('x', event.clientX).data('scrollX', this.scrollLeft);
}).mouseup(function() {
$(this).data('drag', false);
});
What I want is to make a check before calling this marquee function if it exist or not.

if ($.fn.marquee) {
// there is some jquery plugin named 'marquee' on your page
}

You can also do this. Let me take jQuery marquee example.
This is good if you are using only jQuery.
if($().marquee) {
// marquee is loaded and available
}
OR
if($.fn.marquee !== undefined) {
// marquee is loaded and available
}
Similar to above but Safe when you are using other JS frameworks Mootools etc.
if(jQuery().marquee) {
// marquee is loaded and available
}
OR
if(jQuery.fn.marquee !== undefined) {
// marquee is loaded and available
}

Slightly better:
if ($.isFunction($.fn.marquee)) {
// ...
}
Maybe a little overkill, but this will ensure that it's at least a function.
Update January 2021:
Since jQuery.isFunction() has been deprecated as of version 3.3, the easiest & recommended way to check this is now:
if (typeof $.fn.marquee === "function") {
// ...
}
Note that this may not be enough for certain very old browsers—see the $.isFunction() implementation for details.

Related

Exporting jQuery custom plugin

I really hope this question doesn't end marked as 'already answered' because I've minutely checked previous questions and my case, unfortunately, doesn't happen to be there.
I've already create a (working) jQuery function to transform a form into a JSON object so I can send it to the server (this is all with an educational purpose by the way, so please save your time before telling me to use a library lol) and even though is working great, I want to save it in a separate file so my main script doesn't look too awful.
(function ($) {
$.fn.formToJSON = function(){
let json = {};
if($(this).is('form')){
$.each($(this).find('input'), function(){
if(this.name && this.value){ //are not empty
if(this.type === 'checkbox' && this.checked){
json[this.name] = (json[this.name] || []).concat(this.value || ''); //check if exists
}else{
json[this.name]= this.value;
}
}
});
}
console.log(JSON.stringify(json));
}
})(jQuery);
What do I need to do to use it by just importing the script in the HTML file?
The followinglike function patters are not what I'm looking for in my script by the way.
(function($) {
$.fn.helloWorld = function() {
return this.each( function() {
$(this).text("Hello, World!");
});
}
}(jQuery));
I'd appreciate if someone could help me achieve the goal which is using my script like this (I can already use like that but it needs the function to be in the main script):
$('form').formToJSON();
Nevermind, I just figured out all I need to do is add several declarations of functions inside my IIF (Immediately Invoked Function) jQuery function.
(function($){
$.fn.logme = function(){
console.log(this);
}
$.fn.logHi = function(){
console.log('hi!');
}
})(jQuery)

Windows 7 gadget not loading

I'm developing a simple gadget for Windows 7 as a learning exercise.
I read in this article (under the subtopic Gadgets and Script) that to initialize the gadget, you should use document.onreadystatechange instead of events such as onLOad. I've seen it in the example project code I've looked through as well. This is what I came up with for my project.
document.onreadystatechange = function()
{
if(document.readyState == "complete")
{
System.Gadget.settingsUI = "settings.html"; //this line enables the settings UI
System.Gadget.onSettingsClosed = settingsClosed;
}
}
However when I use this snippet in my work, it doesn't work. The Options button in the gadget doesn't show up. If I use onLoad, it works. I have installed 2 gadgets. Each of them use these 2 methods. One use onLoad and the other use document.onreadystatechange. And both of them works!
Now I'm confused why it doesn't work with my gadget. Is there any important part I'm overlooking?
try something along these lines,
move your onsettingsclosed to a different event and call the function with it
document.onreadystatechange = function()
{
if(document.readyState=="complete")
{
var searchTags = System.Gadget.Settings.read("searchTags");
if(searchTags != "")
{
searchBox.value = searchTags;
}
}
}
System.Gadget.onSettingsClosing = function(event)
{
if (event.closeAction == event.Action.commit)
{
var searchTags = searchBox.value;
if(searchTags != "")
{
System.Gadget.Settings.write("searchTags", searchTags);
}
event.cancel = false;
}
}

Why this Javascript code fails in IE7-8?

I have this code:
window.addEvent('domready', function() {
var li_list = document.getElementById("topmenu").getElementsByTagName("li");
for (var i=0; i<li_list.length; i++) {
li_list[i].onmouseover=function() {
this.className+=" hover";
}
li_list[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" hover\\b"), "");
}
}
})
In IE7-8 it fails: document.getElementById(...) is null or not an object.
In Firefox it works well.
That affect the main menu function of the site: http://paraguasparados.com
Thanks.
On IE, domready can fire before the dom is actually ready. Post.
So then document object is not yet available when your code is executed. (Hence the IE error message "document.getElementById(...) is null or not an object.")
Solution: use a toolkit (jQuery, yui, etc) to provide the equivalent of domready that works on IE and other browsers.
Try this instead. This should only work in IE though.
document.attachEvent( "onreadystatechange", function() {
if ( document.readyState === "complete" ) {
// dom ready
}
});
Use jquery, they have done the leg work getting it to work cross browser.
$(document).ready(function() {
// do some stuff here
});

JavaScript bind element events as soon as element is loaded

I want to make things happen with DOM elements as soon as they are loaded (found nothing with search on this site or Google, but it is hard to explain this with few words). For example, when a big page is loading I want to hide/add onlick events/etc. to elements as soon as they appear on user's screen not on $(document).ready(). I wrote a simple class (just for training, closures are new for me so there may be lots of errors) that does what I want but I want to use something better for commercial useb(on the site I'm helping to develop). Here is my source code:
function MY_loader() {
function container() {
this.add_event = function(new_event,obj_selector,settings) {
if(typeof(settings)!='object') {
settings={};
}
if(typeof(settings.event_id)!='string') {
settings.event_id=gen_new_event_id();
}
settings=$.extend({},default_settings,settings);
settings.obj_selector=obj_selector;
settings.event=new_event;
events[settings.event_id]=settings;
}
this.execute_events = function(if_force) {
if(typeof(if_force)=='undefined') {
if_force=false;
}
if(html_is_loaded&&!if_force) {
return;
}
var temp_obj;
for(var event_name in events) {
temp_obj=$(events[event_name].obj_selector);
if(temp_obj.length || (html_is_loaded && events[event_name].if_force)) {
temp_obj.each(function() {
if(events[event_name].expect_multiple) {
if($(this).data('my_loader_'+events[event_name].event_id+'_executed')) {
return;
}
}
if(events[event_name].event_type!='func') {
$(this).bind(events[event_name].event_type+'.'+events[event_name].event_id,events[event_name].event);
}
else {
events[event_name].event($(this));
}
if(events[event_name].expect_multiple) {
alert('here');
$(this).data('my_loader_'+events[event_name].event_id+'_executed',1);
}
});
//alert(events[event_name].obj_selector+' '+events[event_name].event_type);
if(!events[event_name].expect_multiple) {
delete events[event_name];
}
}
}
if(!html_is_loaded) {
var cur_time=new Date().getTime();
setTimeout('MY_loader().execute_events();',Math.max(Math.min(tick_time-(cur_time-last_tick_time),tick_time),0,min_tick_diff));
last_tick_time=cur_time;
}
}
this.html_is_loaded_set=function(if_html_is_loaded) {
html_is_loaded=if_html_is_loaded?true:false;
};
this.html_is_loaded_get=function() {
return html_is_loaded?true:false;
};
return this;
}
function instance(if_strat) {
if(typeof(class_is_loaded)=='undefined'||!class_is_loaded) {
load_class();
}
return container(if_strat);
}
var load_class=function() {
this.class_is_loaded=true;
this.events = {};
this.allowed_event_id_chars='abcdefghijklmnopqrstuvwxyz0123456789';
this.default_settings={
'event_type':'click',
'if_force':false,
'expect_multiple':false
};
this.tick_time=500;
this.min_tick_diff=100;
this.last_tick_time=0;
this.html_is_loaded=false;
MY_loader().execute_events();
$(document).ready(function(){
MY_loader().html_is_loaded_set(true);
MY_loader().execute_events(true);
});
}
var gen_new_event_id=function() {
for(var new_id=gen_random_id();typeof(events[new_id])!='undefined';new_id=gen_random_id());
return new_id;
}
var gen_random_id=function() {
var allowed_event_id_chars_size=allowed_event_id_chars.length;
var new_id='';
for(var i=0;i<10;i++) {
new_id+=allowed_event_id_chars[get_random_int(0,allowed_event_id_chars_size-1)];
}
return new_id;
}
function get_random_int(min, max)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
}
return new instance();
}
//Add click event to #some_selector (once and dont check after it)
MY_loader().add_event(function() {
alert($(this).val());
}, '#some_selector');
//Hide elements as soon as they are loaded.
//We expect multiple elements with this selector, so it will
//check for this elements untill document is loaded, but this function
//will be applied only one time for each element.
MY_loader().add_event(function(obj) {
obj.hide();
alert('This should happen before DOM is completely loaded!');
}, '.some_other_selector',{'event_type':'func','expect_multiple':true});
//This alert should be outputted the last
$(document).ready(function(){
alert('Document is fully loaded!');
});
UPD: To make this question a little bit more interesting as it seems too specific I must add: most of the browsers start page rendering before it is completely loaded (this seems to be not well-known for some reason), here are a few links:
http://en.wikipedia.org/wiki/Incremental_rendering
When do browsers start to render partially transmitted HTML?
http://www.vbulletin.org/forum/showthread.php?t=161099
So, my problem should be more widely known as this incremental page loading adds lots of problems for developer: user can click on non-working buttons before page is loaded, some things that are hidden by JavaScript on load may show and they can be ugly, etc. (this are examples from my problem). Do other developers just ignore this problem? Please, correct me if I am wrong.
If your concern is that you don't want users to see the page before it is final, you can probably get away with doing the DOM modification straightaway, e.g.:
Test
<script type="text/javascript" src="enhancePage.js"></script>
Because the node in question exists in the DOM before the script is parsed, you can work with it.

How can I rewrite this jQuery code into Javascript?

I'm using a WordPress theme that only has about 10 lines of jQuery, yet it's using the 90kb jQuery file. I want to change this jQuery code to Javascript, but I'm not very good at Javascript:
jQuery('body #main-tabbed-area a, body .wp-pagenavi a, body .pagination a').live("click", function () {
$href = jQuery(this).attr('href');
$contentArea.fadeTo('fast', 0.2).load($href + ' #main-area', function () {
$contentArea.fadeTo('fast', 1);
});
return false;
});
var $tabbed_area = jQuery('div#tabbed');
if ($tabbed_area.length) {
$tabbed_area.tabs({
fx: {
opacity: 'toggle'
}
});
};
Thanks in advance!
Personally I'd persist with jQuery. Although there is "only about 10 lines jQuery" what it is doing is quite substantial. By the time you have recreated a lot of what jQuery is providing you here you will have a fairly decent slab of javaScript to debug and maintain. That is the beauty of jQuery, to quote their tag line "write less, do more" Remember with jQuery you are eliminating a lot of annoying cross browser quirks.
Edit: See tbranyen's answer for a practical example of why jQuery is worth it
Use a CDN version of jQuery, like Google's and you will be using jQuery that your uses may already have cached and therefore does not have to be downloaded again. jQuery UI can also be served in the same way. See this article: http://encosia.com/2008/12/10/3-reasons-why-you-should-let-google-host-jquery-for-you/
EDIT
Reading your question further "I'm not very good at javaScript" is all the more reason to stick with jQuery. Let it do all the heaving lifting for you. HOWEVER don't use jQuery as an excuse not to learn more about javaScript, the more you learn about javaScript the more you will be able to get out of jQuery.
My solution is fragmented, its not complete, and I do not expect points for this answer. This was me taking a stab at replicating jQuery's code in vanilla JS, purely as scientific justice to your question. I consider myself good at JavaScript, but even I know my limitations and time constraints. I only have one life on this planet and its honestly not worth my time to write out a tabs plugin and animation for your Wordpress site.
Just take a look at the code difference. If you're really scared about people downloading, you should ask yourself what makes your site so much different than the thousands/millions? of other sites that are visited by millions of people?
Writing this stuff is tedious, that's why if I have to do these things, I use jQuery. However, lets say you don't care about older browser support. You didn't mention that, I have a solution at the very bottom that does more, but WILL not work with older browsers or work period for that matter.
The original
Very little code to do immensely complicated stuff.
jQuery('body #main-tabbed-area a, body .wp-pagenavi a, body .pagination a').live("click", function () {
$href = jQuery(this).attr('href');
$contentArea.fadeTo('fast', 0.2).load($href + ' #main-area', function () {
$contentArea.fadeTo('fast', 1);
});
return false;
});
Attempting to write from scratch
// Not even close to finished solution
(function(window, document) {
var tabbed = document.getElementById('tabbed');
// Semi-normalized event handling, not even a fraction as good as jQuery's
function attachEvent(node, type, callback) {
if(node.attachEvent) {
return node.attachEvent('on'+type, function() {
callback.apply(window.event.target, arguments);
});
}
return node.addEventListener(type, function(e) {
callback.apply(e.target, arguments);
}, true);
}
// Semi-delegation again, not even a fraction of what jQuery offers
attachEvent(document, 'click', function(e) {
var href = this.href;
var body = document.body;
var elements = [];
var slice = [].slice;
var concat = elements.concat;
// This is just the start of what it would take to emulate what jQuery is doing to match all those items
// Without a reliable selector engine like querySelectorAll (not even that reliable) you'd need to match.
elements = concat(slice.call(body.getElementById('main-tabbed-area').getElementsByTagName('a')));
elements = concat(slice.call(body.getElementsByTagName('...');
// Not even going to attempt fading
// jQuery again does all this
});
if(tabbed && tabbed.tagName === 'div') {
// No idea what tabs is? A plugin? Good luck!
}
})(this, this.document);
Code is slightly more modern... but still jeesh look at all that code
function xhr(url, callback) {
var request = new window.XMLHttpRequest();
request.open('GET', url, true);
request.onreadystatechange = function(e) {
if(e.readyState === 4) {
callback(e.responseXML);
}
};
request.send(null);
}
// No idea what contentArea is
var contentArea = ...???;
(function(window, document) {
var tabbed = document.getElementsById('tabbed');
document.addEventListener('click', function(e) {
var href;
var elements = document.querySelectorAll('body #main-tabbed-area a, body .wp-pagenavi a, body .pagination a');
var match = false;
elements.forEach(function(element) {
if(this === element) {
match = true;
}
});
if(match) {
href = e.target.href;
// Some CSS3 class that does a fade out
contentArea.classList.add('fadeOut');
xhr(href, function(data) {
var data = data.getElementById('main-area').innerHTML;
contentArea.innerHTML = data;
contentArea.classList.remove('fadeOut');
// Some CSS3 class that does a fade in
contentArea.classList.add('fadeIn');
});
return false;
}
}, true);
if(tabbed && tabbed.tagName === 'div') {
// Still no idea what tabs is? A plugin? Good luck!
}
})(this, this.document);

Categories