Can not access jquery in function. "Variable Scope" issue? - javascript

My ultimate goal is to have dynamic autocompletion on text input using typeahead jquery library.
In my HTML I put the input text field like this:
<input class="typeahead form-control" name="author_1" id="author_1" type="text"
placeholder="Type a part of author name or surname">
then in javascript I have this:
<script type="text/javascript">
function typeahead_initialize() {
var path = "{{ route('instructor_name') }}";
$('.typeahead').typeahead({
source: function (query, process) {
return $.get(path, { query: query }, function (data) {
return process(data);
});
}
});
}
typeahead_initialize ();
// Here typeahead is recognized as a function
// $('.typeahead').typeahead('destroy');
// Begin jQuery
$(document).ready(function() {
$("#addAuthorBtn").click(function() {
addAuthor();
});
$("#removeAuthorBtn").click(function() {
removeAuthor();
});
function addAuthor () {
// Destroy the typeahead system
// The problem is here: typeahead is not recognized
// as a functon here. It seems I can not reach
// jquery functions here.
$('.typeahead').typeahead('destroy');
// I add the dynamic input here, I deleted the unrelated code
// Reinitialize typeahead system again to include
// the dynamically added text input
typeahead_initialize ();
}
function removeAuthor () {
// Destroy the typeahead system
$('.typeahead').typeahead('destroy');
// I remove the dynamic input here, I deleted the unrelated code
// Reinitialize typeahead system again to include
// the dynamically added text input
typeahead_initialize ();
}
});
</script>
I explained in comment where the problem is. The auto-completion works for the first static input. But the second dynamically added input is not offering autocomplete, which I suspect I must destroy the typeahead and rerun it again. I guess the 'this' object inside addAuthor() function does not point to the same 'this' which is outside of $(document).ready(function() {}). How can I solve this? I cannot destroy and reinitialize the typeahead system when user clicks the add or remove button.
The official error I get is:
TypeError: $(...).typeahead is not a function
Update:
This is not related to forgetting to include jquery library, these are the libraries that I have included so far (I am using Laravel so the formatting is a bit odd) I guess it is related to "scope". The autocompletion actually works! so it means "typeahead" library is included properly. It just does not work when I call the typeahead from "inside a function".
<script src="{{ URL::to('js/jquery-3.1.1.js') }}"></script>
<script src="{{ URL::to('js/bootstrap3-typeahead.min.js') }}"></script>

Thing you did wrong is invoking typeahead_initialize() in script directly. Put this function in document.ready and all will go smoothly.
I just copied your code and did some modification check jsfiddle below, see log in console also
https://jsfiddle.net/Ld1wcy03/

OK I found the problem by myself. The problem comes because I use Laravel and it adds some scripts via app.js at the button of my view that causes this problem.
Probably the Laravel framework adds jQuery library by itself and two instances of it causes this issue.Removing the Laravel scripts solved the issue.

Related

Getting Html From calling jQuery custom function

I created a custom function and am trying to call it in a separate function and get the elements html. What am I missing?
Custom Function: (wizard.js)
function wizard() {
var wizardBody = $(this).html();
console.log(wizardBody);
}
jQuery.fn.wizard = wizard;
Calling Said function on element: (config.js)
// Initiate Web Design Get Started Wizard
$("#webDesignGetStartedWizard").wizard();
I simply get undefined with the current code above, if I don't call the function on the html ($(this).html) then I get the following:
ƒ (e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w…
UPDATE
So the problem seems to be related to the use of my router plugin, jq-router Because if I take #webDesignGetStartedWizard out of the template and place it in my index file, it works perfectly.
https://github.com/muzammilkm/jq-router
It does work correctly make sure config.js and wizard.js loaded in the document correctly. You should load the wizard.js and then include config.js and also make sure the div#webDesignGetStartedWizard available when the script is called.
See a demo of your code.
function wizard() {
var wizardBody = $(this).html();
console.log(wizardBody);
}
jQuery.fn.wizard = wizard;
$(document).ready(function() {
// Initiate Web Design Get Started Wizard
$("#webDesignGetStartedWizard").wizard();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="webDesignGetStartedWizard">
<p>current text in the paragraph.</p>
</div>

Where should I initialize select when using Materialize and Meteor?

I'm trying to use Materialize Forms on Meteor. On its Materialize's page it says I should init the "select" input field like this:
$(document).ready(function() {
$('select').material_select();
});
I've tried calling this on Meteor.startup, Template.body.created - nothing worked. I get the following error:
undefined is not a function (evaluating '$('select').material_select()')
Where should I initialize it?
Use the template's .rendered callback
<template name="hello">
<select><option>...</option></select>
</template>
Then you can have this in your js file
Template.hello.onRendered(function() {
$('select').material_select();
});
The template is added to the body most likely after rendered has already fired so thats why the body rendered didn't work. If you use .created the DOM hasn't rendered yet.
Akshat's answer is correct but if it still doesn't work for you, there might be a problem with subscription not fired yet or not every needed part of DOM beeing rendered. Use afterflush then.
Template.listing.onRendered(function () {
var template = this;
template.subscribe('listOfThings', function () {
Tracker.afterFlush(function() {
template.$('select').material_select();
});
});
});
Here is a conversation about that: https://github.com/meteor/meteor/issues/4401#issuecomment-103340262
And the docs: http://docs.meteor.com/api/tracker.html#Tracker-flush

conflict between two jquery plugins with same function name

I am working in a large site that has 2 conflicting jquery plugins included for doing autocmplete.
1) jquery.autocomplete.js (not part of jquery ui) that does :
$.fn.extend({
autocomplete: function ...
2) jquery.ui.autocomplete.js (from the latest jquery ui library), that also uses the autocomplete keyword.
$.widget( "ui.autocomplete", { ...
Is there a way to specify that i am using only the second, jquery.ui widget
when calling
$( "#tags" ).autocomplete ...
without changing the 2 files?
As the second autocomplete is using the $.Widget method of registering itself with jQuery it'll be easiest to change the behaviour of the in-house one.
You won't be able to load both of them without making some sort of change to the jQuery object between the two script loads because they'll just conflict with (or overwrite) each other.
I would try this:
<script src="jquery.autocomplete.js"> </script>
<script>
// rename the local copy of $.fn.autocomplete
$.fn.ourautocomplete = $.fn.autocomplete;
delete $.fn.autocomplete;
</script>
<script src="jquery-ui.autocomplete.js"> </script>
Which will then make:
$().autocomplete()
use the jQuery UI version, and
$().ourautocomplete()
use your local version.
I tried to do it with the tabs function of jQuery UI, it should work the same for you.
A function is technically a js object, so you could simply rename it :
$.fn.tabs2 = $.fn.tabs;
delete $.fn.tabs;
$("#tabz").tabs2({});
Hope that helps!
Edit
Like Alnitak suggested, you also need to delete the previous function's name.
Also, I think .fn is required.

jquery live data is not responsding to the DOM

I am using this jquery plugin for called tokeninput it's for autosuggestion when typing:
the code here generates the autosuggestion for the input box:
$("#input-auto").tokenInput("topicGet.php", {
theme: "facebook"
});
but when I try to append the input which uses the #input-auto it does not do the autosuggestion but it works when it's loaded on the page:
the code is here:
$('.topicEdit').live('click', function() {
$('#Qtopics').html('<input type="text" id="input-auto" />');
I'm trying to solve the problem, but I can't find anything, I also tried to put the live click on the .topicEdit, but it's still not working. :)) thanks
Looks like you're probably initializing the autosuggestion BEFORE you add the input into the DOM. You have to remember that jQuery is stupid, and only does things in the order that you tell it. When you initially 'generate' the autosuggestion, if it can't find it in the DOM at that moment, it won't do anything! So, to solve your problem, you'll want to do the generation of the autosuggest after you insert it into the DOM:
$('.topicEdit').live('click', function() {
$('#Qtopics').html('<input type="text" id="input-auto" />');
$("#input-auto").tokenInput("topicGet.php", {
theme: "facebook"
});
});
yay?
Calling tokenInput on page load when input-auto doesn't yet exist is your problem.
$('.topicEdit').live('click', function() {
$('#Qtopics').html('<input type="text" id="input-auto" />');
$("#input-auto").tokenInput("topicGet.php", {
theme: "facebook"
});
});
I'm not exactly sure what the problem is, but try using livequery plugin. You don't need to specify an event to it, just a function which will run for all current and future elements that match the selector.
Example:
$(".something").livequery(function () {
// do something with the element
}

jquery autocomplete this.source is not a function error

I've implemented autocomplete on an input field, but the box does not show up and firebug returns "this.source is not a function". I've used autocomplete on other fields of the same page without any problems. (two textarea's).
I'm using the following code to debug, same effect if I run from script file or Firebug command line.
var fakedata = ['test1','test2','test3','test4','ietsanders'];
$("#omschrijving").autocomplete(fakedata);
running jquery 1.4.2 and jquery ui 1.8.2, both minified versions.
Does anyone have an idea how autocomplete works fine on the textareas but causes this malfunctioning on inputs?
Error & Stack trace:
this.source is not a function
http://facturatie.autodealers.nl/dev/resources/js/jquery-ui-1.8.2.custom.min.js
Line 570
close(Object { name="a"})jquery....min.js (regel 570)
close(Object { name="a"}, Object { name="c"})jquery....min.js (regel 570)
response()
Answer is that the first parameter of the autocomplete should be an object containing the "source" property. This works
var fakedata = ['test1','test2','test3','test4','ietsanders'];
$("#omschrijving").autocomplete({source:fakedata});
If you were trying to use autocomplete from http://www.devbridge.com/projects/autocomplete/jquery/#demo, it now collides with the autocomplete method in jQuery UI. I had the same problem and later noticed that I could just use the jQuery UI implementation.
(NOTE: It appears that this page's documentation is wrong: http://docs.jquery.com/Plugins/Autocomplete#Setup)
If you use it with jQuery UI library it also has plugin named autocomplete. In this case you can use plugin alias devbridgeAutocomplete:
$('.autocomplete').devbridgeAutocomplete({ ... });
This solve the problem with jQuery UI collision
As Shelton stated, the version from devbridge.com (1.1.3) collides with jQuery UI (1.8.4). Got it working by making sure the devbridge version loads after jQuery UI's version.
Had similar problem for tagedit/autocomplete. It seems you also want to disable the autocomplete. Setting the source to false avoids these errors.
Solution:
options.autocompleteOptions.source = false;
Search at the end of jquery.autocomplete.js the following section:
Create chainable jQuery plugin:
$.fn.devbridgeAutocomplete = function (options, args) {....
This devbridgeAutocomplete is an alternative plugin to access to the same functionality using this lines:
if (!$.fn.autocomplete) {
$.fn.autocomplete = $.fn.devbridgeAutocomplete;
}
So.. you can use devbridgeAutocomplete instead of autocomplete or any name by changing this $.fn.devbridgeAutocomplete
in my case I had a second import of jquery which I didn't realize.
Something like:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.devbridge-autocomplete/1.2.27/jquery.autocomplete.min.js"></script>
// More code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"> </script>
So be sure to import the autocomplete script after you initialized jquery.

Categories