SITUATION:
I am trying to implement the first answer (with 25 upvotes) to this question: How can I make an Upvote/Downvote button? with my Node.js ejs template.
So I wrote this code.
MY CODE:
Main.js
<script src=".1.1/jquery.min.js"></script>
$('.UpvoteButton').click(function () {
$(this).toggleClass('on');
});
$('.DownvoteButton').click(function () {
$(this).toggleClass('on');
});
style.css
.UpvoteButton {
display: inline-block;
overflow: hidden;
width: 80px;
height: 50px;
margin-top: 15px;
margin-right: 3px;
cursor: pointer;
background: url('/assets/UpvoteButtonSpriteSheet.png');
background-position: 0 0px;
}
.DownvoteButton {
display: inline-block;
overflow: hidden;
width: 80px;
height: 50px;
margin-top: 15px;
margin-right: 3px;
cursor: pointer;
background: url('/assets/DownvoteButtonSpriteSheet.png');
background-position: 0 0px;
}
.UpvoteButton.on {
background-position: 0 50px;
}
.DownvoteButton.on {
background-position: 0 50px;
}
index.ejs
<% include ../partials/header %>
<script src=".1.1/jquery.min.js"></script>
<div class ="containerMarginsIndex">
<% for(var i=0; i < fun.length; i++) {%>
<div class="fun">
<h3 class="text-left"><%= fun[i].title %></h3>
<a href="details/<%= fun[i].id %>">
<img class = "postImg" src="/images/uploads/<%= fun[i].image %>">
</a>
<span class="UpvoteButton"> </span><span class="DownvoteButton"> </span>
</div>
<% } %>
</div>
<% include ../partials/footer %>
PROBLEM:
Nothing happens when I click. The images stay the same.
QUESTION:
What have I done wrong ?
SITUATION:
I am trying to implement the first answer (with 25 upvotes) to this question: How can I make an Upvote/Downvote button? with my Node.js ejs template.
So I wrote this code.
MY CODE:
Main.js
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
$('.UpvoteButton').click(function () {
$(this).toggleClass('on');
});
$('.DownvoteButton').click(function () {
$(this).toggleClass('on');
});
style.css
.UpvoteButton {
display: inline-block;
overflow: hidden;
width: 80px;
height: 50px;
margin-top: 15px;
margin-right: 3px;
cursor: pointer;
background: url('/assets/UpvoteButtonSpriteSheet.png');
background-position: 0 0px;
}
.DownvoteButton {
display: inline-block;
overflow: hidden;
width: 80px;
height: 50px;
margin-top: 15px;
margin-right: 3px;
cursor: pointer;
background: url('/assets/DownvoteButtonSpriteSheet.png');
background-position: 0 0px;
}
.UpvoteButton.on {
background-position: 0 50px;
}
.DownvoteButton.on {
background-position: 0 50px;
}
index.ejs
<% include ../partials/header %>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class ="containerMarginsIndex">
<% for(var i=0; i < fun.length; i++) {%>
<div class="fun">
<h3 class="text-left"><%= fun[i].title %></h3>
<a href="details/<%= fun[i].id %>">
<img class = "postImg" src="/images/uploads/<%= fun[i].image %>">
</a>
<span class="UpvoteButton"> </span><span class="DownvoteButton"> </span>
</div>
<% } %>
</div>
<% include ../partials/footer %>
PROBLEM:
Nothing happens when I click. The images stay the same.
QUESTION:
What have I done wrong ?
Share Improve this question edited May 23, 2017 at 12:19 CommunityBot 11 silver badge asked Oct 23, 2016 at 21:19 Coder1000Coder1000 4,47110 gold badges37 silver badges87 bronze badges 13- 1 "with Node.js" - what exactly does than mean ? That you are using Express for example ? Can you paste you source code - as source generated and 'seen' by the browser ? – marcinrek Commented Oct 23, 2016 at 21:24
-
jQuery is available for Node.js through NPM, but generally you don't need it on the server (or on the client for that matter). There's no document, nor anything to click, on a webserver, and there's usually no
require
on the clientside, unless you're using Browserify or Webpack. In other words, you're most likely doing it wrong. – adeneo Commented Oct 23, 2016 at 21:28 - @adeneo I am using ejs to render my pages (as the index.ejs suggests). In my index.js, I have 2 spans which contain clickable images. As said, I am trying to replicate the behaviour in the linked answer. If I am doing it wrong, please tell me why and how I can remedy to the situation :) Thank you ! – Coder1000 Commented Oct 23, 2016 at 21:46
- @marcinrek It means I am exclusively using npm modules to render my pages (I am using ejs). Just looking to add some clickable functionality to 2 spans in one of my ejs files. Express is one of the modules I am using, yes. – Coder1000 Commented Oct 23, 2016 at 21:47
- 1 jsfiddle/da1nk1s2 – adeneo Commented Oct 23, 2016 at 23:48
4 Answers
Reset to default 10You'll have to include jQuery and the clientside script in your EJS template, so it's rendered in the browser.
Installing jQuery with npm in Node, and doing var $ = require('jquery')
on the serverside, just lets you use some of jQuery's methods on the server, it doesn't include jQuery on the clientside.
Change the template to something like
<% include ../partials/header %>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class ="containerMarginsIndex">
<% for(var i=0; i < fun.length; i++) {%>
<div class="fun">
<h3 class="text-left"><%= fun[i].title %></h3>
<a href="details/<%= fun[i].id %>">
<img class = "postImg" src="/images/uploads/<%= fun[i].image %>">
</a>
<span class="UpvoteButton"> </span><span class="DownvoteButton"> </span>
</div>
<% } %>
</div>
<script>
$('.UpvoteButton').click(function () {
$(this).toggleClass('on');
$('.DownvoteButton').removeClass('on');
});
$('.DownvoteButton').click(function () {
$(this).toggleClass('on');
$('.UpvoteButton').removeClass('on');
});
</script>
<% include ../partials/footer %>
the browser does not support require mand natively. you have to use a file bundler like webpack or browserify in order to include the "jquery.js" file in your main js file.
I have faced similar issue in NodeJS using the ejs as the 'view engine' template, and resolved it as bellow:
Server side:
Install jQuery and jsdom:
npm install jquery --save npm install jsdom --save
For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as jsdom and as of v10, jsdom has a new API and you can configure jsdom in your server side code (i.e. app.js or index.js) as below:
var jsdom = require("jsdom"); const { JSDOM } = jsdom; const { window } = new JSDOM(); const { document } = (new JSDOM('')).window; global.document = document; var $ = require("jquery")(window);
Client side:
Include jQuery package as usual in the ejs template (e.g. header.ejs):
<head> <title>Whatever App</title> <script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script> </head>
Then the js scripts that you put in the ejs file will be rendered without any problem, for example, in your case, just put the js script in the index.ejs:
<script> $('.UpvoteButton').click(function () { $(this).toggleClass('on'); $('.DownvoteButton').removeClass('on'); }); $('.DownvoteButton').click(function () { $(this).toggleClass('on'); $('.UpvoteButton').removeClass('on'); }); </script>
Excuse me for my english.
I know this post is old but I have the same issue and I finded a solution.
It's possible to use an external JQuery file.
It must be placed into "public" folder.
With this tree :
application.js
[views]
index.ejs
[public]
[include]
jquery.min.js
fonctions_jquery.js
With this code in "index.js" :
<script src="/include/jquery.min.js"></script>
<script src="/include/fonctions_jquery.js"></script>
With this code in "application.js"
var express = require('express');
var path = require('path');
var appli = express();
appli.use(express.static(__dirname +path.sep+ 'public'));
It works for me.