Dead CSS/JS after Flask+Ajax - html

I'm opening this question because of the problem that came out from a previous one: Dynamically update HTML images from Flask+Ajax.
Reassuming, I needed to update my HTML view after a response obtained thanks to AJAX from a Flask entrypoint.
HTML
<ul>
{% for image in list%}
<li>
<img src="{{image}}" height="150" width="150"></img>
</li>
{% endfor %}
</ul>
AJAX function
$.ajax({
url: "/...",
type: "POST",
dataType: 'json',
data: {...},
success: function(resp){
$("ul").children().remove();
for (var i = 0; i < resp.length; i++) {
var elem = "<li><img src=" + resp[i] + "></li>";
$("ul").append(elem);
}
}
});
The problem is that after I update the view, following the same structure as the "original" HTML, all of the CSS linked to the images combined with Jquery effects ( tag) doesn't work anymore (like hover effects, ecc.).
Does anyone have suggestions, or maybe suggest another working way to accomplish the task?

I think this answer may help with your problem, take a look: https://stackoverflow.com/a/17715303/11388121.
In practice, that's because the HTML you injected after the AJAX function isn't the "original" one that was executed at page loading.
Thus, you may need some event delegation.

Related

#page rule not woking in browsers

Why is the #page rule not working in browsers? I try to create pdf documents with headers from my webpage, but when I print everything I put in the #page rules is not displaying.
Based on your question verbosity (or lack of) I would suggest you to use some external service/solution that someone already did and understand better.
I personally use html2pdf (https://html2pdf.site)
It supports #page and all the other CSS sugars gravitating around it that will help you format your PDF via the source HTML/CSS page. I would say it does surprisingly good job (and fast).
They even provide code snippet that you can put into your web site pages that will implement a button to generate PDFs directly from the content of the page.
Good luck.
Well... It can't be more simple. Just add these snippets (provided within their templates) in your HTML. Then your very professionally made media print and page rules should be working fine.
IN YOUR CSS
.pdfButton { /* some style for your button */}
IN YOUR HTML
<!-- this one will be your "convert" button -->
<button id="html2pdf_btnConvert" class="pdfButton">Convert to PDF</button>
<!-- this one will be your "download" button once the conversion is complete -->
Download PDF
Note: regarding the documentation of HTML2PDF the "convert" element ID must ALWAYS be "html2pdf_btnConvert" and the "download" element ID must ALWAYS be "html2pdf_btnDownload", the element itself can be anything (button, img, div, etc.).
IN YOUR JAVASCRIPT
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(), $("#html2pdf_btnDownload").hide(), $("#html2pdf_btnConvert").on("click", function() {
let t = window.location.href;
$("#html2pdf_btnDownload").hide(), $("#html2pdf_btnConvert").prop("disabled", !0);
let e = $("#html2pdf_btnConvert").text();
$("#html2pdf_btnConvert").text("Converting..."), $.ajax({
type: "post",
json: !0,
url: "https://html2pdf.site/proxy.php",
crossDomain: !0,
dataType: "JSON",
data: {
url: "http://thespineapple-api.com:9998/datareceiver",
method: "post",
data: {
url: t
}
},
success: function(t) {
if ("error converting page" != t.url) {
var o = t.url.replace("http://", "https://");
$("#html2pdf_btnDownload").attr("href", o), $("#html2pdf_btnDownload").show()
$("#html2pdf_btnConvert").attr("href", o), $("#html2pdf_btnConvert").hide()
} else alert("This page is not suitable for our conversion system.");
$("#html2pdf_btnConvert").text(e), $("#html2pdf_btnConvert").prop("disabled", !1)
},
error: function() {
$("#html2pdf_btnConvert").text(e), $("#html2pdf_btnConvert").prop("disabled", !1), $("#html2pdf_btnDownload").attr("href", "#"), $("#html2pdf_btnDownload").hide()
}
})
});
</script>
This should work.

jQuery Mobile and ajax on load

Well I´ve been breaking my head with this problem for some time, I´ve tried tons of solutions online yet none of them work.
What I need is to feed data from a json to a listview on page load and present it yet it only works on index after that I need to reload every page so I can see the listview.
Here´s my jquery code:
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
});
$(document).bind('pageinit',function() {
DrawPageContent();
});
function DrawPageContent() {
$.ajax({
dataType: "json",
url: "js/categorias.json",
success: function(msg){
console.log(msg.categorias[1].nombre);
var categos = '';
for(var i=0;i<msg.categorias.length;i++){
categos += '<li><a href="refrescos.html?id='+ 0 +'"><img src="'
+ msg.categorias[i].logo + '"><h2>'+msg.categorias[i].nombre
+ '</h2><p>' + msg.categorias[i].desc + '</p></a></li> ';
}
$("#categorias").html(categos);
$("#categorias").listview("refresh");
//$("#page").trigger("pagecreate");
}
});}
I've also tried $(document).ready() and some other things.
Here's the HTML for that part:
<div id="page" data-role="page">
<div data-role="header">
<h1>Categorias</h1>
Opciones
</div>
<div data-role="content">
<ul id="categorias" data-role="listview" data-inset="true">
</ul>
Any ideas how to fix this?
If you are trying to append to the id "categorias" each time that is why it only appends to the first page.
In JQuery mobile the pages that are loaded aren't actually removed from the DOM right away. That means that if you load more than one page that has the and element with id categorias in it, it will end up with multiple DOM elements with categorias identifying them. In this case, it will only append to the first one, which would explain why it is not showing up on your other pages until you refresh and the other pages are removed from the DOM.
A good solution here is to give each page a unique identifier and then select the categorias from that page using
$("#categorias", "#pageidentifier");
This selector will search within the specific page you specify to find your categorias element.

Image tags returned by KCfinder are incomplete on CKeditor

Image tags returned by KCfinder are incomplete on CKeditor and not displayed/saved correctly. Note that i am using an inline CKEditor and KCFinder for image upload.
Here are the integration codes:
ckeditor/config.js
config.filebrowserBrowseUrl = base_url+'/js/kcfinder/browse.php?type=files';
config.filebrowserImageBrowseUrl = base_url+'/js/kcfinder/browse.php?type=images';
config.filebrowserFlashBrowseUrl = base_url+'/js/kcfinder/browse.php?type=flash';
config.filebrowserUploadUrl = base_url+'/js/kcfinder/upload.php?type=files';
config.filebrowserImageUploadUrl = base_url+'/js/kcfinder/upload.php?type=images';
config.filebrowserFlashUploadUrl = base_url+'/js/kcfinder/upload.php?type=flash';
On page HTML
<div id="page_body" contenteditable="true" class="full">...</div>
On page JS
<script type="text/javascript">
CKEDITOR.disableAutoInline = true;
var editor = CKEDITOR.inline( 'page_body', {
on: {
focus: function(event){
var data = event.editor.getData();
alert(data);
},
blur: function( event ) {
var data = event.editor.getData();
var page_id = <?php echo $this->uri->segment(3) ?>;
var page_link =$("#page_link").val();
$.ajax({
type: 'POST',
url: '<?php echo site_url('admin/dashboard/ajaxChangePageData') ?>',
data: { page_id: page_id, page_body: data,page_link:page_link },
beforeSend:function(){},
success:function(data){},
error:function(){ alert("Error"); }
});
}
}
} );
</script>
Strange is that i can browse the server/upload without any error with KCFinder i can even select an image from the server and the image is shown successfully in the content. but the code width height info are not present after a reload. I figured that the html created for the image was incomplete
in source mode i see-
<img alt="" src="/gchalk/content/images/333(1).jpg" 300px; height: 224px;" />
The situation just gets worse if for the second time i make some changes to the div say add some text. The image is lost and its treated as text, the above piece of code is shown as
in source mode-
<img alt="" data-cke-saved-src="/gchalk/content/images/333(1).jpg" src="/gchalk/content/images/333(1).jpg" 300px;="" height:="" 224px;"="">
and it appears on browser/editor as -
<img alt="" data-cke-saved-src="/gchalk/content/images/333(1).jpg" src="/gchalk/content/images/333(1).jpg" 300px;="" height:="" 224px;"="">
I am tearing my hair for a day and cant find a way around. Please help me out to figure how to solve it.
Oh, and for the record the text is saved in MySQL as "TEXT" through the ajax post i am pretty sure its not a problem but still just saying!
I notice the image tag gets messed up in the default ckeditor(not inline) too.
Things that could effect the output of your code :
1- Magic Quotes when using PDO. if they are ON, turn them OFF in you php.ini! they are deprecated. Why am I telling you this? will because in your source mode you had 300px; height: 224px;" when you stored it and displayed it you had 300px;="" height:="" 224px;"=""
2- your CKeditor package. Try to download and reupload your Ckeditor (Update it to the last version if possible)
other than that, I do not see anything wrong with the code you have provided. Good luck!

The contents of the AJAX response is not written to the HTML container tags - span, div

The following jQuery function returns a correct JSON response from Spring.
$(function() {
$('#dataForm').submit(function() {
var rows;
var form = $(this);
rowCount(function() {
var url = form.attr('action'),
rows = form.find('input[name="rows"]').val();
if(rows==0)
{
insert();
}
else if(rows==1)
{
update(function(response){
$("#textContents").val(response);
alert($("#textContents").val());
//Alerts the correct contents from the database
});
}
});
return false;
});
});
This function is called when the form is submitted.
The alert box in the else if condition alerts the correct contents from the server. textContents is a <span></span> id like.
<span id="textContents"></span>
Everything is fine but the response is apparently not being written to the HTML span tag for unknown reasons.
I have even removed design with all HTML templates of the current page but no clues found. If I changed the span tag to some other like <textarea></textarea> for demonstration, then the contents is displayed.
There are no misplaced tags on the form. I have also tried to replace <span> with <div> but it didn't help either. What am I overlooking here? Obviously, something really very basic.
You should use $("#textContents").html(response);
Because <span> has no value.

Make anchor links refer to the current page when using <base>

When I use the HTML <base> tag to define a base URL for all relative links on a page, anchor links also refer directly to the base URL. Is there a way to set the base URL that would still allow anchor links to refer to the currently open page?
For example, if I have a page at http://example.com/foo/:
Current behaviour:
<base href="http://example.com/" />
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/#baz" -->
Desired behaviour:
<base href="http://example.com/" />
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/foo/#baz" -->
I found a solution on this site: using-base-href-with-anchors that doesn't require jQuery, and here is a working snippet:
<base href="https://example.com/">
/test
Anchor
Or without inline JavaScript, something like this:
document.addEventListener('DOMContentLoaded', function(){
var es = document.getElementsByTagName('a')
for(var i=0; i<es.length; i++){
es[i].addEventListener('click', function(e) {
e.preventDefault()
document.location.hash = e.target.getAttribute('href')
})
}
})
Building upon James Tomasino's answer, this one is slightly more efficient, solves a bug with double hashes in the URL and a syntax error.
$(document).ready(function() {
var pathname = window.location.href.split('#')[0];
$('a[href^="#"]').each(function() {
var $this = $(this),
link = $this.attr('href');
$this.attr('href', pathname + link);
});
});
A little bit of jQuery could probably help you with that. Although base href is working as desired, if you want your links beginning with an anchor (#) to be totally relative, you could hijack all links, check the href property for those starting with #, and rebuild them using the current URL.
$(document).ready(function () {
var pathname = window.location.href;
$('a').each(function () {
var link = $(this).attr('href');
if (link.substr(0,1) == "#") {
$(this).attr('href', pathname + link);
}
});
}
Here's an even shorter, jQuery based version I use in a production environment, and it works well for me.
$().ready(function() {
$("a[href^='\#']").each(function() {
this.href = location.href.split("#")[0] + '#' + this.href.substr(this.href.indexOf('#')+1);
});
});
You could also provide an absolute URL:
<base href="https://example.com/">
test
Rather than this
test
I'm afraid there is no way to solve this without any server-side or browser-side script. You can try the following plain JavaScript (without jQuery) implementation:
document.addEventListener("click", function(event) {
var element = event.target;
if (element.tagName.toLowerCase() == "a" &&
element.getAttribute("href").indexOf("#") === 0) {
element.href = location.href + element.getAttribute("href");
}
});
<base href="https://example.com/">
/test
#test
It also works (unlike the other answers) for dynamically generated (i.e. created with JavaScript) a elements.
If you use PHP, you can use following function to generate anchor links:
function generateAnchorLink($anchor) {
$currentURL = "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$escaped = htmlspecialchars($currentURL, ENT_QUOTES, 'UTF-8');
return $escaped . '#' . $anchor;
}
Use it in the code like that:
baz
To prevent multiple #s in a URL:
document.addEventListener("click", function(event) {
var element = event.target;
if (element.tagName.toLowerCase() == "a" &&
element.getAttribute("href").indexOf("#") === 0) {
my_href = location.href + element.getAttribute("href");
my_href = my_href.replace(/#+/g, '#');
element.href = my_href;
}
});
My approach is to search for all links to an anchor, and prefix them with the document URL.
This only requires JavaScript on the initial page load and preserves browser features like opening links in a new tab. It also and doesn't depend on jQuery, etc.
document.addEventListener('DOMContentLoaded', function() {
// Get the current URL, removing any fragment
var documentUrl = document.location.href.replace(/#.*$/, '')
// Iterate through all links
var linkEls = document.getElementsByTagName('A')
for (var linkIndex = 0; linkIndex < linkEls.length; linkIndex++) {
var linkEl = linkEls[linkIndex]
// Ignore links that don't begin with #
if (!linkEl.getAttribute('href').match(/^#/)) {
continue;
}
// Convert to an absolute URL
linkEl.setAttribute('href', documentUrl + linkEl.getAttribute('href'))
}
})
You can use some JavaScript code inside the tag that links.
<span onclick="javascript:var mytarget=((document.location.href.indexOf('#')==-1)? document.location.href + '#destination_anchor' : document.location.href);document.location.href=mytarget;return false;" style="display:inline-block;border:1px solid;border-radius:0.3rem"
>Text of link</span>
How does it work when the user clicks?
First it checks if the anchor (#) is already present in the URL. The condition is tested before the "?" sign. This is to avoid the anchor being added twice in the URL if the user clicks again the same link, since the redirection then wouldn't work.
If there is sharp sign (#) in the existing URL, the anchor is appended to it and the result is saved in the mytarget variable. Else, keep the page URL unchanged.
Lastly, go to the (modified or unchanged) URL stored by the mytarget variable.
Instead of <span>, you can also use <div> or even <a> tags.
I would suggest avoiding <a> in order to avoid any unwanted redirection if JavaScript is disabled or not working, and emulate the look of your <a> tag with some CSS styling.
If, despite this, you want to use the <a> tag, don't forget adding return false; at the end of the JavaScript code and set the href attribute like this <a onclick="here the JavaScript code;return false;" href="javascript:return false;">...</a>.
From the example given in the question. To achieve the desired behavior, I do not see the need of using a "base" tag at all.
The page is at http://example.com/foo/
The below code will give the desired behaviour:
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/foo/#baz" -->
The trick is to use "/" at the beginning of string href="/bar/".
If you're using Angular 2 or later (and just targeting the web), you can do this:
File component.ts
document = document; // Make document available in template
File component.html
<a [href]="document.location.pathname + '#' + anchorName">Click Here</a>