Javascript code not working in Ruby on Rails - javascript

I was trying to do my front-end with this Codepen Template but when i'm trying to click on the signup button, it's not changing to signup form for which the code is in the index.js file, i've included hte index.js file in the login.html.erb but when i'm running the rails server the transition isn't working. My Rails Project, Codepen Template
Here is the javascript code in index.js
document.querySelector('.img__btn').addEventListener('click', function() {
document.querySelector('.cont').classList.toggle('s--signup'); });

Try changing the path of index.js Add this line in app.html for including index js file .
<%= javascript_include_tag "index" %>

Wrap your current JS code in app/assets/javascripts/application.js within a DOMContentLoadListener event listener:
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('.img__btn').addEventListener('click', function() {
document.querySelector('.cont').classList.toggle('s--signup');
});
});

Related

How and where to add JQuery in Module project in DotnetNuke(DNN)?

I am beginner in DotnetNuke. I am creating a project which provide a Module that can be add in DotnetNuke based website.
I have configured www.dnndev.me in my IIS server and created project in DesktopModule folder of it. I can create, build and add my module to www.dnndev.me successfully but I don't know where to add JQuery in Solution Explorer of my module project.
1- Where should I add my JS and CSS files? I have tried by adding a folders "Assets", "Assets/CSS", "Assets/JS" and put my files there in my solution explorer.
2- How to include JS/CSS files in ascx page?
I have tired by following
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="View.ascx.cs" Inherits="CustomerDemo.Modules.CustomerDemo.View" %>
<dnn:DnnCssInclude runat="server" FilePath="~/DesktopModules/CustomerDemo/Assets/JS/fullcalendar.min.js" />
<dnn:DnnCssInclude runat="server" FilePath="~/DesktopModules/CustomerDemo/Assets/JS/jquery-ui-timepicker-addon.js" />
By above way .js shows in my source of webpage but it doesn't call. But if I try by following way, it works
<script type="text/javascript">
$(document).ready(function () { $.getScript("http://www.dnndev.me/DesktopModules/CustomerDemo/Assets/JS//jquery-ui-timepicker-addon.js?_=1483026285109", function () {
if ($('.mmdd').length > 0) {
$(".mmdd ").datetimepicker();
}
});
});
</script>
Can anybody please suggest me how and where to place .js and '.css' files and how to include them in project?
I am using: Visual Studio 2015 & DotnetNuke 8 Commnunity
File path confusion:
This is my physical location of folder when I open by Right Click--> Open with folder explorer
F:\websites\dnndev.me\DesktopModules\CustomerDemo\CustomerDemo\Assets
But when I drag CSS or JS file from file explorer to ascx design page, it use this location: "~\DesktopModules\CustomerDemo\Assets\file.css"
you can see that the physical path has 2 folder of CustomerDemo and the file dragged from solution explorer having path with only 1 CustomerDemo folder.
I don't understand this mechanism. Which one should I use? Can somebody clear my mind for this?
I have tried this way as one of the suggestion but it looks like I am missing something
Use the DnnJsInclude control of the Client Resource Management for registering scripts instead of the DnnCssInclude.
In your .ascx:
<%# Register TagPrefix="dnn" Namespace="DotNetNuke.Web.Client.ClientResourceManagement" Assembly="DotNetNuke.Web.Client" %>
<dnn:DnnJsInclude runat="server" FilePath="~/DesktopModules/CustomerDemo/Assets/JS/fullcalendar.min.js" />
OR in your code behind, you could instead use the ClientResourceManager API:
protected void Page_PreRender(object sender, EventArgs e)
{
ClientResourceManager.RegisterScript(this.Page, base.ControlPath + "/Assets/JS/fullcalendar.min.js", 100);
ClientResourceManager.RegisterScript(this.Page, base.ControlPath + "/Assets/JS/jquery-ui-timepicker-addon.js", 100);
ClientResourceManager.RegisterStyleSheet(this.Page, base.ControlPath + "/Assets/CSS/module.css", 100);
}

Include Javascript on Certain Pages in Phoenix Framework Application

I've got a bit of Javascript that I only want to include on certain pages in my Phoenix application.
Right now I've got the Javascript inside a script tag in myapp/web/templates/post/form.html.eex.
I understand that I can move the JavaScript to web/static/js/app.js ...but I don't want to include the Javascript on every page (it's only required on 2 specific pages).
What's the best way to load this section of Javascript on certain pages in my application without duplication the code and violating the DRY principle?
1.
Put all that javascript from form.html.eex into its own file (maybe something like js/posts.js).
Add this at the bottom:
export var Post = { run: function() {
// put initializer stuff here
// for example:
// $(document).on('click', '.remove-post', my_remove_post_function)
}}
2.
In your app.html, under <script src="#{static_path(#conn, "/js/app.js")}"></script> add this:
<%= render_existing #view_module, "scripts.html", assigns %>
3.
Then, in your view (probably views/post_view.ex), add a method like this:
def render("scripts.html", _assigns) do
~s{<script>require("web/static/js/posts").Post.run()</script>}
|> raw
end
Conclusion
Now the javascript file post.js will only be loaded when the post view is being used.
Here is one way to achieve this.
The JavaScript you have in the script tag, you move that into a separate file.
You divide your "regular" javascript (to be included in every page) and this custom javascript (to be included in some specific pages) into separate directories. e.g. app/common/standard.js and app/custom/unique.js
You modify your brunch-config.js to as follows:
module.exports = {
files: {
javascripts: {
joinTo: {
'custom.js': /^app[\\\/]common[\\\/][\S*?]\.js/,
'app.js': /^app[\\\/]common[\\\/][\S*?]\.js/
}
}
}
Then you include app.js in all pages,
<script src="<%= static_path(#conn, "/js/app.js") %>"></script>
but custom.js only in page (or layout) templates that need it.
<script src="<%= static_path(#conn, "/js/custom.js") %>"></script>
Another way is to make use of page-specific classes/elements. For example, the following code in app.js will ensure that the code only gets executed on the lesson/show page, since only that page has an element with the id #lesson-container:
import { startLesson } from './lesson/show.ts';
if (document.querySelector('#lesson-container')) {
startLesson();
}
This is based on Gazler's comment on the question and is a slightly more general answer than the one submitted by cmititiuc. You don't strictly need to wrap your page-specific JavaScript code like in that answer, nor do anything beyond import your page-specific file in the page-specific script element.
Layout templates
Use Phoenix.View.render_existing/3 in your layouts like this:
<head>
<%= render_existing #view_module, "scripts.html", assigns %>
</head>
... or this:
<head>
<%= render_existing #view_module, "scripts." <> #view_template, assigns %>
</head>
For the first example, this will render a "scripts.html" template if one exists for the relevant view module.
For the second example, a "scripts." <> #view_template template, e.g. scripts.form.html, will be rendered if it exists.
If the 'scripts' template does NOT exist for a view module, nothing will be output in the page HTML.
View modules
For the first example using render_existing/3 in the layout template, you'd add code like this to the post view module:
def render("scripts.html", _assigns) do
~E(<script src="file.js"></script>)
end
... and for the second you'd add code like this:
def render("scripts.show.html", _assigns) do
~E(<script src="show-file.js"></script>)
end
def render("scripts.index.html", _assigns) do
~E(<script src="index-file.js"></script>)
end
Details
The difference between render_existing and render is that the former won't raise an error if the referenced template does NOT exist (and nothing will be output in the page HTML in that case either).
The ~E sigil provides "HTML safe EEx syntax inside source files" and is similar to (in most cases, or maybe even always) the corresponding code from cmititiuc's answer:
~s{<script>require("web/static/js/posts").Post.run()</script>}
|> raw
Conclusion
In general then, for any page for which you want to import specific JavaScript files via script elements in the page head (or at the end of the body), or link CSS files, or do anything to the page output in a portion thereof otherwise handled by the layout, you'd use render_existing in the layout template as above and then implement appropriate render clauses in the view modules for those pages.
And further, there's no reason why you couldn't use something like both of the two examples above so that, for any view module and its templates, you could both:
Include some script(s) (or CSS files or otherwise manipulate the HTML output of in a layout template) for all the view module templates (but not all templates for the entire app)
Include some script(s) (or ...) for only a single template
<script src="myscripts.js"></script>
Put your code in a new .js file. Include the script tag with a source to the file path in the relevant html files.

Adding javascript to a rails app page

I want to hide and show 2 links in my rails app
Invite
Undo
In my css
.email_sent{display: none;}
I added this to the bottom of the page
<%= javascript_tag do %>
$(function(){
$('.send_email > a').click(function(){
$('.send_email').hide();
$('.email_sent').show();
});
$('.email_sent > a').click(function(){
$('.send_email').show();
$('.email_sent').hide();
});
});
<% end %>
In console I get the following error
Uncaught ReferenceError: $ is not defined(anonymous function)
The page's source shows this
<script>
//<![CDATA[
$(function(){
$('.send_email > a').click(function(){
$('.send_email').hide();
$('.email_sent').show();
});
$('.email_sent > a').click(function(){
$('.send_email').show();
$('.email_sent').hide();
});
});
//]]>
</script>
How do I fix the javascript?
$ variable defined in JQuery library, so you should include it to your page before. Check that assets/javascripts/application.js includes this library.
FYI: your a tags has commas it can cause any rendering problems. Remove it.
Your javascript code should be put after the following tag.
<%= javascript_include_tag "application" %>
Because the application.js file includes jQuery. your script must be loaded after the jQuery is successfully loaded. The above line of code includes application.js to your web page.

The right way to include page-specific JavaScript in Rails

I want to include this, for example:
jQuery(document).ready(function($) {
$('#my-modal').modal(options)
});
In one specific place in a rails app. In my case the file is called views/modals/mymodal.html.erb. There and only there.
I can't figure out how to do that without getting it on all pages as would happen if I put it in assets.
These are some useful tricks
#1 with file js
Create file your.js for your javascript
call file your.js on specific your layout
remove //= require_tree . on application.js
add your.js to asset percompile on config/application.rb : config.assets.precompile += %w( your.js )
#2 put into specific file non layout (not recommended)
put your js script with javascript tag on mymodal.html.erb
#3 use if..else..
put your js script into layout/yourlayout.html.erb and use if.. else.. logic.
example :
<% if current_page?(yourspecific_path) %>
<script language="text/javascript">
your javascript here ..
</script>
<% end %>
Read more here about current_page?
Or use request.fullpath to get current full path
example :
<% if request.fullpath == yourspecific_path %>
<script language="text/javascript">
your javascript here ..
</script>
<% end %>
Read more here about request.fullpath
Also you can combine #1 and #3 if you want script put into file .js
cheers
Given the JS file you want to include is named my_modal.js:
Place your JS files placed in assets/javascripts in some directory inside of
assets/javascripts, for example application.
Change line //= require_tree . to //= require_tree application in your application.js (it prevents loading my_modal.js on every page).
Place your my_modal.js in assets/javasctripts
Add my_modal.js to config.assets.precompile array (config assets.precompile += ['my_modal.js']) in your application.rb.
Put javascript_include_tag 'my_modal' in the view you want this file included
You can go to Rails guides for reference.
One of the solution is to insert our javascript in to its own file: Reference Link
For example :
// app/assets/javascripts/alert.js
alert("My example alert box.");
And including this file only in the view we want it to execute:
<%# app/views/page/contact.html.erb %>
<%= javascript_include_tag "alert" %>
<h1>Contact</h1>
<p>This is the contact page</p>
And don’t forget to include your new file in the list of files to be compiled:
# config/environments/production.rb
config.assets.precompile += %w( alert.js )
Late to the party, but for anyone viewing this today I think I've come up with something better.
Punchbox Gem for Rails
With this, you can write code like:
class Post {
controller() {
// Runs on every action
}
index() {
// Runs on just the index action
}
}
Punchbox.on('Posts', Post);
(You can also create an object instead of a class. See the docs)
I've written about this much more in depth here: https://kierancodes.com/blog/page-specific-javascript-in-rails-4
jquery-readyselector is a plugin that "Extends $().ready() to provide a convenient syntax for page-specific script"
Install jquery-readyselector
Create some CSS classes
<body class="<%= controller_name %> <%= action_name %>">
Scope your javascript to your page
$("#my-modal").ready(function() {
$('#my-modal').modal(options)
});
More info in this answer How to load page specific rails 4 js files?

Sails.js - How to inject a js file to a specific route?

For example, I have a page /locations/map which I need to include Google Map library, and include a .js file (e.g. location.js) specifically for this page only.
I want to inject these 2 files to after <!--SCRIPTS END--> this line
Is it possible to do this?
NOTE: I was using Sails.js v0.10
Sails uses ejs-locals in its view rendering, so you can accomplish what you want with blocks.
In your layout.ejs file, underneath the <!--SCRIPTS END-->, add (for example):
<%- blocks.localScripts %>
Then in the view you're serving at /locations/map, call the block with your script tag, for example:
<% block('localScripts', '<script src="https://maps.googleapis.com/maps/api/js"></script>') %>
As an alternative, you could put the <!--SCRIPTS--> and <!--SCRIPTS END--> tags in the <head> of your layout, and then add your view-specific scripts directly into your view rather than using blocks. This is a fine option if you don't mind waiting for those linked scripts to load before your page content is displayed.
Scott's answer is the proper way to insert non-global JS into a specific view. Just a little comment, though: the block call from the view should not have the dash. It should be as follows:
<% block('localScripts', '<script src="https://maps.googleapis.com/maps/api/js"></script>') %>
Both calls will work, but using the dash makes the insertion twice; once the view is loaded and previous to the layout render, and then once again when the view is inserted in the rendered base layout. This leads not only to inserting/running unnecessarily twice the same code but also to errors that break your JS code if the inserted script depends on libraries that you have in your base layout (e.g. jQuery, Backbone).
EJS interprets the magic <%- as "insert unescaped". So, -I guess- what this is doing is calling the block() function, which returns our HTML <script> tag. This is replaced where the magic was called but also is executing the block() function inside of it, which is executing the layout block localScripts replacement.
On the other hand, <% means "instruction". I.e., just run this JS piece of code, which is not echoed to the view where is called.
I discover other way to do that
In MapController.js
// you can add as many as you like
res.locals.scripts = [
'//maps.googleapis.com/maps/api/js',
];
return res.view();
In layout.ejs
<!--SCRIPTS-->
<!--SCRIPTS END-->
<!-- Loop through all scripts that passed from controller -->
<% if (scripts) { %>
<% for (i = 0; i < scripts.length; i++) { %>
<script src="<%- scripts[i] %>"></script>
<% } %>
<% } %>
This method allows flexibility to locally serve js files from any page and also prevent any reference errors caused by dependencies.
In pipeline.js insert '!js/local/*.js at the bottom of jsFilesToInject like so:
var jsFilesToInject = [
// Load sails.io before everything else
'js/dependencies/sails.io.js',
// Dependencies like jQuery, or Angular are brought in here
'js/dependencies/jquery-3.3.1.min.js',
'js/dependencies/**/*.js',
// All of the rest of your client-side js files
// will be injected here in no particular order.
'js/**/*.js',
//Ignore local injected scripts
'!js/local/*.js'
];
Create a local folder inside the /assets/js folder ie /assets/js/local/. Place any locally injected scripts in here.
In your master view ejs ie layout.ejs insert <%- blocks.localScripts %> below the SCRIPTS block like this:
<!--SCRIPTS-->
<script src="/js/dependencies/sails.io.js"></script>
<script src="/js/dependencies/jquery-3.3.1.min.js"></script>
<script src="/js/dependencies/bootstrap.min.js"></script>
<script src="/js/dependencies/popper.min.js"></script>
<!--SCRIPTS END-->
<%- blocks.localScripts %>
In your local ejs view (eg. homepage.ejs) insert your localScripts block like this:
<% block('localScripts', '<script src="/js/local/homepage.js"></script>') %>
sails v0.12.14
EDIT
Is this still relevant for Sails v1.0?
My answer is a resounding YES and in my earlier answer I lacked explaining how to get the most out of the Grunt pipeline like clean, coffee, concat, uglify etc... when going into production.
The trick here is to make a local file (there should only be one per page) as small as possible.
Group and name specific your function calls
Save functions as separate files for easy maintenance and group them into folders.
Group bindings and any initialising of global variables into a couple of functions like initThisPageVariables() and initThisPageBindings() so that Grunt can crunch these later.
Set a master function call to run your app startThisPageApp()
Then simply calling the few functions from your local (master) file to get things rolling.
$(window).on('load', function(){
initThisPageVariables();
initThisPageBindings();
$(window).on("resize", function(){
initThisPageVariables();
}).resize();
startThisPageApp();
});
I know this is an old question by I discovered another option.
File:
config\routes.js
Code:
'/': 'HomeController.StartHome'
I set StartHome function in HomeController responsible for managing '/' route.
File:
api\controllers\HomeController.js
Code:
StartHome: function(req, res) {
var template_data = {
"data" : {
"view_name" : "home_view"
}
}
res.view('home_view', template_data)
}
Here, I created an object with some data which is passed to EJS template(to client).
File:
views\layout.ejs
Code:
<% if (data["view_name"] === "home_view") { %>
<script src="script_for_home_view.js"></script>
<% } %>
In my layouts.ejs I created if statement which "enables" script tag depending on on the view I am currently on.
This is how I handle this. I hope it's clear for you.
Sails 0.12.4

Categories

Resources