why jquery UI Widgets doesn't work in my laravel application? - javascript

I have laravel application and trying to use dialog widget, but I keep getting this error in the console:
TypeError: $(...).dialog is not a function[Learn More]
I tried to test normal jquery functions and it works fine, it is just jquery UI.
<head>
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<!-- Scripts -->
<script>
window.Laravel = {!! json_encode([
'csrfToken' => csrf_token(),
]) !!};
</script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="text/javascript">
$( function() {
$( "#dialog" ).dialog({
autoOpen: false,
show: {
effect: "blind",
duration: 1000
},
hide: {
effect: "explode",
duration: 1000
}
});
$( ".opener" ).on( "click", function() {
$( "#dialog" ).dialog( "open" );
});
} );
</script>
</head>
<body>
<div id="dialog" title="Basic dialog">
<p>This is an animated dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>
Update:
there is a conflict between these lines:
<script src="{{ asset('js/app.js') }}"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
but still can't remove any of them.
Update 2
webpack.mix.js
const { mix } = require('laravel-mix');
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
app.js
require('./bootstrap');
window.Vue = require('vue');
Vue.component('example', require('./components/Example.vue'));
const app = new Vue({
el: '#app'
});
bootstrap.js
window._ = require('lodash');
try {
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
} catch (e) {}
window.axios = require('axios');
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = window.Laravel.csrfToken;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

See this link: https://github.com/JeffreyWay/laravel-mix/blob/master/docs/jquery-ui.md
NOTE: I am fairly new to Laravel Mix (webpack) and still learning.
In the linked example his resources/assets/js/app.js contains the lines:
import $ from 'jquery';
window.$ = window.jQuery = $;
but in my case I'm editing resources/assets/js/bootstrap.js, which contains the line:
window.$ = window.jQuery = require('jquery');
so I added the widget import line:
import 'jquery-ui/ui/widgets/dialog.js';
After the edits, to run the Mix tasks, I ran this command at my project root: npm run dev
And in my Chrome browser, on the page calling $(...).dialog(), I opened the devtools console and then right clicked on the browser page reload icon and clicked Empty cache and hard reload
Since I am using Laravel Mix (webpack) I do not need to include the jquery specific script tags and stylesheet links.

Are you using the .sass file that you're mixing in your webpack.mix.js file?
If not, try changing your webpack.mix.js to this:
const { mix } = require('laravel-mix');
mix.js('resources/assets/js/app.js', 'public/js');
New to Laravel and web development in general; that worked for me.

Try inserting app.js before jquery-ui.js. This makes jquery-ui.js overwrite any common code. I found it does not cause significant side-effects. Some items like tooltips will look different, but you can just modify the linked js files to handle that if necessary.

Related

PHP + Laravel + Vue - Unexpected token '<' at app.js

I have a PHP+Vue project that I inherited from another programmer. I know the code should work because it's currently hosted on a server and running.
I downloaded the files to make some changes, and tried to run it locally (using Wampserver). However, when I try to access the site I get Uncaught SyntaxError: Unexpected token '<' (at app.js:1:1).
What I tried:
Looking into app.js (and app.css for that matter) in DevTools shows an HTML file (seems to be from base.blade.php) instead of javascript code. I checked every app.js file I could find on the project's folder and found actual code.
It seems like the wrong file is being served, but I don't know why or how to fix it. I don't have any experience with PHP.
Code:
app.js:
require('./bootstrap');
window.Vue = require('vue');
const files = require.context('./components', true, /\.vue$/i)
files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
const app = new Vue({
el: '#app',
});
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
bootstrap.js:
window._ = require('lodash');
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
base.blade.php:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>#yield('title')</title>
<link href="{{ env('APP_ENV') == 'development' ? mix('css/app.css') : asset('css/app.css') }}" rel="stylesheet" defer>
<script src="{{ env('APP_ENV') == 'development' ? mix('js/app.js') : asset('js/app.js') }}" defer></script>
{{-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> --}}
<link href="https://fonts.googleapis.com/css?family=Roboto:200,300,400,500,600,700,800,900" rel="stylesheet">
#stack('head')
#stack('style')
</head>
<body>
<div id="app">
#yield('main')
</div>
</body>
#stack('script')
</html>

jQuery functions and libraries not works if I include app.js in blade file,

I have vue.js component of pusher notification system in my Laravel app and I have to install tinymce for blog posts.
MY tinymce and other jquery functions stops working if i add js/app.js in my main layout blade file. but everything works with normal jquery 3.4.1 public folder link. it is important for me to add app.js because of vue.js components here is my files code
main_layout.blade.php
{{--<script src="{{asset('js/app.js')}}" ></script>--}}
<script src="{{asset('Assets/bootstrap4/jquery-3.4.1.min.js')}}" ></script>
<script src="{{asset('node_modules/tinymce/tinymce.min.js')}}"></script>
<script src="{{asset('node_modules/tinymce/jquery.tinymce.min.js')}}"></script>
<script src="{{asset('node_modules/tinymce/themes/silver/theme.js')}}"></script
<script src="{{asset('Admin/vendor/js-cookie/js.cookie.js')}}"></script>
<script src="{{asset('Admin/vendor/jquery.scrollbar/jquery.scrollbar.min.js')}}"></script>
<script src="{{asset('Admin/vendor/jquery-scroll-lock/dist/jquery-scrollLock.min.js')}}"></script>
<script src="{{asset('plugins/sweetalert/sweetalert.min.js')}}"></script>
<script src="{{asset('plugins/select2/dist/js/select2.js')}}"></script>
<script src="{{asset('Admin/js/argon.js')}}"></script>
<script src="{{asset('js/script.js')}}"></script>
<script type="text/javascript">
$(document).ready(function(){
$(".nav-link.collapseLink").click(function(){
$(this).children(".collapse").collapse('toggle');
});
})
</script>
#yield('javascript')
</body>
resources/js/bootstrap.js
window._ = require('lodash');
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: true,
encrypted: true,
authEndpoint: "/broadcasting/auth",
namespace:'App.Notifications',
});
resource/js/app.js
require('./bootstrap');
window.Vue = require('vue');
Vue.component('notifications', require('./components/Notifications.vue').default);
window.onload = function () {
var app = new Vue({
el: '#app',
});
}
I have checked all my code and not found any other mistake, please suggest any solution for this, if I uncomment js/app.js and comment public folder jQuery, then all other libraries gives errors like they doesn't have jQuery with them. i have also tried defer in app.js script link.
If use public folder jquery like i have shown below then all my jquery functions works and also tinymce but then i am unable to use that vue.js component
Thanks
You have to reformat your code.
Jquery script line should be before the app.js line Eg.
<script src="{{asset('Assets/bootstrap4/jquery-3.4.1.min.js')}}" ></script>
<script src="{{ asset('js/app.js') }}"></script>

Load external javascript to component dynamically

I am trying to load an external library (Javascript) to an Angular2 component (TypeScript).
Take example: https://github.com/fengyuanchen/cropperjs
My approach:
index.html
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/0.8.1/cropper.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/0.8.1/cropper.js"></script>
</head>
myCropper.js
window.addEventListener('DOMContentLoaded', function () {
var image = document.querySelector('#image');
var cropper = new Cropper(image, {
viewMode: 3,
dragMode: 'move',
autoCropArea: 1,
restore: false,
modal: false,
guides: false,
highlight: false,
cropBoxMovable: false,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
});
});
photo.component.ts
#Component({
selector: 'photo-crop',
template: `
<div class="row">
<img id="image" src="http://img01.ibnlive.in/ibnlive/uploads/875x584/jpg/2015/09/new-google-logo-010915.png" class="img-responsive"/>
<div class="row">
`,
styles: []
})
export class PhotoComponent {
public ngOnInit() {
this.loadScript('src/assets/js/myCropper.js');
});
}
public loadScript(url) {
console.log('preparing to load...')
let node = document.createElement('script');
node.src = url;
node.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(node);
}
}
Problem: the image is loaded without zoom/crop effect. I inspected the page and saw the script was added correctly in . I refreshed page, no luck. I had no error at all. It seems Angular2 does not activate the script.
I also tried a workaround: putting script in index.html directly (This workaround return error when the page is not loaded yet)
<head>
...
<script src="src/assets/js/myCropper.js"></script>
</head>
Photo is loaded without zoom/crop effect at start. But after I refresh the page, zoom/crop effect is activated. This is not a good practice where all scripts kept in index.html, but at least the script works after refresh.
Any suggestion is appreciated.

External library reference works in Webpack but not in JSPM within Aurelia

I am trying to use the Datatables.net library in my Aurelia application.
https://www.npmjs.com/package/datatables.net
The issue is that the following code works with the Webpack version of Aurelia. The JSPM build I get the error
mytable.js:13 Uncaught (in promise) TypeError: $(...).dataTable is not a function(…)attached # mytable.js:13attached # aurelia-templating.js:2947attached # aurelia-templating.js:1016attached # aurelia-templating.js:1472attached # aurelia-templating.js:1026attached # aurelia-templating.js:1472(anonymous function) # aurelia-framework.js:204
I added "datatables.net": "npm:datatables.net#^1.10.11", to my package.json and did jspm install -y and datatables.net was said it was installed.
ViewModel:
import $ from 'jquery';
import dataTable from 'datatables.net';
export class MyTable{
dataSet = [
['Ken','Husband','Home'],
['Barbie','Wife','Home']
];
attached(){
//console.log(dataTable);
var dataSet = this.dataSet;
//console.log(dataSet);
//require( 'datatables.net' )( window, $ );
$(() => $('#example').DataTable({
select: true,
data: dataSet,
columns: [
{ title: "Name" },
{ title: "Position" },
{ title: "Office" }
]
}) );
}
}
View
<template>
<div class="container" style="margin-top:20px">
<div>test datatables</div>
<table id="example" class="display" width="100%"></table>
</div>
</template>
It looks like it has already been setup in jspm: https://github.com/jspm/registry/blob/master/package-overrides/github/DataTables/DataTables#1.10.4.json
Simply install it via its alias:
jspm install datatables
Responsive has overrides too: and https://github.com/jspm/registry/blob/master/package-overrides/github/DataTables/Responsive#1.0.4.json
but I think you'll have to install it like:
jspm install github:DataTables/Responsive#1.0.4
When you are using jspm you don't need to change anything in package.json. You should install javascript libraries using jspm, like this:
jspm install npm:datatables.net
Then, you have to import it, using this:
import $ from 'jquery';
import 'datatables.net';
export class MyTable{
dataSet = [
['Ken','Husband','Home'],
['Barbie','Wife','Home']
];
attached(){
//console.log(dataTable);
var dataSet = this.dataSet;
$('#example').DataTable({
select: true,
data: dataSet,
columns: [
{ title: "Name" },
{ title: "Position" },
{ title: "Office" }
]
});
}
}
Hope this helps!
Resolved the issue. It was all in how I was adding the libraries to my project, how I was importing them, and a slight issue with the way JSPM loads the library (at least I think someone with more experience with Javascript can correct me).
The solution is at this link.
https://github.com/aurelia/skeleton-navigation/issues/473
A working example:
Add the following libraries to your project
jspm install datatables.net=npm:datatables.net
jspm install datatables.net-responsive=npm:datatables.net-responsive
jspm install datatables.net-responsive-bs=npm:datatables.net-responsive-bs
jspm install datatables.net-bs=npm:datatables.net-bs
Index.html:
<html>
<head>
<title>Aurelia</title>
<link rel="stylesheet" href="jspm_packages/npm/font-awesome#4.6.1/css/font-awesome.min.css">
<link rel="stylesheet" href="styles/styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app="main">
<div class="splash">
<div class="message">Aurelia Navigation Skeleton</div>
<i class="fa fa-spinner fa-spin"></i>
</div>
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
// ensure jQuery is loaded and set before other imports in you project
System.import('jquery')
.then(jquery => {
window.jQuery = jquery;
window.$ = jquery;
// now load and bootstrap aurelia
return System.import('aurelia-bootstrapper');
});
</script>
</body>
</html>
welcome.html:
<template>
<section class="au-animate">
<div class="container" style="margin-top:20px">
<div>test datatables</div>
<table id="example" class="table table-striped table-bordered dt-responsive nowrap" width="100%"></table>
</div>
</section>
</template>
welcome.js
import * as datatable from 'datatables';
//following only once in you app i think
import * as responsive from 'datatables.net-responsive';
import * as responsiveBs from 'datatables.net-responsive-bs';
import * as netBs from 'datatables.net-bs';
//This could be done an alternative way apparently (see below) but this is what worked for me. I have to give credit to the poster doktordirk on the github aurelia issue.
responsive.default(window, $)
responsiveBs.default(window, $)
netBs.default(window, $)
//alternative method
//let responsive = responsive.default(); // to change settings?
//responsiveBs.default();
//netBs.default();
export class Welcome {
dataSet = [
['Ken','Husband','Home'],
['Barbie','Wife','Home']
];
attached() {
// can call: responsive(settings, options);
$('#example').DataTable({
select: true,
data: this.dataSet,
columns: [
{ title: "Name" },
{ title: "Position" },
{ title: "Office" }
]
});
}
}

PhantomJS not playing nice with RequireJS+Jasmine

I have some tests running with RequireJS and Jasmine. I have a Jasmine test harness file that looks like this:
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="./Scripts/jasmine/jasmine.css" />
<script type="text/javascript" src="./Scripts/jasmine/jasmine.js"></script>
<script type="text/javascript" src="./Scripts/jasmine/jasmine-html.js"></script>
<script type="text/javascript" src="./Scripts/jasmine/boot.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js"></script>
<script type="text/javascript">
require(["fakeTest"], function () {
window.onload();
});
</script>
</head>
<body>
</body>
</html>
My fakeTest file is very simple:
define(["require", "exports"], function (require, exports) {
describe("fake test", function () {
it("test nothing", function () {
expect(1).toEqual(1);
});
});
});
If I run this in FireFox/Chrome then everything works fine; I see one test and that it passed. If I run this with PhantomJS though, I start getting problems. Running it with the remote debugger flag I get the error:
Error: Cannot find module 'fakeTest'
phantomjs://bootstrap.js:299 in require
phantomjs://bootstrap.js:263 in require
If I try changing my harness file so that it says requirejs[("fakeTest"...... instead of just require, I get this error:
Error: Script error for "fakeTest"
http://requirejs.org/docs/errors.html#scripterror
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:140
in defaultOnError
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:544
in onError
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1732
in onScriptError :0 in appendChild
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1952
in load
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1679
in load
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:829
in load
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:819
in fetch
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:851
in check
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1177
in enable
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1550
in enable
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1162
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:131
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:56
in each
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1114
in enable
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:783
in init
https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js:1453
If I put in a completely invalid module name, I get the same errors in both cases.
I'm totally lost as to why this is happening. I've played around with changing the path for fakeTest in the harness file but nothing changes. I've simplified the harness file as much as I could, but since I'm still seeing this i'm not sure what else to try. Anyone have any ideas?
edit
I've removed everything to do with Jasmine and just have fakeTest do an alert. Now I get errors saying
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.20/require.js"></script>
<script type="text/javascript">
require(["fakeTest"], function () {});
</script>
</head>
<body>
</body>
</html>
and
define(["require", "exports"], function (require, exports) {
alert('foo');
});
"ReferenceError: Can't find variable: requirejs"
Instead of write html use karma with requirejs plugin.
karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['jasmine', 'requirejs'],
files: [
{pattern: 'Scripts/**/*.js', included: false},
{pattern: 'test/*.js', included: false},
'test/test-main.js'
],
// list of files to exclude
exclude: [],
browsers: ['PhantomJS']
});
};
test/test-main.js
var TEST_REGEXP = /(spec|test)\.js$/i;
var allTestFiles = [];
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule);
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
// example of using a couple path translations (paths), to allow us to refer to different library dependencies, without using relative paths
paths: {
// Put Your requirejs config here
},
// example of using a shim, to load non AMD libraries (such as underscore)
shim: {
},
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
This is example files. Fix it and run
karma run
Instead of
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js"></script>
use
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js"
data-main="Tests/main"></script>
Move test files to Tests directory.
In Tests/main.js use Your requirejs config and run main tests file.
var deps = ['Tests/fakeTest'];
require.config({
baseUrl: '..',
paths: {
'jasmine': ['Scripts/jasmine//jasmine'],
'jasmine-html': ['Scripts/jasmine/jasmine-html'],
'jasmine-boot': ['Scripts/jasmine/boot']
},
// shim: makes external libraries compatible with requirejs (AMD)
shim: {
'jasmine-html': {
deps : ['jasmine']
},
'jasmine-boot': {
deps : ['jasmine', 'jasmine-html']
}
}
});
require(['jasmine-boot'], function () {
require(deps, function(){
//trigger Jasmine
window.onload();
})
});
In index.html run only Tests/main.js file:
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="./Scripts/jasmine/jasmine.css" />
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js" data-main="Tests/main"></script>
</head>
<body>
</body>
</html>

Categories