I would like to use the Aladin Lite app on my React app.
When building a site without React, it is very simple to embed the app in a div by doing:
<!-- include Aladin Lite CSS file in the head section of your page -->
<link rel="stylesheet" href="https://aladin.u-strasbg.fr/AladinLite/api/v2/latest/aladin.min.css" />
<!-- you can skip the following line if your page already integrates the jQuery library -->
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.1.min.js" charset="utf-8"></script>
<!-- insert this snippet where you want Aladin Lite viewer to appear and after the loading of jQuery -->
<div id="aladin-lite-div" style="width:400px;height:400px;"></div>
<script type="text/javascript" src="https://aladin.u-strasbg.fr/AladinLite/api/v2/latest/aladin.min.js" charset="utf-8"></script>
<script type="text/javascript">
var aladin = A.aladin('#aladin-lite-div', {survey: "P/DSS2/color", fov:60});
</script>
Where you then have an object aladin to use in Javascript.
How would I go about using this app on my React page? It was not built for React and uses jquery.
I need to be able to access its props to change the field of view of the sky which in Javascript is done by:
aladin.setFov(1)
Would this be a good time for React portals?
Thank you.
Create a React component that will render Aladin sky map (so there will be no Aladin anywhere else). Then, you can define and configure aladin inside componentDidMount (if you are using class components) or React.useEffect (if you are using hooks).
Index.html:
...
<head>
<link rel="stylesheet" href="https://aladin.u-strasbg.fr/AladinLite/api/v2/latest/aladin.min.css" />
<!-- you can skip the following line if your page already integrates the jQuery library -->
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.1.min.js" charset="utf-8"></script>
<!-- insert this snippet where you want Aladin Lite viewer to appear and after the loading of jQuery -->
<script type="text/javascript" src="https://aladin.u-strasbg.fr/AladinLite/api/v2/latest/aladin.min.js" charset="utf-8"></script>
</head>
...
Aladin.jsx:
const Aladin = () => {
React.useEffect(() => {
let aladin = A.aladin('#aladin-lite-div', { survey: 'P/DSS2/color', fov:60 })
aladin.setFov(1)
}, [])
return (
<div id='aladin-lite-div' style={{ width: '400px', height: '400px' }} />
)
}
export default Aladin
Then, everywhere you want to render Aladin sky map:
import Aladin from './Aladin'
...
<Aladin />
Just an update to Michal's answer.
let aladin = window.A.aladin('#aladin-lite-div', { survey: 'P/DSS2/color', fov:60 })
The function A.aladin can't be called straightaway since it is an external JavaScript function.
Related
I want to implement this into my Next.js App
https://codepen.io/Lemonzillah/pen/rmQLRm
I tried to add both libraries needed for this to work in the _document.js file and then link the js code in text-slider from /public
<Main />
<NextScript />
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.5.9/slick.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="public/text-Slider.js"></script>
But it ain't working, somehow - it doesn't show any error. It's just now working - hope you can help me!
First of all. It is recommended to not use jquery in react or next js app.
Then if you want to use jquery in next js app you can use next docuemnt..
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head>
**Here you can use custom css link or font link like bootstrap cdn
</Head>
<body>
<Main />
<NextScript />
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.5.9/slick.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="public/text-Slider.js"></script>
</Html>
)
}
}
export default MyDocument
You can use now slick by calling slick slider cdns link in script and css. Ans use them. It is recommend to use React slick in next js app
I want to use firebase inside a Vue JS component, but it seems like the firebase object is loaded after the creation of my component.
Is there a way to wait for firebase to load before executing JS code ?
Exemple : i want to create a vue composant called loader which output the firebase object on the webconsole at his creation
<html>
<head>
<!-- Firebase -->
<script defer src="/__/firebase/5.0.4/firebase-app.js"></script>
<!-- include only the Firebase features as you need -->
<script defer src="/__/firebase/5.0.4/firebase-auth.js"></script>
<script defer src="/__/firebase/5.0.4/firebase-database.js"></script>
<script defer src="/__/firebase/5.0.4/firebase-messaging.js"></script>
<script defer src="/__/firebase/5.0.4/firebase-storage.js"></script>
<!-- initialize the SDK after all desired features are loaded -->
<script defer src="/__/firebase/init.js"></script>
<!-- Vue.js-->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
</head>
<body>
<div id="app"></div>
<script>
var loader = {
template: '<div></div>',
created: function(){
console.log(window.firebase); // undefined
}
};
var app = new Vue({
el : '#app',
template :
`<div>
<loader></loader>
</div>`,
components : {
'loader' : loader
}
});
</script>
</body>
</html>
It doesn't work but, of course, one second later i can output the firebase object on the console.
PS :
It is my first question on this website so if you have any advice on how to ask question, i will take it as well.
I am french so pardon my english
You need to remove the defer attributes from the firebase scripts. It will cause the scripts to be executed once the whole document has been parsed, which means that your script in the body runs before firebase scripts.
I am setting up an architecture for an MVC6 app, and I'm relying heavily on ViewComponents. My goal is to let each ViewComponent have its own javascript section, but from reading here rendersection does not work with ViewComponents so I've been trying to do it in another way.
In my _Layout.cshtml
I have this part in just before the closing of the body tag:
#{Html.RenderPartial("_LayoutScriptsPartial"); }
In _LayoutScriptsPartial
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/app.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js">
</script>
<script src="~/js/app.min.js" asp-append-version="true"></script>
</environment>
Now in one of my components at /Views/Shared/Components/MyComponent/Default.cshtml I reference another partial view that has this content, it's for a carousel ViewComponent
#model MyProj.MyViewModel
#{Html.RenderPartial("_LayoutScriptsPartial"); }
#if (!string.IsNullOrEmpty(Model.ImageUrl))
{
<script type="text/javascript">
var cssClass= "#Model.cssClass";
var imageUrl = "#Model.ImageUrl";
webbCore.carouselSetBackgroundImage(cssClass, imageUrl);
</script>
}
Only reason I had to do this was to have all required js files available for my view component.
As you can see, I reference _LayoutScriptsPartial multiple times. When I debug using chromes f12 and watching the network section, I do not se the same javascript files being downloaded multiple times. Still I have a bad feeling about this solution. I have looked around and have not found any good solutions for working with js files and ViewComponents that I really liked. Something like this would suit my needs.
My question: how good is this solution, whats the pros and cons and are there any better ways to work with js files and ViewComponents?
There are 3 main cases for an ideal solution to your problem:
ViewComponent is added 0 times and the corresponding JavaScript library is added 0 times
ViewComponent is added 1 time, the corresponding JavaScript library is added 1 time and the dynamically created initialization JavaScript is created once and placed after the library.
ViewComponent is added many times, the corresponding JavaScript library is added 1 time and the dynamically created initialization JavaScript is created for each ViewComponent and are all placed after the library.
So in your example, jquery and app.js are your libraries while your dynamically created initialization JavaScript is the part that references #Model in your <script type="text/javascript"> tag. Let's say we added your component to a view 3 times (I'll replace #RenderBody() with the resulting html from a view that invokes your component 3 times):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - MyProj.Web</title>
<environment names="Development,Staging,Production">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/lib/font-awesome/css/font-awesome.css" />
<link rel="stylesheet" href="~/css/site.css" />
<link rel="stylesheet" href="~/css/culture-flags.css" />
</environment>
</head>
<body>
<header>#Html.Partial("~/Views/Shared/_Header.cshtml")</header>
<main>
<nav></nav>
<article>
<div class="container body-content">
<!--#RenderBody()-->
<!--#await Component.InvokeAsync("MyComponent", new MyViewModel {cssClass="t1", ImageUrl="1.jpg"})-->
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/app.js" asp-append-version="true"></script>
<script type="text/javascript">
var cssClass= "t1";
var imageUrl = "1.jpg";
webbCore.carouselSetBackgroundImage(cssClass, imageUrl);
</script>
<!--#await Component.InvokeAsync("MyComponent", new MyViewModel {cssClass="t2", ImageUrl="2.jpg"}) -->
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/app.js" asp-append-version="true"></script>
<script type="text/javascript">
var cssClass= "t2";
var imageUrl = "2.jpg";
webbCore.carouselSetBackgroundImage(cssClass, imageUrl);
</script>
<!--#await Component.InvokeAsync("MyComponent", new MyViewModel {cssClass="t3", ImageUrl="3.jpg"}) -->
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/app.js" asp-append-version="true"></script>
<script type="text/javascript">
var cssClass= "t3";
var imageUrl = "t3.jpg";
webbCore.carouselSetBackgroundImage(cssClass, imageUrl);
</script>
</div>
</article>
<aside></aside>
</main>
<footer>#Html.Partial("~/Views/Shared/_Footer.cshtml")</footer>
<!-- These are the libraries that should only be loaded once -->
<environment names="Development,Staging,Production">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<!-- Ideally this is where the dynamically create scripts would go -->
#RenderSection("scripts", required: false)
</body>
</html>
As you can see, you would be loading the jquery library 4 times, once for your Layout and 3 times for your ViewComponents. Any good browser should only download the file once but will be loaded into memory multiple times and will just overwrite the the same global variables multiple times($ for example).
You might also be tempted to move the library to the top of the Layout and remove the references from the View Component but that is not a best practice either.
The main issue is that section doesn't work with ViewComponents and that appears to be by design. You should think of a ViewComponent as a fancy html helper. I haven't seen any great solutions to this problem but here are a couple of ideas.
Within the View, immediately after you call your component (Component.InvokeAsync("MyComponent")), add your javascript to #section scripts {...}
Create a library js that initializes this component and set data attributes from the element
$(".carousel").each(function() {
var css = $(this).data("carousel-css");
var image = $(this).data("carousel-image");
});
<input class="carousel" type=hidden data-carousel-css="#Model.cssClass" data-carousel-image="#Model.imageURL" />
I'm using Angular 2 to build my web application. When I try to put a tooltip or popover on an image or button, I get the default-looking tooltip instead of the bootstrap one.
I've tried the basic W3Schools examples and did everything as shown, yet it doesn't work.
I believe my problem lies with the correct imports of the bootstrap.js or jQuery, but other bootstrap items like buttons etc. do work properly.
(I use nodejs to install the necessary files/dependencies -> npm install npm install bootstrap npm install jquery)
index.html
<html>
<head>
<base href="/"><!--Without this tag, the browser may not be be able to load resources (images, css, scripts) when "deep linking" into the app. Bad things could happen when someone pastes an application link into the browser's address bar or clicks such a link in an email link. -->
<title>Factory</title>
<link type="text/css" rel="stylesheet" href="/css/styles.css">
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<script src="/node_modules/angular2/bundles/http.dev.js"></script>
<!--<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">-->
<!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>-->
<!--<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>-->
<!--<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />-->
<!-- stackoverflow suggested settings -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
</head>
<body>
<my-app></my-app>
</body>
</html>
page-with-tooltip(.ts)
import {Component} from "angular2/core";
import ... from ...;
import ... from ...;
...
#Component({
template: `
<div *ngIf="hall" class="container">
<h2>Detail van hal <small>{{hall.name}}</small></h2>
Hover over me
<div class="container">
<div class="hall-box-single">
<div class="hall-box"
[style.width]="hall.areaWidth*4"
[style.height]="hall.areaHeight*4">
<div class="image-container">
<div *ngFor="#item of hall.items">
<a data-toggle="tooltip" title="Popover title">
<img [src]="item.image"
[style.left]="item.posX"
[style.top]="item.posY"/>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip();
});
</script>
`})
export class HallDetailComponent implements OnInit {
...
constructor(...) {
...
}
ngOnInit() {
...
(<any>$('[data-toggle="tooltip"]')).tooltip();
$('[data-toggle="tooltip"]').tooltip();
}
}
!Edit!
Added suggestions from users as well as an extract of the running webpage source.
The script tag you wrote in your template is getting ignored, run your JS code from inside the component instead, I suggest you to run it in the ngOnInit() method since you are implementing the OnInit interface.
This should work:
#Component({
selector: 'app',
template: `
Hover over me
`
})
export class AppComponent{
ngAfterViewInit(){
$('[data-toggle="tooltip"]').tooltip();
}
}
using:
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
So specific to your project:
You have three options to fix it:
One is to set a nasty timeout so it initiates the tooltips until you get a response back from the server and they have actually rendered.
The second is to find some method like the ones we try that gets executed everytime the dom changes, not just the first time.
The third and best but a bit more complicated is by implementing a method that gets executed before the page starts rendering, and if you return a promise in that method, the page will wait for the Promise to get done before rendering, so you can return a promise and resolve the promise until you get the answer from the service, that way the dom will be ready the first time the controller loads
I believe the last method is called CanActivate or something like that.
Okay, I have a pretty basic site I'm working on that I'm now modifying to use a MEAN stack and thus I'm getting started with Angular. I'm using Scotch.io's MEAN starter App as a base to get started. So far, it's been pretty easy, I've got key components in templates and added them using ng-include.
HTML
<title>First Angular Page</title>
<!-- CSS -->
<link rel="stylesheet" href="libs/font-awesome/css/font-awesome.min.css"> <!-- Font Awesome -->
<link href='http://fonts.googleapis.com/css?family=Quicksand:700|Montserrat:700|Open+Sans|Sniglet:400,800' rel='stylesheet' type='text/css'> <!-- Google Fonts -->
<link rel="stylesheet" href="css/mainStyles.css"> <!-- Stephie's styles -->
<!-- JS -->
<script src="libs/angular/angular.min.js"></script>
<script src="libs/angular-route/angular-route.min.js"></script>
<!-- ANGULAR CUSTOM -->
<script src="js/controllers/MainCtrl.js"></script>
<script src="js/controllers/NerdCtrl.js"></script>
<script src="js/services/NerdService.js"></script>
<script src="js/appRoutes.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="sampleApp" ng-controller="NerdController">
<!-- NAVAGATION -->
<div ng-include='"templates/navagation.html"'></div>
<div id="site-canvas">
<!-- HEADER -->
<div ng-include='"templates/header.html"'></div>
<div id="page-content">
<!-- ANGULAR DYNAMIC CONTENT / UNIQUE PAGE FRAGMENT -->
<div ng-view></div>
</div> <!-- #page-content -->
<!-- FOOTER -->
<div ng-include='"templates/footer.html"'></div>
</div><!-- #site-canvas -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/menu.js"></script>
</body>
</html>
But now I've got problems, my menu.js file isn't working. It consists pretty much entirely of add/removeClass methods using jQuery.
Here's an old Code Pen of the site I'm working on in basic HTML to demostrate how it's supposed to work.
http://codepen.io/StuffieStephie/pen/BNqJVX
function toggleNav() {
if ($('#drawer').hasClass('show-nav')) {
$('#drawer').removeClass('show-nav');
$('#nav-icon').removeClass('open');
$("nav li.gotsMenus").removeClass("showSub");
} else {
$('#drawer').addClass('show-nav');
$('#nav-icon').addClass('open');
$("nav li.gotsMenus").removeClass("showSub");
}
}
$('#closeButton, #site-canvas, nav li li').click(function() {
$('#drawer').removeClass('show-nav');
$('#nav-icon').removeClass('open');
$("nav li.gotsMenus").removeClass("showSub");
});
But this doesn't work with my Angular templates. (Or at least, the click and hover functions don't. The scroll function that auto hides the header still works mysteriously ...? So it's kinda working)
So.. where to begin? I'm sorry if this is a really dumb question but I'm new to Angular and I've been spinning my wheels for a couple of hours now. Do I put this in a directive or controller or module or what? Do I have to rewrite this in vanilla js? And even if I did, I have other jQuery dependencies (I have an image gallery powered by Tumblr's JSON API that uses a jQuery-dependent lightbox, among other things).
If someone can just point me in the right direction I would be so grateful ;_;
Sounds like a race condition, when the script executes, there might not a #menuHeader in the DOM. You may need to add the code to the load callback using a delegate. So like:
$("#menuHeader").on('load', function () {
// Put menu.js code here
});
I would put a break point and figure out what's actually in the DOM when this executes. And basically figure out what it takes to load up the DOM first, then run the script.