Call multiple times require JS in a single file, is it the right move - requirejs

I need to use require js to use jquery in my block(Magento2).
Do I have to declare for each function require JS at each beginning or there is a way to declare it only once?
here is my code, thanks
my html
<div class="mainMenu">
<div style="background-color: black;color: white;">
<div onClick="openCategory(1)">MENU 1</div>
<div onClick="openCategory(2)">MENU 2</div>
<div onClick="openCategory(3)">MENU 3</div>
</div>
</div>
<div onClick="openMainMenu()">
OUVRIR MENU
</div>
SCRIPT inside phtml
<script>
let menu
require(['jquery', 'jquery/ui'], function($){
$.ajax({
url: "https://catfact.ninja/fact",
context: document.body
}).done(function(value) {
menu = []
menu.forEach(element => {
$('.mainMenu').append("<div class='menuContainer menuNumber" + element.id + "'>" + element.name + "</div>")
});
});
});
function openMainMenu(){
require(['jquery', 'jquery/ui'], function($){
$('.mainMenu').show()
});
}
function openCategory(categoryNumber){
require(['jquery', 'jquery/ui'], function($){
console.log($('.menuNumber' + categoryNumber).css("visibility", "visible"));
});
}
</script>

No it don't require to use it multiple times
See Updated Code:
<script>
let menu
require(['jquery', 'jquery/ui'], function($){
$.ajax({
url: "https://catfact.ninja/fact",
context: document.body
}).done(function(value) {
menu = []
menu.forEach(element => {
$('.mainMenu').append("<div class='menuContainer menuNumber" + element.id + "'>" + element.name + "</div>")
});
});
function openMainMenu(){
$('.mainMenu').show();
}
function openCategory(categoryNumber){
console.log($('.menuNumber' + categoryNumber).css("visibility", "visible"));
}
});
</script>
Hope it helps !!

Related

How to display data in ejs view from ajax resultset when called in the view

I have an empty ejs view but I would like to display the result set of the ajax call that I am calling in the ejs view
<script>
// Fetch
$.ajax(`/x`).done(function(data, textStatus, xhr){
console.log(data);
console.log(textStatus);
console.log(xhr);
});
</script>
<!-- how do I loop the data received from above and display the content here? -->
I am not sure how to do this.
UPDATE
here is what I have now. Is there any neater way to do this instead of appending as html?
<script>
const gId = '<%= gId %>';
// Fetch the current users c here from `/g/${gId }/c `
$.ajax(`/g/${gId }/c `).done(function(data, textStatus, xhr){
var c = '';
$.each(data, function(index, value){
console.log(index);
console.log(value)
c += '<div class="col-sm-6 col-md-2"><div><img class="col-sm-12 col-md-11" src="'+value.image+'" /></div><div class="text-center"><input name="card" id="card" type="checkbox" value="'+value.value+'" /> Discard</div></div>';
});
$('#c ').append('<div class="row"><div class="row col-sm-12">'+c +'</div><div class="col-xs-2"></div></div>');
$('#c ').append('<button type="submit">c </button>');
});
const checkExchangeStatus = function(){
$.ajax(`/g/${gId}/allExchanged`).done(function(data, textStatus, xhr){
if (xhr.status !== 202) { // not pending
document.location = `/g/${gId}/result`;
}
})
}
setInterval(checkExchangeStatus, 1000);
</script>
<form method="POST" action="/g/<%= gId %>/exchange">
<div id="c ">
</div>
<div>
<br/>gId : <%= gId %>
</div>
</form>
"ejs code like <% %> is executed on server and rendered as html. So you can't use ejs code with ajax requests."
What you can do is make an ajax call, then alter your html page with jQuery.
I have an empty ejs view but I would like to display the result set of the ajax call that I am calling in the ejs view.
<script>
$.ajax(`/x`).done(function(data, textStatus, xhr){
console.log(data); //I am assuming this prints
$('#someID').html(data);
});
</script>
I don't know what results you are expecting, or what your html looks like. If you update your question with more code I can assist you further.

Pagination meteor publish does not return records

I definitely know that something is wrong with this snippet but can't figure out the right way to get it done. I want to paginate the page where students are displayed. If I put it plainly like this return SchoolStudents.find();, it works perfectly by returning all the students but this defeats the main purpose of pagination. I'm either not sure where the problem is, either in the publish function or the helper function. What I want to achieve is that the records in SchoolStudents colleciton should be paginated to display 2 records on a page.
This is the autorun
Session.setDefault('skip', 0);
Template.view.onCreated(function () {
Session.setPersistent('ReceivedSlug', FlowRouter.getParam('myslug'));
this.autorun(function () {
Meteor.subscribe('SchoolStudents', Session.get('skip'));
});
});
this is the helper method
students(){
let myslug = trimInput(Session.get('ReceivedSlug'));
if (myslug) {
let mySchoolDoc = SchoolDb.findOne({slug: myslug});
if (mySchoolDoc) {
let arrayModuleSchool = StudentSchool.find({schoolId: mySchoolDoc._id});
if (arrayModuleSchool) {
var arrayStudentIds = [];
arrayModuleSchool.forEach(function(studentSchool){
arrayStudentIds.push(studentSchool.studentId);
});
let subReadiness = SchoolStudents.find({_id: {$in: arrayStudentIds}}).fetch();
if (subReadiness) {
return subReadiness;
}
}
}
}
}
This is the publish method
Meteor.publish('SchoolStudents', function (skipCount) {
check(skipCount, Number);
user = Meteor.users.findOne({_id:this.userId})
if(user) {
if(user.emails[0].verified) {
return SchoolStudents.find({userId: this.userId}, {limit: 2, skip: skipCount});
} else {
throw new Meteor.Error('Not authorized');
return false;
}
}
});
Blaze template
<section class="tab-section" id="content4">
{{#each student in students}}
<div class="row" style="margin-top: -20px;">
<!-- Begin Listing: 609 W GRAVERS LN-->
<div class="brdr bgc-fff pad-10 box-shad btm-mrg-20 property-listing card-1">
<div class="media">
<div class="media-body fnt-smaller">
<h4 class="media-heading">{{student.firstname}} {{student.lastname}}</h4>
<p class="hidden-xs" style="margin-bottom: 5px; margin-top: -10px;">{{trimString student.useremail 0 110}}</p><span class="fnt-smaller fnt-lighter fnt-arial">{{course.createdAt}}</span>
</div>
</div>
</div><!-- End Listing-->
</div>
{{/each}}
<ul class="pager">
<li class="studentprevious">Previous </li>
<li class="studentnext">Next </li>
</ul>
</section>
the pagination event
'click .studentprevious': function () {
if (Session.get('skip') > 0 ) {
Session.set('skip', Session.get('skip') - 2 );
}
},
'click .studentnext': function () {
Session.set('skip', Session.get('skip') + 2 );
}

How to apply masonry to items appended by ajax call

I have a picture grid and in the Mobile View (320 X 480), there is a "Load More" button. The container div is as follows:
<div id="divMoments" class="grid" data-masonry='{ "itemSelector": ".grid-item"}'>
<div class="grid-item">
<div class="gridContainer">
<img src="ImageURL" />
<p>OwnerName</p>
</div>
</div>
</div>
On the button click, it triggers an ajax call. The received result is a html string of many such grid items:
"<div class=\"grid-item\">imagex<div>
<div class=\"grid-item\">imagey<div>
..."
After appending the string to the container, I have the jQuery code to reload masonry, but all the images are overlapped. When I check the html, the masonry css is applied to all the items.
function GetNextSet() {
jQuery.ajax({
url: "/api/sitecore/Moment/GetNextSet",
type: "POST",
context: this,
success: function (data) {
ShowNextResultSet(data);
}
});
}
function ShowNextResultSet(data) {
var $content = jQuery(data.ResultSet);
jQuery("#divMoments").append($content).masonry('appended', $content);
jQuery("#divMoments").masonry('reloadItems');
jQuery("#divMoments").masonry();
}
using masonry v4.1.1
Re-applying masonry after a delay worked for me.
function ShowNextResultSet(data) {
var $content = jQuery(data.ResultSet);
jQuery("#divMoments").append($content).masonry('appended', $content);
setTimeout(function () {
jQuery("#divMoments").masonry('reloadItems');
jQuery("#divMoments").masonry();
}, 100);
}

Vue js 2 Method not working from click event

I have a vue component which prints out a list of radio buttons. I have a watch on internalValue which sends the selected value to the root
I am trying to send a console.log on a click event using a method called doSomething but it is not working. Furthermore I am not getting any errors or warnings.
Load Component
Vue.component('topic', require('./components/Topicselect.vue'));
Use Component
<div class="form-group" id="topic">
<topic v-model="selectedTopic"></topic>
</div>
Initialise Vue
new Vue({
el: '#topic',
data: {
selectedTopic: null
}
});
Component
<template>
<div>
<label v-for="topic in topics" class="radio-inline radio-thumbnail" style="background-image: url('http://s3.hubsrv.com/trendsideas.com/profiles/74046767539/photo/3941785781469144249_690x460.jpg')">
<input type="radio" v-model="internalValue" :click="doSomething" name="topics_radio" :id="topic.id" :value="topic.name">
<span class="white-color lg-text font-regular text-center text-capitalize">{{ topic.name }}</span>
</label>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
internalValue: this.value,
topics: []
}
},
mounted(){
axios.get('/vuetopics').then(response => this.topics = response.data);
},
watch: {
internalValue(v){
this.$emit('input', v);
console.log('the value is ' + this.value);
}
},
methods: {
doSomething: function (){
console.log('doSomething is firing');
}
}
}
</script>

Cannot use $(this) in $.getJSON in .each

Im building a custom Minecraft Server Status and hit a problem. The first version of this was successful but the code was rather long and I decided to make it better and shorter. The script is supposed to fill the elements of each .server but it doesn't work.
<div class="server_status">
<div class="container servers_info">
<h1>My Network</h1>
<div id="of the server" class="server" title="of the server" server-ip="0.0.0.0">
<div class="name"></div>
<div class="count"><i class="fa fa-spinner fa-spin"></i></div>
<div class="players">Loading player data <i class="fa fa-spinner fa-spin"></i></div>
<div class="status"></div>
</div>
<div id="of the server" class="server" title="of the server" server-ip="0.0.0.0">
<div class="name"></div>
<div class="count"><i class="fa fa-spinner fa-spin"></i></div>
<div class="players">Loading player data <i class="fa fa-spinner fa-spin"></i></div>
<div class="status"></div>
</div>
<!-- ..... more servers -->
<span class="total"><i class="fa fa-spinner fa-spin"></i></span>
</div>
$(document).ready(function ping() {
$( ".servers_info .server" ).each( function() {
var name = $(this).attr( "title" );
var ip = $(this).attr( "server-ip" );
var id = $(this).attr( "id" );
var total = 0;
var call = "Get Avatar List adress";
//Set the name:
$(".name",this).html(name);
//Gets the data:
$.getJSON("http://mcapi.ca/v2/query/info/?ip=" + ip, function (json) {
//Checks The status and applies visual effects:
if (json.status !== "false") {
$(".status",this).html("<span class=\"l-online\">" + json.ping + " ms</span>");
$(this).removeClass('blur');
} else {
$(".status",this).html("<span class=\"l-offline\">0 ms</span>");
$(this).addClass('blur');
};
});
});
//Sets Refresh rate of 10s
setTimeout(ping, 10000);
});
I narrowed down the problem to the $.getJSON part. The data is retrieved correctly but cannot be placed in its respective DIVs. The only difference with the first version of the script is that I used 4 getJSON separately for each of the servers I wanted to display. Now using .each to combine it for all 4 of them and also $(this) to use relative objects.
I suspect the problem is in th usage of $(this) in .get but I'm nnot sure and don't know how to fix it.
As you suspect, the issue is the $(this). part. Inside the $.getJSON callback this no longer refers to the DOM object that triggered the event.
To fix this you can either:
Add a .bind(this) to the callback function. No changes required inside the function itself.
$.getJSON(url, function(json) {
/* all your code here */
}.bind(this)
);
Or save the reference to this before $.getJSON and use it inside the callback.
var _this = this;
$.getJSON(url, function(json) {
/* replace all references of this to _this for example*/
$(_this).removeClass('blur');
});
Hope that helps

Resources