Add like on click - javascript

I need to create a cookie method with the current time, which will first check the data (like_finger and article_id), and if there is no data, then add a like and update the date, if there is data, then do nothing.
I have a function
$likes = request()->cookie('like_finger');
$hours = 24;
if ($likes) {
Article::find($id)
->where('updated_at', '<', Carbon::now()->subHours($hours)->toDateTimeString())
->increment('like_finger');
}
But I can't check it yet, because I got confused in the add like button
I added a button to php.blade and created a function in js
<input type="button" id="start" value="Like Finger" onclick="startCombine(this)"> {{ $article->like_finger }}
function startCombine(startButton) {
startButton.disabled = true;
startButton.disabled = false;
}
How can I make sure that a like is added when true?
I want that when the button is clicked, one like is added, which will be stored in cookies for 24 hours, I wrote an approximate function of how the like should be added, but it is not perfect, since there is no button functionality

First of all, you should never store any logic in the client side. A great alternative for this kind of feature would be using the Laravel Aquantances package.
https://laravel-news.com/manage-friendships-likes-and-more-with-the-acquaintances-laravel-package
Anyway, since you want to do it with cookies;
We can actually do this a lot easier than thought.
Articles.php
class User extends Authenticatable
{
// ...
public static function hasLikedToday($articleId, string $type)
{
$articleLikesJson = \Cookie::get('article_likes', '{}');
$articleLikes = json_decode($articleLikesJson, true);
// Check if there are any likes for this article
if (! array_key_exists($articleId, $articleLikes)) {
return false;
}
// Check if there are any likes with the given type
if (! array_key_exists($type, $articleLikes[$articleId])) {
return false;
}
$likeDatetime = Carbon::createFromFormat('Y-m-d H:i:s', $articleLikes[$articleId][$type]);
return ! $likeDatetime->addDay()->lt(now());
}
public static function setLikeCookie($articleId, string $type)
{
// Initialize the cookie default
$articleLikesJson = \Cookie::get('article_likes', '[]');
$articleLikes = json_decode($articleLikesJson, true);
// Update the selected articles type
$articleLikes[$articleId][$type] = today()->format('Y-m-d H:i:s');
$articleLikesJson = json_encode($articleLikes);
return cookie()->forever('article_likes', $articleLikesJson);
}
}
The code above will allow us to is a user has liked an article and generate the cookie we want to set.
There are a couple important things you need to care about.
Not forgetting to send the cookie with the response.
Redirecting back to a page so that the cookies take effect.
I've made a very small example:
routes/web.php
Route::get('/test', function () {
$articleLikesJson = \Cookie::get('article_likes', '{}');
return view('test')->with([
'articleLikesJson' => $articleLikesJson,
]);
});
Route::post('/test', function () {
if ($like = request('like')) {
$articleId = request('article_id');
if (User::hasLikedToday($articleId, $like)) {
return response()
->json([
'message' => 'You have already liked the Article #'.$articleId.' with '.$like.'.',
]);
}
$cookie = User::setLikeCookie($articleId, $like);
return response()
->json([
'message' => 'Liked the Article #'.$articleId.' with '.$like.'.',
'cookie_json' => $cookie->getValue(),
])
->withCookie($cookie);
}
});
resources/views/test.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<meta name="csrf-token" content="{{ csrf_token() }}" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
</head>
<body>
<div class="container">
#if (session('success'))
<div class="alert alert-success" role="alert">
{{ session('success') }}
</div>
#endif
<pre id="cookie-json">{{ $articleLikesJson }}</pre>
<div class="row">
#foreach (range(1, 4) as $i)
<div class="col-3">
<div class="card">
<div class="card-header">
Article #{{ $i }}
</div>
<div class="card-body">
<h5 class="card-title">Special title treatment</h5>
<p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
<a href="/test?like=heart&article_id={{ $i }}" class="btn btn-primary like-button">
Like Heart
</a>
<a href="/test?like=finger&article_id={{ $i }}" class="btn btn-primary like-button">
Like Finger
</a>
</div>
<div class="card-footer text-muted">
2 days ago
</div>
</div>
</div>
#endforeach
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/js/bootstrap.min.js" integrity="sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF" crossorigin="anonymous"></script>
<script>
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.like-button').on('click', function(event) {
event.preventDefault();
let href = $(this).attr('href');
$.ajax({
url: href,
type: 'POST',
success: function (response) {
alert(response.message)
$('#cookie-json').text(response.cookie_json)
}
})
});
});
</script>
</body>
</html>

In Blade you can have conditionals, like
#if (count($records) === 1)
I have one record!
#elseif (count($records) > 1)
I have multiple records!
#else
I don't have any records!
#endif
Example taken from https://laravel.com/docs/8.x/blade
Let's try to apply it on your specific issue
#if ($article->article_id && $article->like_finger)
<input type="button" id="start" value="Like Finger" onclick="startCombine(this)"> {{ $article->like_finger }}
#endif

Make an AJAX request in startCombine() when the button is clicked.
Your server code processing the like seems to use a cookie named like_finger, so before the request to the server is made you create that cookie:
const d = new Date();
d.setTime(d.getTime() + (24*60*60*1000)); // Expiry in milliseconds
document.cookie = "like_finger=" + d.toUTCString() +
";expires=" + d.toUTCString() +
";path=/";
(The cookie is set to expire after 24 h with the above values)
Then you want to send that to the server:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "the_place_where_php_processing_code_is.php", true);
xhttp.setRequestHeader("Content-Type", "application/json");
xhttp.onreadystatechange = function() { // When status of the ongoing request changes
if (this.readyState == 4 && this.status == 200) {
// Server has processed the like request and is done
// You can do some "summary" here, like disabling the Like button
var response = this.responseText;
}
};
var data = {
id : 1, // The id of the article being liked, not sure how to retrieve that right now
};
xhttp.send(JSON.stringify(data));
..and then you use something like this in the receiving PHP code on the server:
$id = $request->input('id'); // $id = 1 (in this case, of course)

Related

ASP.NET Core - change form action to list options in view

I have controller for changing website language, saving cookie and returning url.
`
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
namespace Website.Controllers;
public class CultureController : Controller
{
[HttpPost]
public IActionResult SetCulture(string culture, string returnUrl)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddDays(365) }
);
return LocalRedirect(returnUrl);
}
}
`
And in View I need create html list for better user experience but I don't understand how to change from 'form' to 'list' or how to submit changes and return url
`
#using Microsoft.AspNetCore.Localization
#using Microsoft.Extensions.Options
#inject IOptions<RequestLocalizationOptions> LocalizationOptions
#{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = LocalizationOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.EnglishName })
.ToList();
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString}";
}
<!-- FROM FORM -->
<div class="language">
<form asp-controller="Culture" asp-action="SetCulture" asp-route-returnUrl="#returnUrl" class="form-horizontal nav-link text-dark">
<select name="culture"
onchange="this.form.submit();"
asp-for="#requestCulture.RequestCulture.UICulture.Name"
asp-items="cultureItems">
</select>
</form>
</div>
<!-- TO LIST -->
<div class="language-toggle">
<i class="fas fa-language"></i>
<ul class="language-menu">
#foreach (var item in LocalizationOptions.Value.SupportedUICultures)
{
<li>#item.Name.ToUpper()</li>
}
</ul>
</div>
`
I tried with anchor tag helper but without success
output
Output
I can get current url in view and append ?culture=en and that changes language and stays on current page but does not save cookie so every time user goes to different page website is in native language not in user selected language.
You can achieve that with something like this:
<head>
<script type="text/javascript">
function submitCulForm(val) {
document.getElementById("cultureVal").value = val;
var hh = document.getElementById("cultureForm");
hh.submit();
return false;
}
</script>
</head>
Then
<form asp-controller="Culture" id="cultureForm" asp-action="SetCulture" asp-route-returnUrl="#returnUrl" class="form-horizontal nav-link text-dark">
<input id="cultureVal" type="hidden" name="culture" value="-">
<div class="language-toggle">
<i class="fas fa-language"></i>
<ul class="language-menu">
#foreach (var item in LocalizationOptions.Value.SupportedUICultures)
{
<li>#item.Name.ToUpper()</li>
}
</ul>
</div>
</form>
If you try to pass the value with herf,you shouldn't add [HttpPost] Attribute on your controller.
I tried with the codes in your controller,it works well,I'll show what I've tried and hopes it could help
in View:
<div>
<a asp-action="SetCulture" asp-route-culture="zh-CN">zh-CN</a>
<a asp-action="SetCulture" asp-route-culture="en-US">en-US</a>
</div>
<script>
var cookie = document.cookie
console.log(cookie)
</script>
in Controller:
public IActionResult SetCulture(string culture)
{
if (culture != null)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddDays(365) });
return RedirectToAction("Create");
}
return BadRequest();
}
Configure in startup:
services.AddControllersWithViews()
.AddDataAnnotationsLocalization(
options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResources));
});
...............
var supportedCultures = new[] { "en-US", "zh-CN" };
var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
created an empty class called SharedResources
and the resourcefile:
The Result:
It just performed as the document,and if you tried with mulipule providers,you could try to change request culture providers order which has been mentioned in the document

Invisible Google Recapthca two in Sweetalert2

I saw the code snippets at Google reCaptcha within SweetAlert modal window , particularly the one without the jquery (the 1st answer)
But that solution makes the captcha box visible.
How do i make it invisible within Sweetalert? I will do a server backend validation
I looked at https://github.com/prathameshsawant7/multiple-invisible-recaptcha and included the entire code from init_recaptcha.js along with the "onOpen" feature of SWAL... but no luck. The captcha is not set in the form.
Any help will be appreciated> I need the invisible captcha as I will triggering several SWAL forms within the HTML tag of the sweetalert (needed for multiple inputs at time)
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/cover.css">
<script src="js/jquery1.11.1.min.js" type="text/javascript"></script>
<script src="js/sweetalert2#10.js"></script>
<script>
$(document).ready(function() {
$(document).on('click', '#comment_button', function(e) {
e.preventDefault();
//var M_user = "";
Swal.fire({
title: 'Add a comment to the page',
titleText: 'Add a comment to the page',
//included dynamically... :-)
width: '75%',
position: 'center',
showCancelButton: true,
showConfirmButton: false,
showCloseButton: true;
allowOutsideClick: false,
focusConfirm: false,
//grow: 'fullscreen',
allowEscapeKey: true,
html: '<div class="card"><form name="form2" id="form2" method="post" action="process3.php"><div class="form-group"><label for="InputText2">Enter Text (Recaptcha 2)</label><input type="text" class="form-control" id="text2" name="textmsg" placeholder="Enter random text" value="this_is_textmsg"></div><div class="form-group"><label for="InputText3">Enter Text :</label><input type="text" class="form-control" id="textv3" name="textmsg3" placeholder="Enter random text" value="this_is_textmsg3"></div><div id="recaptcha-form-2" style="display:none;"></div><input type="button" class="btn btn-primary" onclick="formSubmit(\'2\')" value="Submit" /></form></div>',
footer: 'We reserve the right to moderate your comments if we feel the need.',
onOpen: function() {
console.log('setting initial values, if any on onOpen');
/***
* #Created by: Prathamesh Sawant (prathameshsandeepsawant#gmail.com)
* #Date : 24/07/2017
* #description To handle Multiple Google Invisible reCaptcha Implementation
*/
/**************************************************************************\
* Step 1 - Initialize reCaptcha Site Key and Widget eg: widget_1 for Form 1
* Step 2 - In init function add code to create form submit callback action.
* Step 3 - Call renderInvisibleReCaptcha function by passing reCaptcha ID
* and createCallbackFn Response.
***************************************************************************/
"use strict";
var PS = PS || {};
var widget_1;
var widget_2;
var widget_3;
var recaptcha_site_key = 'my Real Site Key Goes here....removed for stackoverflow';
if (typeof PS.RECAPTCHA === 'undefined') {
(function(a, $) {
var retryTime = 300;
var x = {
init: function() {
if (typeof grecaptcha != 'undefined') {
//For Form 1 Initialization
if ($('#form1 #recaptcha-form-1').length > 0) {
var callbackFn = {
action: function() {
saveData('1'); //Here Callback Function
}
}
/*--- 'recaptcha-form-1' - reCaptcha div ID | 'form1' - Form ID ---*/
widget_1 = x.renderInvisibleReCaptcha('recaptcha-form-1', x.createCallbackFn(widget_1, 'form1', callbackFn));
}
//For Form 2 Initialization
if ($('#form2 #recaptcha-form-2').length > 0) {
var callbackFn = {
action: function() {
saveData('2'); //Here Callback Function
}
}
/*--- 'recaptcha-form-2' - reCaptcha div ID | 'form2' - Form ID ---*/
console.log('defining widget 2');
widget_2 = x.renderInvisibleReCaptcha('recaptcha-form-2', x.createCallbackFn(widget_2, 'form2', callbackFn));
}
//For Form 3 Initialization
if ($('#form3 #recaptcha-form-3').length > 0) {
var callbackFn = {
action: function() {
saveData('3'); //Here Callback Function
}
}
/*--- 'recaptcha-form-3' - reCaptcha div ID | 'form3' - Form ID ---*/
widget_3 = x.renderInvisibleReCaptcha('recaptcha-form-3', x.createCallbackFn(widget_3, 'form3', callbackFn));
}
} else {
setTimeout(function() {
x.init();
}, retryTime);
}
},
renderInvisibleReCaptcha: function(recaptchaID, callbackFunction) {
return grecaptcha.render(recaptchaID, {
'sitekey': recaptcha_site_key,
"theme": "light",
'size': 'invisible',
'badge': 'inline',
'callback': callbackFunction
});
},
createCallbackFn: function(widget, formID, callbackFn) {
return function(token) {
$('#' + formID + ' .g-recaptcha-response').val(token);
if ($.trim(token) == '') {
grecaptcha.reset(widget);
} else {
callbackFn.action();
}
}
}
}
a.RECAPTCHA = x;
})(PS, $);
}
$(window).load(function() {
PS.RECAPTCHA.init();
});
},
preConfirm: function(login) {
//run any stuff to do before login here
console.log('doing before preConfirm stuff....');
//let s_user_name = Swal.getPopup().querySelector('#s_user_name').value;
//M_user= s_user_name;
},
}).then(function(result) {
console.log('then function result initial');
if (result.value) {
console.log('Doing if result.value here...');
}
}) //swal.fire end
}); //function(e) ends
}); //doc ready ends
</script>
</head>
<body>
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div class="inner">
<center>
<h3 class="">Handle Multiple Invisible Recaptcha</h3>
</center>
</div>
</div>
<div class="inner cover">
<hr>
<form id="comment_form" name="comment_form_name"><button id="comment_button" class="coach_button">Leave a Comment...</button></form>
</hr>
<div class="mastfoot">
<div class="inner">
<p>Sample template by #Prathamesh-Sawant to implement multiple invisible recaptcha on single page dynamically.</p>
</div>
</div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit"></script>
<script src="js/form.js" async defer></script>
</body>
</html>
I figured it out
Basically, inside sweetalert2, captcha doesn't render...
I was anyway using multiple fields in SWAL... so I had to use fields inside the HTML parameter.
To address the invisible captcha, I took an idea from Invisible reCaptcha AJAX Call . From within sweetalert, using Swal.getPopup().querySelector('#field').value, in pre-confirm, I will populate hidden fields in the form that is outside of sweetalert and submit it via Ajax
Not a brilliantly clean solution but, hey, it works!

How to load javascript step by step with QWebEngineView and qtwebchannel.js?

I'm setting up like a framework who use python in backend and html/css/js for frontend. My problem arrived during the loading of a QWebEngineView.
I search on the web how to establish a communication between python and javascript with QWebEngineView and I finally tried to use QtWebChannel.
So I setted up everything, and everything worked good with communication between python and javascript, but the next issue appeared:
First: i can't load javascript files directly in html with tags <script>
Second: javascript loaded randomly, i tried to load javascript from python with my_view.page().runJavascript(my_js) but it work one try on two. So sometimes jQuery load at the end, so an other part of the code doesn't work.
base.html:
<!DOCTYPE html>
<html lang="en">
<p id="log"></p>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script>
window.onerror = function (error, url, line) {
console.error("ERROR: " + error.toString());
console.error("LINE: " + line.toString());
};
function load_app(){
new QWebChannel(qt.webChannelTransport, function (channel) {
window.app = channel.objects.app;
app.load_javascript(function(ret){
console.error("load javascript: " + ret)
});
});
}
load_app();
console.error("app loaded")
</script>
{{ application_html_content | safe }}
</html>
Another part of HTML:
{% extends 'base.html' %}
{% block content %}
<div class="row">
{% for user_id, user in user_dict.items() %}
<div id="{{ user_id }}" class="col s12 m6">
<div class="card blue-grey darken-1">
<div class="card-content white-text">
<span class="card-title">Visit Card</span>
<p>{{ user.name }}</p>
</div>
<div class="card-action">
<button id="btn_del_{{ user_id }}" class="btn blue waves-effect waves-light" onclick="delete_user({{ user_id }})">Delete</button>
<button class="btn blue waves-effect waves-light" onclick="detail_user({{ user_id }})">Detail</button>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block javascript %}
<script>
$(document).ready(function() {
app.request_result.connect(function (result) {
if ("delete" in result) {
user_id = result.delete;
var element = document.getElementById(user_id);
element.parentNode.removeChild(element)
}
});
console.error("ready");
});
function delete_user(user_id) {
document.getElementById("btn_del_" + user_id).innerHTML = "Waiting ...";
app.request('DemoHtml:Default:delete', user_id);
}
function detail_user(user_id) {
app.path('detail_user', {"user_id": user_id});
}
</script>
{% endblock %}
load_javascript function:
JQUERY = "vendor/Resources/js/jquery.js"
MATERIALIZE = "vendor/Resources/css/materialize/js/materialize.js"
#pyqtSlot(result=str)
def load_javascript(self):
with open(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.MATERIALIZE), "r") as m_stream:
materialize_content = m_stream.read()
with open(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.JQUERY), "r") as j_stream:
jquery_content = j_stream.read()
self.template_view.view.page().runJavaScript(jquery_content)
self.template_view.view.page().runJavaScript(materialize_content)
return "ok"
As you can see, normally I must see in log error:
First: "load javascript: ok"
Second: "app loaded"
but one time one two, this is reverse like:
js: app loaded
js: ERROR: Uncaught ReferenceError: $ is not defined
js: LINE: 67
js: Uncaught ReferenceError: $ is not defined
js: load javascript: ok
Any help for this?
Thank you in advance!
I resolved my problem, thanks to #ekhumoro for trying to help me, i found an answer on this thread:
How to wait for another JS to load to proceed operation ?: https://stackoverflow.com/a/8618519/8293533
So to make it work, i change my javascript to this:
I named this file app.js
function set_app() {
try{
new QWebChannel(qt.webChannelTransport, function (channel) {
window.app_channel = channel.objects.app;
});
} catch (e) {
console.error("setting_app error: " + e)
}
}
set_app();
function request(route, args) {
let interval = 10;
window.setTimeout(function () {
if (window["app_channel"]) {
app_channel.request(route, args)
} else {
try {
set_app();
}
catch(error) {
console.error("app load error: " + error)
}
window.setTimeout(arguments.callee, interval);
}
}, interval)
}
function path(route, args) {
let interval = 10;
window.setTimeout(function () {
if (window["app_channel"]) {
app_channel.path(route, args)
} else {
try {
set_app();
}
catch(error) {
console.error("app load error: " + error)
}
window.setTimeout(arguments.callee, interval);
}
}, interval)
}
function request_result(callback) {
let interval = 10;
window.setTimeout(function () {
if (window["app_channel"]) {
app_channel.request_result.connect(callback)
} else {
try {
set_app();
}
catch(error) {
console.error("app load error: " + error)
}
window.setTimeout(arguments.callee, interval);
}
}, interval)
}
I erase my code load_javascript in python because i found the way to call js with <script> tags and qrc:/// path.
Now my html head look like this:
<!DOCTYPE html>
<html lang="en">
<p id="log"></p>
<script src="qrc:///qwebchannel.js"></script>
<script src="qrc:///app.js"></script>
<script src="qrc:///jquery.js"></script>
{{ application_html_content | safe }}
<script src="qrc:///materialize.min.js"></script>
</html>
To use qrc:///xxx.js i used QResource and .qrc, .rcc files.
This is an example of my code for those who want:
class ApplicationContainer:
SRC_QRC_PATH = "src/*Bundle/Resources/qrc/*.qrc"
SRC_RCC_PATH = "src/*Bundle/Resources/qrc/*.rcc"
VENDOR_QRC_PATH = "vendor/*Bundle/Resources/qrc/*.qrc"
VENDOR_RCC_PATH = "vendor/*Bundle/Resources/qrc/*.rcc"
def __init__(self):
self.__pyqt_application = QApplication(sys.argv)
self.__pyqt_resources = QResource()
self.set_rcc_files()
#property
def application(self):
return self.__pyqt_application
#application.setter
def application(self, new_app: QApplication):
self.__pyqt_application = new_app
def set_rcc_files(self):
qrc_files = glob.glob(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.SRC_QRC_PATH))
qrc_files += glob.glob(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.VENDOR_QRC_PATH))
for qrc in qrc_files:
subprocess.call(["rcc", "-binary", qrc, "-o", qrc[:-3] + "rcc"])
rcc_files = glob.glob(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.SRC_RCC_PATH))
rcc_files += glob.glob(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), self.VENDOR_RCC_PATH))
for rcc in rcc_files:
self.__pyqt_resources.registerResource(rcc)
As you can see i use rcccommand, not pyrcc5
To finish, this is my .qrc file:
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource>
<file alias="jquery.js">../js/jquery.js</file>
<file alias="app.js">../js/app.js</file>
<file alias="qwebchannel.js">../js/qwebchannel.js</file>
<file alias="materialize.js">../css/materialize/js/materialize.js</file>
<file alias="materialize.css">../css/materialize/css/materialize.css</file>
</qresource>
</RCC>
I know there can be a lot of improvment and optimisation in javascript code and python code. But it works like this !
Thank's and hope i help someone too.

.on('mouseover') did not feedback info

I have such a snippet of ajax request:
<div>
<h4>Comments</h4>
<!-- <form action="/article/comment/create/{{ article.id }}" method='post'> -->
<form action="#">
<textarea class="form-control" rows="5" name='comment' id="commentContent"></textarea>
<br>
<button class="btn btn-primary" id="commentBtn">Post Your Comment</button>
</form>
</div>
</div><!--/class="col-xs-8 col-md-8">-->
</div><!-- row -->
<script src="/static/js/jquery-3.3.1.js"></script>
<script src="/static/js/jquery-csrf.js"></script>
<script>
$(document).ready(function(){
var article_id = article.id;
var num_pages = {{ page.num_pages }};
$("#commentBtn").on('mouseover', function(e){
e.preventDefualt();
alert("clicked")
var comment = $("#commentContent").val();
var param = {
"article_id": article.id
"content": comment};
$post("/comment/create/", param, function(data){
var ret = JSON.parse(data);
if (ret["status"] = "ok") {
$("#commentConent").val("");
window.location.href = "/article/detail/{{ article.id }}?page_number=" + num_pages;
} else {
alert(ret["msg"]);
}
});
});
});
</script>
I set the event type as mouseover,
However, when I place my mouse over the button "#commentBtn",
nothing occurs.
What's the problem it might be with my codes?
You have many syntax errors and typos in your code , and that's the cause of your problem , you write every thing correct , but I suggest you should use IDE like vscode to help you find this errors , IDEs help in finding undefined variables , or any syntax errors , to help you avoid this kind of problems and bugs , if you look at your code you'll see that ,
var num_pages = {{ page.num_pages }}; this code should be like this
var num_pages = page.num_pages ; if you try to extract num_pages into variable , also you can use destructuring which is ES6 feature
also you should change $post to $.post and e.preventDefualt(); to e.preventDefault();
I suggest that you should learn about ES6 features which will make your code better and enhance your development with JavaScript , things like const let and arrow functions and many great features , you can take an overview of this features here
es6-features
$(document).ready(function() {
// var article_id = article.id;
// var num_pages = {{ page.num_pages }};
$('#commentBtn').on('mouseover', function(e) {
e.preventDefault();
alert('clicked');
var comment = $('#commentContent').val();
var param = {
// "article_id": article.id
content: comment,
};
$.post('/comment/create/', param, function(data) {
var ret = JSON.parse(data);
if ((ret['status'] = 'ok')) {
$('#commentConent').val('');
window.location.href =
'/article/detail/{{ article.id }}?page_number=' + num_pages;
} else {
alert(ret['msg']);
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h4>Comments</h4>
<!-- <form action="/article/comment/create/{{ article.id }}" method='post'> -->
<form action="#">
<textarea class="form-control" rows="5" name='comment' id="commentContent"></textarea>
<br>
<button class="btn btn-primary" id="commentBtn">Post Your Comment</button>
</form>
</div>
</div><!--/class="col-xs-8 col-md-8">-->
</div><!-- row -->
Typo, use:
e.preventDefault();
Also:
$.post
And, at the end:
$("#commentContent")

Form in modal with symfony2 and jquery is not being submitted with data

I have a list of Schools displayed in my list.html.twig. For each school I need to insert some data which is filled in a form inside a modal. I need that once the form is filled, the modal is submitted and closes, showing again the background page. Normally the submit action of the modal causes page refresh, and I want to avoid that obviously.
The inspiration for the code was this tutorial, specifically I followed the creation of the form...
//school controller
$school = new School();
$form = $this->createForm(
new SchoolFormType($param),
$school,
array(
'action' => $this->generateUrl("school_modal_vp", array(
'param' => $param,
)),
'method' => 'POST'
));
if($request->isMethod('POST')) {
$form->handleRequest($request);
if($form->isValid()) {
$data = $form->getData();
$em->persist($data);
$em->flush();
$response = new Response(json_encode([
'success' => true,
]));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
... and the function which "replaces" the submit action of the modal with a AJAX call with form data, storing it to database and closing modal.
<script>
var param_id = '{{ param.id }}';
function sendForm(form, callback) {
// Get all form values
var values = {};
$.each( form[0].elements, function(i, field) {
if (field.type != 'checkbox' || (field.type == 'checkbox' && field.checked)) {
values[field.name] = field.value;
}
});
// Post form
console.log(values);
$.ajax({
type : form.attr( 'method' ),
url : form.attr( 'action' ),
data : values,
success : function(result) { callback( result ); }
});
}
$(function() {
$("#school_"+param_id+"_save").on("click", function( e ) {
e.preventDefault();
sendForm($("#myModalSchool_" + param_id).find('form'), function (response) {
$("#myModalSchool_" + param_id).modal('hide');
});
});
});
</script>
However, this works only for the last modal created while listing the schools. Any help is appreciated, and please if you need ask for details.
EDIT 1:
This is the template as requested
<div class="modal fade" data-backdrop="static" id="myModalSchool_{{ param.id }}">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h3 class="modal-title">
School
</h3>
</div>
<div class="modal-body">
<form id="school_{{ param.id }}" name="school_{{ param.id }}" method="post" action="{{ path('school_modal_vp', {param_id: param.id, }) }}" class="form-horizontal">
{{ form_errors(form) }}
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
</div>
I think the main problem is the var param_id = '{{ param.id }}'; which is defined manually in your javascript.
First, I advise you to add a class on all your save button (e.g modal-submit) and a data-id on each button.
Example:
<button type="button" class="btn btn-primary modal-submit" data-id="{{myData.id}}">Submit</button>
Then in your javascript when you click on a save button (with modal-submit), you retrieve the id from the data-id and execute the sendForm($("#myModalSchool_" + param_id).find('form'),....
Example:
$(function() {
$(".modal-submit").on("click", function( e ) {
e.preventDefault();
var param_id = $(this).attr('data-id');
sendForm($("#myModalSchool_" + param_id).find('form'), function (response) {
$("#myModalSchool_" + param_id).modal('hide');
});
});
});
EDIT:
Saved multiple times issue ?
Moreover, i think you defined the javascript above in each modal. That's why the save is called multiple times. You need to have only one instance of this javascript (so it can't be placed in your modal view). Try to put the javascript in your global layout.
Hope it will help

Categories