Rails 7 + ImportMaps/whatever + TailwindCSS + JS = Boggled - ruby-on-rails

First, I'm much more of a Rails back end person. The JS world today scares me. I know this is a super basic question, but I've racked my brain for a solid couple days trying to figure, this out. I don't know why I can't put a CDN link somewhere in my HTML and get all the JS I need. Those were the good ol' days...
Anyway, I have a nearly fresh Rails 7 app that uses import-maps (do they all?) and I'm trying to get a dropdown "component" from https://tailwindui.com/preview (the first navbar from that page) working. It starts popped open, no hover effects, and is unable to close. My goal is to use more of those components, but all the docs I read seem to leave me thinking there's a missing piece I'm not understanding.
Gemfile contains gem "tailwindcss-rails", "~> 2.0" # github: "rails/tailwindcss-rails"
app/assets/stylesheets/application.tailwind.css:
#tailwind base;
#tailwind components;
#tailwind utilities;
app/assets/javascript/application.js
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
// what else needs to go here???
config/tailwind.config.js
// const defaultTheme = require('tailwindcss/defaultTheme')
// module.exports = {
// content: [
// './app/helpers/**/*.rb',
// './app/javascript/**/*.js',
// './app/views/**/*'
// ],
// theme: {
// extend: {
// fontFamily: {
// sans: ['Inter var', ...defaultTheme.fontFamily.sans],
// },
// },
// },
// plugins: [
// require('#tailwindcss/forms'),
// require('#tailwindcss/aspect-ratio'),
// require('#tailwindcss/typography'),
// ]
// }
What else do I need to put where to get this working? Thank you kindly for filling in the missing pieces in my brain.

I know it's been a while since you've asked this question, yet I've been fighting this thing recently and I'd like to talk about what I've found, in case anybody's wondering.
So, Tailwind UI provides components in 3 variants: HTML, React, and Vue. If you pick HTML, you'll have to figure out how to write your own JavaScript. this answer mentions that, but I'll elaborate on that point, though.
Aside from mentioning "do your own JavaScript" on their website, they also give us instructions how exactly we should style our components when we add JavaScript:
<!--
Dropdown menu, show/hide based on menu state.
Entering: "transition ease-out duration-100"
From: "transform opacity-0 scale-95"
To: "transform opacity-100 scale-100"
Leaving: "transition ease-in duration-75"
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
Yet, that doesn't really tell us that we must code it ourselves. Surely, there's something we're missing, right? Turns out, not really.
Basically, the "dynamic" aspect of the layout is implemented via Headless UI, a set of components developed & maintained by the same people. It only has three public packages: #headlessui/vue, #headlessui/react and #headlessui/tailwindcss.
I ran npm i #headlessui/tailwindcss and added #headlessui/tailwindcss to the plugins, but it didn't really do much. If you inspect the source code for the package, you'll find a pretty tiny index.js which only adds some utility classes. So that didn't help and I had to scratch it.
So far it seems the most viable option is to grab a React or Vue version of the template and integrate those into your pipeline. Otherwise you'll have to write a bunch of JS to basically reimplement headless UI yourself.
I'm still looking for an importmap-based solution to integrate Vue, while webpack should be pretty much straightfoward.

There is no JavaScript in their HTML code. On TailwindUI homepage, they explain:
Accessible, interactive examples for React and Vue powered by
Headless UI, plus vanilla HTML if you’d rather write any necessary JS
yourself.
So I guess in this case you have to write the necessary JS yourself.

Related

Getting paperjs to work in an electron app

Another learning project in the works... I am trying to use paperjs in an electron app.
According to the instructions, I think I should be using paper-jsdom (please correct me if I'm wrong). BTW, I am using TypeScript if that makes a difference. I have an HTML document with nothing but an empty <canvas> and a <script> tag referencing this:
import paper, {Color, Point, Path} from 'paper-jsdom'
window.onload = (): void => {
let canvas = document.getElementById("workspace") as HTMLCanvasElement;
paper.setup(canvas);
let path = new Path();
path.strokeColor = Color.random();
let start = new Point(100, 100);
path.moveTo(start);
path.lineTo(start.add(new Point(200, -50)));
paper.view.update();
};
So right off the bat I get:
Uncaught TypeError: paper_jsdom_1.Path is not a constructor
Ugh... So I tried a few random things (it's late, I'm tired...) and changing my import to:
import paper from 'paper'
import {Color, Point, Path} from 'paper-jsdom'
works, or at least the code above works.
Am I supposed to be importing some things from 'paper' and others from 'paper-jsdom'? What is the correct way to use paperjs in an electron app?
Unfortunately paper-jsdom doesn't seem to have any type info for TS.
Thanks!!
Since you are using Paper.js in the renderer process of Electron, you are using it in the browser context and not in Node.js context so you should use the common paper package which relies on browser Canvas API (and not paper-jsdom which targets browserless usage).
So you should be able to use Paper.js as you would for a website.
From your code example, I see that you are using TypeScript so you can have a look at this simple quickstart project that I made to play with Paper.js and TypeScript.
It uses this kind of import:
import * as paper from 'paper';
And then access Paper.js classes through the imported paper object:
new paper.Path.Circle({
center : paper.view.center,
radius : 50,
fillColor: 'orange',
});
Edit
Here is a repository showing the simplest way of using Paper.js in an Electron app.

Cannot get Cordova text-to-speech plugin to work

I'm trying various plugins for TTS, including the one at https://github.com/vilic/cordova-plugin-tts, but cannot get any to work. For this one, for example, according to the docs, its usage should be:
TTS
.speak('hello, world!', function () {
alert('success');
}, function (reason) {
alert(reason);
});
but I get 'TTS not defined'. Also tried 'navigator.TTS....' but still no good. Also I'm unsure whether I need to include the tts.js in the package; if so I get 'exports not defined'. If anyone is successfully using this plugin, please can you put me in the correct direction? Or if there's an alternative plugin that works, I could use that, but many TTS plugins on GitHub appear unsupported for 3-4 years.
BTW other plugins I am using (e.g. geolocation) are working fine
Have now solved this. I didn't have <script src="cordova.js"></script> in my index.html. This was also stopping 'onDeviceReady' from firing, which is how I came about solving it.
So it seems you need this script included for some plugins but not for others. How confusing.
Can I claim back my 50 bonus points for solving it myself? ;)
Prefer with keyword window
window.TTS.speak({
text: 'hello world!!',
locale: 'en-GB',
rate: 1.3
}, function () {
// Do Something after success
}, function (reason) {
// Handle the error case
});
I tried the same way it worked for me.
Thanks,
Praveen

.NET/MVC4/Jquery Mobile/Knockout/Chrome/iPhone extra # character in URL

Okay, if I could offer a bounty for this I would - I offer virtual karma.
As mentioned in the title I have an .NET/MVC4/Jquery Mobile/Knockout website. On the index page there is a button
<button data-bind="click: getResults" data-theme="f">Search</button>
which calls a javascript function
$.mobile.navigate("/results?option1=a&option2=b", { transition: amw.transitions.slide });
This works great on all browsers and devices except Chrome/iPhone. As far as I can tell the version of Chrome or iOS does not matter. The resulting URL in the address bar is
iPhone/Chrome: http://www.mywebsite.com/#/results?option1=a&option2=b
Other Devices: http://www.mywebsite.com/results?option1=a&option2=b
I have put alerts throughout jQuery mobile to try and figure out what is going on (if someone knows a way to debug chrome on iOS let me know) and I cannot see where the extra # is being added.
This may not seem like a big deal but the url ends up being passed on to a downstream service that really does not like the extra #.
I can put in a hack at the call to the service to strip out the # but I would really like to figure out what is happening.
The only suspect line I can find in jQuery mobile (1.3.0) is line #2298
// if the hash is included in the data make sure the shape
// is consistent for comparison
if( data.hash && data.hash.indexOf( "#" ) === -1) {
data.hash = "#" + data.hash;
}
But I am not sure what this does or why it would occour only on Chrome/iPhone.
so StackOverflow people - what is going on?
Thanks.

"document" in mozilla extension js modules?

I am building Firefox extension, that creates single XMPP chat connection, that can be accessed from all tabs and windows, so I figured, that only way to to this, is to create connection in javascript module and include it on every browser window. Correct me if I am wrong...
EDIT: I am building traditional extension with xul overlays, not using sdk, and talking about those modules: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules
So I copied Strophe.js into js module. Strophe.js uses code like this:
/*_Private_ function that creates a dummy XML DOM document to serve as
* an element and text node generator.
*/
[---]
if (document.implementation.createDocument === undefined) {
doc = this._getIEXmlDom();
doc.appendChild(doc.createElement('strophe'));
} else {
doc = document.implementation
.createDocument('jabber:client', 'strophe', null);
}
and later uses doc.createElement() to create xml(or html?) nodes.
All worked fine, but in module I got error "Error: ReferenceError: document is not defined".
How to get around this?
(Larger piece of exact code: http://pastebin.com/R64gYiKC )
Use the hiddenDOMwindow
Cu.import("resource://gre/modules/Services.jsm");
var doc = Services.appShell.hiddenDOMWindow.document;
It sounds like you might not be correctly attaching your content script to the worker page. Make sure that you're using something like tabs.attach() to attach one or more content scripts to the worker page (see documentation here).
Otherwise you may need to wait for the DOM to load, waiting for the entire page to load
window.onload = function ()
{
Javascript code goes here
}
Should take at least diagnose that issue (even if the above isn't the best method to use in production). But if I had to wager, I'd say that you're not attaching the content script.

error on firefox: $.widget is not a function

I have a few multiselect boxes from the Jquery UI on a page that work perfectly well in Chrome & Safari but not in Firefox for some reason... when I load the Error Console in Firefox I see:
Error: $.widget is not a function
Source File: http://localhost:3000/javascripts/jquery.multiselect.js?1302660373
Line: 563
Any ideas why?
edit: the line itself is within the open function right where it says "// react to option changes after initialization"
// open the menu
open: function(e){
var self = this,
button = this.button,
menu = this.menu,
speed = this.speed,
o = this.options;
widget: function(){
return this.menu;
},
// react to option changes after initialization
_setOption: function( key, value ){
var menu = this.menu;
switch(key){
case 'header':
menu.find('div.ui-multiselect-header')[ value ? 'show' : 'hide' ]();
I am assuming you are using the jQuery Multiselect plugin… which depends on jQuery UI.
Sounds like you have not included enough of the jQuery UI library or just none of it. You need to include the core parts of jQuery UI (including Widget) if you build a custom download. Or just download the whole jQuery UI and include it instead.
For anyone else who is getting this but has the requirements; make sure you are including the Javascript files in the correct order. This error was being caused by my jquery-ui.js being included after the multiselect js file.
This answer is probably unrelated to the situation of the questioner, but I put it here for the sake of others Googling the question.
I got this error using Rails 3.2 and fixed it by deleting (renaming) the public/assets folder. It seems there are a lot of problems with the assets pipeline still. I don't know the details but have had other Javascript failures that are fixed this way.
Actually if you are getting this error then it's either
a) per #andyb answer - you haven't included the correct jQuery UI components
OR
b) your DOM is not loaded yet with the correct $.widget and therefore your function is attempting to call before $.widget has loaded. to fix the problem, ensure $.widget is called BEFORE your function

Resources