-1

I've a puzzling difference between two pages that have very similar content. Both pages load the same set of scripts:

<script type="text/javascript" src="scripts/modernizr.min.js"></script>
<script type="text/javascript" src="scripts/jquery.min.js?v=1.8.3"></script>
<script type="text/javascript" src="scripts/jquery.colorbox.min.js"></script>
<script type="text/javascript" src="scripts/jquery.tools.min.js"></script>
<script type="text/javascript" src="scripts/URI.js"></script>

and they then have this $(document).ready():

    $(document).ready(function () {
        $(".profileImage").tooltip({
            position: 'top right',
            relative: true,
            offset: [50, 0]
        }).dynamic();
    });

On one page, this works fine. On the other page, i get the following as soon as the event fires:

Uncaught TypeError: $(...).tooltip is not a function

On the page that works, I've been able to determine (by pausing and stepping into) that .tooltip() is part of jquery.tools.min.js

Edit/Update3 (1 and 2 removed because they were probably misleading)

Both these pages come from different parts of an app that implements something like an online forum

On the page where everything works, it's just messages from forum users, and their avatar images. On the page that doesn't work, that page also includes a statistics/graph drawing device that is written in javascript and html5

I've noticed, by pausing at the same point in each page's document.ready in the debugger, that on the page that works, jQuery is version 1.8.3 and all the methods from jquery-tools are available to call

On the page that doesn't work, jQuery version is 1.9.1

My presumption is that including the statistics/bar graph drawing device has completely replaced the jquery1.8.3+jquery-tools libraries loaded earlier in the page, with jquery1.9.1+NO_TOOLS, hence the reason why the selector still works (jquery's job) but the .tooltip() function (jquery-tools job)is now absent

I'm not really sure what to do about it though - what's the normal solution to having a page that has its own jquery setup, and then including other things on it that also use and load jquery (different version) etc?

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • what your html looks like? – sabotero Aug 22 '17 at 13:06
  • which bits do you want to see? (the resulting page html can be quite huge...) – Caius Jard Aug 22 '17 at 16:08
  • it would be necessary a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) – sabotero Aug 22 '17 at 16:11
  • indeed, but I've a doubt that I could turn this massive production system into an MCVE in a way that demonstrates the problem; it would be more pertinent to give you a login to it so you could see it in action... – Caius Jard Aug 22 '17 at 16:17
  • ultimately, my question seems simple - "I have this `scriptX.js` that calls `functionX()`, and it all works fine until I include this other `scriptY.js` on the same page, at which point `functionX` disappears completely, and calls to `functionX()` result in a 'functionX is not defined' crash - how did scriptY achieve this?" – Caius Jard Aug 22 '17 at 16:25
  • well, that definitely could happen. If another script register a function with the same name in the `fn` namespace of `jQuery` it will override the previous one. In your case `jQuery.fn.tooltip= function(){}` – sabotero Aug 22 '17 at 16:27
  • but would that cause it to crash with "is not defined" - surely it can be redefined, but once defined, it always "dose something" even if not intended? – Caius Jard Aug 22 '17 at 16:32
  • `jQuery.fn.tooltip= null` or `jQuery.fn.tooltip=undefined` or even `delete jQuery.fn.tooltip` will remove the function and crash in the way you described – sabotero Aug 22 '17 at 16:34
  • interesting- everything I read on the web about it indicated that though variables could be deleted, functions couldn't... have you any recommendations what to do about it? do I change some namespacing? do I rename one of the references to tooltip? etc – Caius Jard Aug 22 '17 at 16:42

2 Answers2

1

jQuery.fn.tooltip = null or jQuery.fn.tooltip = undefined or even delete jQuery.fn.tooltip will remove the function as demotrated in the following demo:

<!DOCTYPE html>
<html lang="en">

<head>

  <title>Reduxtagram</title>
</head>
<body>
<h1>messages</h1>
<div id="messages-placeholder"></div>
<h1>Errors</h1>
<div id="errors-placeholder"></div>

<script>

 function html(id, inner){
  var el = document.getElementById(id);
  el.innerHTML += inner + " ------------------- ";
 }
 function logError(error){
  html("errors-placeholder", error);
 }
 function logMsg(msg){
  html("messages-placeholder", msg);
 }
 var myNamespace= {};
 myNamespace.myFunctionToNull = function(){ 
  logMsg("myFunctionToNull was called"); 
 };
 myNamespace.myFunctionToUndefined = function(){ 
  logMsg("myFunctionToUndefined was called"); 
 };
 myNamespace.myFunctionToDelete = function(){ 
  logMsg("myFunctionToDelete was called"); 
 };
 
 myNamespace.myFunctionToNull();
 myNamespace.myFunctionToUndefined();
 myNamespace.myFunctionToDelete();
 
 myNamespace.myFunctionToNull = null;
 myNamespace.myFunctionToUndefined = undefined;
 delete myNamespace.myFunctionToDelete;
 
 try{
  myNamespace.myFunctionToNull();
 }
 catch(e)
 {
  logError(e);
 }
 try{
  myNamespace.myFunctionToUndefined();
 }
 catch(e)
 {
  logError(e);
 }
 try{
  myNamespace.myFunctionToDelete();
 }
 catch(e)
 {
  logError(e);
 }
</script>

</body>

</html>

You should found what bit of the script is removing the tooltip function and correct that.

You could also try by reordering the scripts, say, putting <script type="text/javascript" src="scripts/jquery.tools.min.js"></script> at the last position.

sabotero
  • 4,265
  • 3
  • 28
  • 43
1

If jQuery is reloaded it will replace the $ alias and the jQuery namespace, hence jQuery.fn.tooltip won't exist anymore.

You should try to reload jQuery.toolbox after jQuery 1.9.1 is reloaded.

you can do this dynamically like this (https://stackoverflow.com/a/950146/2776550):

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

var myPrettyCode = function() {

   // Here, do what ever you want
};

loadScript("my_lovely_script.js", myPrettyCode);

Nevertheless, you should strive to have only one copy and version of jQuery in your application.

sabotero
  • 4,265
  • 3
  • 28
  • 43