TypeError: $(...).selectize is not a function
Asked Answered
P

3

7

I installed the "selectize-rails" gem into my rails app, and I'm trying to get it to work. I keep getting this error in my web console:

TypeError: $(...).selectize is not a function

and nothing happens in the browser. Here's the code I have so far, following the "Email Contacts" example from this page: http://brianreavis.github.io/selectize.js/


views/emails/new.html.erb

<script type="text/javascript">


  $(document).ready(function() {
    console.log( typeof $.fn.selectize === 'function'); // true
    console.log( $('#select-to').length === 1 ); // true

    var REGEX_EMAIL = '([a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@' + '(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)';

    $('#select-to').selectize({
      persist: false,
      maxItems: null,
      valueField: 'email',
      labelField: 'name',
      searchField: ['name', 'email'],
      options: [ 
        {email: '[email protected]', name: 'Brian Reavis'},
        {email: '[email protected]', name: 'Nikola Tesla'},
        {email: '[email protected]'}
      ],
      render: {
        item: function(item, escape) {
          return '<div>' +
            (item.name ? '<span class="name">' + escape(item.name) + '</span>' : '') +
            (item.email ? '<span class="email">' + escape(item.email) + '</span>' : '') +
          '</div>';
        },
        option: function(item, escape) {
          var label = item.name || item.email;
          var caption = item.name ? item.email : null;
          return '<div>' +
            '<span class="label">' + escape(label) + '</span>' +
            (caption ? '<span class="caption">' + escape(caption) + '</span>' : '') +
          '</div>';
        }
      },
      createFilter: function(input) {
        var match, regex;

        // [email protected]
        regex = new RegExp('^' + REGEX_EMAIL + '$', 'i');
        match = input.match(regex);
        if (match) return !this.options.hasOwnProperty(match[0]);

        // name <[email protected]>
        regex = new RegExp('^([^<]*)\<' + REGEX_EMAIL + '\>$', 'i');
        match = input.match(regex);
        if (match) return !this.options.hasOwnProperty(match[2]);

        return false;
      },
      create: function(input) {
        if ((new RegExp('^' + REGEX_EMAIL + '$', 'i')).test(input)) {
          return {email: input};
        }
        var match = input.match(new RegExp('^([^<]*)\<' + REGEX_EMAIL + '\>$', 'i'));
        if (match) {
          return {
            email : match[2],
            name : $.trim(match[1])
          };
        }
        alert('Invalid email address.');
        return false;
      }
    });
  });
</script>

application.html.erb

<head>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
  <%= javascript_include_tag "jquery.endless-scroll" %>
  <%= yield(:head) %>
</head>

javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require bootstrap
//= require turbolinks
//= require selectize
//= require_tree .

Selectize.js seems to be included in my application: this is the <head> from my page source:

<!DOCTYPE html>
<html>
<head>
<!--...-->
  <link href="/assets/selectize.css?body=1" media="screen" rel="stylesheet" />  
  <link data-turbolinks-track="true" href="/assets/application.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/custom.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/jquery-ui.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/jquery-ui.structure.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/jquery-ui.theme.css?body=1" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/assets/users.css?body=1" media="all" rel="stylesheet" />
  <script data-turbolinks-track="true" src="/assets/jquery.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery_ujs.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery-ui.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/bootstrap.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/turbolinks.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/sifter.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/microplugin.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/selectize.min.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery.color.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery.endless-scroll.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/users.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/application.js?body=1"></script>
  <meta content="authenticity_token" name="csrf-param" />
<meta content="KjspKaF93jfFsjf8jsoaisHSf=" name="csrf-token" />
</head>

Gemfile:

source 'https://rubygems.org'
ruby '2.0.0'

gem 'rails', '4.0.10'
gem 'bootstrap-sass', '~> 2.3.2.0'
gem 'sprockets', '~> 2.12'
gem 'chosen-rails'
gem 'bcrypt', '~> 3.1.7'
gem 'therubyracer'
gem 'sass-rails', '4.0.5'
gem 'uglifier', '~> 2.1.1'
gem 'coffee-rails', '~> 4.0.1'
gem 'jquery-rails', '~> 2.3.0'
gem 'turbolinks', '~> 1.1.1'
gem 'jbuilder', '~> 1.0.2'
gem 'libv8', '3.16.14.7'
gem 'yaml_db_improved'
gem 'selectize-rails'

group :development, :test do
  gem 'sqlite3', '~> 1.3.8'
  gem 'rspec-rails', '~> 2.13.1'
end

group :test do
  gem 'selenium-webdriver', '~> 2.35.1'
  gem 'capybara', '~> 2.1.0'
end

group :doc do
  gem 'sdoc', '~> 0.3.20', require: false
end

group :production do
  gem 'rails_12factor', '~> 0.0.2'
end

config/environments/production.rb:

Website::Application.configure do
  config.cache_classes = true
  config.eager_load = true
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
  config.serve_static_assets = false
  config.assets.js_compressor = :uglifier
  config.assets.compile = false
  config.assets.digest = true
  config.assets.version = '1.0'
  config.log_level = :info
  config.i18n.fallbacks = true
  config.active_support.deprecation = :notify
  config.log_formatter = ::Logger::Formatter.new
end

config/environments/development.rb:

Website::Application.configure do
  config.cache_classes = false
  config.eager_load = false
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false
  config.action_mailer.raise_delivery_errors = false
  config.active_support.deprecation = :log
  config.active_record.migration_error = :page_load
  config.assets.debug = true
end

config/application.rb:

require File.expand_path('../boot', __FILE__)

require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"

Bundler.require(*Rails.groups)

module Website
  class Application < Rails::Application

    config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
  end
end

Does anyone who has used Selectize know what I might be missing?

UPDATE:

It gets weirder: Error-prone code randomly started working, but then broke again upon refresh

Pattani answered 3/1, 2015 at 17:40 Comment(40)
that error generally means you either forgot to load the plugin file,or the path is wrong to the file, or you have loaded jQuery more than once and wiped out that plugin. It is not a problem specific to any particular plugin. In short, the error is telling you that function declaration can't be found at the time your code runsAgostino
@Agostino But it's a gem. Do I need to download additional files even after installing the gem?Pattani
I don't know (not a rails dev) but you can at least inspect the output and see what's there and what's not. Browser could care less how your back end worksAgostino
Nope. you don't have to download the plugin files; the gem handles that part. Could you include the full content of the javascripts/application.js file? The //= require selectize directive should be after //= require jquery for it to work properly. When it is working properly, you should be able to see selectize.js as one of the loaded files in Sources on the browser.Messick
@PrakashMurthy Yeah it's after //= require jquery, I included the full code above. And selectize.js is also loaded apparently; I also included the relevant line from my source's head.Pattani
@Agostino What do you mean by output? You mean inspect the elements that appear in my browser?Pattani
Do you see selective.js in the scripts/assets section when you inspect the page on the browser?Messick
@PrakashMurthy Yes, it's there.Pattani
then possibly more than one version of jQuery library is being loaded. There is a reason that the function can't be found.Agostino
@Agostino Are you aware of a solution?Pattani
you haven't confirmed the suggestions I already gave you. be aware that just becase a script tag exists, the path may not be correct or loading order may not be correctAgostino
You mean in your first comment? How do I check if I included jquery more than once? I can't imagine the path is wrong.Pattani
@Agostino How can I check the path/loading order?Pattani
by looking at source of page. Do you have a live link?Agostino
I don't unfortunately. The line including assets/selectize.js?body=1 is the second-to-last asset included (the last is assets/application.js?body=1) but I have no idea how to verify if that's correct, or even the correct path.Pattani
Are you using jQuery-rails gem? Can you post your Gemfile? Also, what files are in your app/assets/javascripts and vendor/assets/javascripts/ folders?Capitol
@Capitol Yes, I'm using v '~>2.3.0'. I added my Gemfile. That's weird though, 'selectize.js' is included in my source code, but it's not in app/assets/javascripts or vendor/assets/javascripts. Should it be?Pattani
No, the jQuery-rails gem is providing the javascript file.Capitol
The question is, where is your script tag, the one shown above, in relation to the selectize.js include. The script tag where you use selectize has to come after the line where the script is loaded in the DOM. Also, is the script tag inserted after all the DOM elements, as you don't have a DOM ready handler in there ?Charyl
@Charyl I admit, I didn't fully understand everything in your comment. So I added my full <head> from my page source. I hope there's enough information in it to answer your question.Pattani
And there it is, jQuery is included multiple times, so is jQuery UI in various forms. Make sure jQuery and jQuery UI is only included once in the document, and that the order is correct, i.e. jQuery comes before jQuery UI, then the plugins, and at the end your scripts using all the former etc.Charyl
@Charyl I removed the duplicates from my <head> but the order is still off, /assets/jquery.js?body=1 and /assets/jquery.min.js?body=1 are still both included, and the error is still there. How can I edit my application.html.erb or application.js to remedy this? I added my application.html.erb, by the way.Pattani
Place this on top inside your javascript tag, and see what you get in the console -> jsfiddle.net/fvf7qqyn/1Charyl
@Charyl I updated my javscript; check to see if I did it correctly. The console shows two instances of "false", listed right after the TypeError.Pattani
Oh okay, both are false. One of them is easy to fix, just add a $(document).ready() function around your code so the DOM is loaded when you try to access it. The other one is that selectize is not a function, and that's still an issue with the order of the scripts, assuming all the files load properly, which they probably do, otherwise you'd get an 404 error in the console.Charyl
@Charyl How would you recommend I order the scripts?Pattani
Not sure, but if $.fn.selectize is still undefined in your script tag, it's not loaded, or not loaded in the right place. Did you try wrapping everything in $(document).ready() by the way `Charyl
@Charyl I updated my javascript so you can make sure I did it right. Now the two "false"s are listed before selectize.js, right after the line GET http://localhost:3000/resources/demos/style.css.Pattani
What happens when you move the console logs inside the document.ready functionCharyl
@Charyl Okay now both "false"s are back where they were, right after selectize.js.Pattani
If both are still false inside the document.ready handler, you don't have an element with the ID select-to in your document (or you have more than one) ?Charyl
@Charyl Ah, that's good to know. Okay I now have a <div id="select-to">, and the console now reads "false" "true".Pattani
The second false is of course $.fn.selectize not being a function, and that's probably because the plugin isn't loading. Open the console and look in the network tab if any of the scripts are returning 404. It does seem strange as it seems to be in the right place in the head. Check the HTML to make sure there are no more jQuery versions being loaded in the body as well.Charyl
@Charyl None of the scripts are returning 404, and there are no other versions of jQuery being loaded. Would you recommend I just try to guess different orders for the scripts?Pattani
Nope, first jQuery, then the plugin, then your script, which it looks like it is now, but if selectize isn't defined, it's not loading, or loading at the wrong time, and it's hard to tell why!Charyl
@Charyl Wait, which plugin?Pattani
@Charyl Haha oh, I was confused because I'm using the gem.Pattani
@Charyl What on Earth????? I visited the relevant page without changing anything, and it randomly started working! But then when I refreshed the page, it stopped working again..Pattani
Sounds strange, could be browser cache, but then it normally wouldn't stop working again on a refresh. I really have no idea ?Charyl
Comments are not for extended discussion; this conversation has been moved to chat.Actinomycete
C
4

I think you have a jQuery dependency issue caused by the jQuery-rails gem. Try this:

1) Comment out this line in your Gemfile

gem 'coffee-rails', '~> 4.0.1'
#gem 'jquery-rails', '~> 2.3.0'
gem 'turbolinks', '~> 1.1.1'

2) Run bundle install

3) Download this version of jQuery and put in in your vendor/assets/javascript folder.

EDIT

To migrate to the non-gem version place these files in the following paths:

  • vendor/assets/stylesheets/selectize.css
  • vendor/assets/javascript/selectize.min.js
  • vendor/assets/javascript/sifter.js
  • vendor/assets/javascript/microplugin.js
Capitol answered 8/1, 2015 at 3:51 Comment(12)
Where can I download it from? I don't see any links.Pattani
I'm still getting the same "not a function" error. I suppose it's worth noting that I had to remove //= require jquery_ujs from my application.js because I was getting a "file not found" error for it after I deleted the jquery-rails gem; but I don't know if that would cause any problems.Pattani
Which version of Selectize did you download? There is one with dependencies and another without dependencies, which did you download?Capitol
I'm not sure, I just bundle installed selectize-rails. How can I check?Pattani
It looks like the gem is missing the dependencies. Can you add the dependencies into the vendor/assets/javascript folder (sifter, microplugin)?Capitol
Oh, good catch. But unfortunately it still doesn't work. I noticed selectize.js is included before sifter.js and microplugin.js in the source code's <head>; do you think that could be a problem?Pattani
Actually scratch that...I figured out how to put them in the proper order, but to no avail.Pattani
Ok, lets try to remove the selectize-rails gem and use the straight JS libraries.Capitol
I actually tried to install the plugin (I assume that's what you're talking about) before, but there is such a vast number of files that I have no idea which ones to require. Here's a list of all the files in it: [#27638320Pattani
All the files are being included, but I'm still getting the error.Pattani
Let us continue this discussion in chat.Capitol
FWIW, this answer didn't solve the problem for me. (It sounds like it didn't solve the OP's problem, either.)Sing
S
1

I had resolved same issue by removing jQuery include, that was included twice. There's note about that in the comments, but it's collapsed and I figured that out myself. Posting this as answer for people to notice it.

Sabelle answered 10/9, 2016 at 9:26 Comment(0)
S
1

For me, the issue was that my application code was being included before selectize.js. Adding //= require selectize to app/assets/javascripts/application.js before //= require_tree . fixed it.

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require selectize
//= require_tree .
Sing answered 14/2, 2017 at 14:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.