Jquery BlockUI - Wait for images before unblocking on ajax load - ajax

I'm using the BlockUI jquery plugin to show a loading message in a div until the content is loaded using JQuery's load method.
The problem is, the content I'm pulling in contains images. The load callback fires before the images are fully loaded and the div is unblocked too early.
Is there a way I can wait for all the images to load before BlockUI unblocks the div?
Alternatively, if I can override the unblocking I can do the following, using the waitForImages plugin
$('#mydiv').block({ message: 'Loading' });
$('#mydiv').load('ajax.php', function() {
$('#mydiv').waitForImages(function() {
$('#mydiv').unblock();
});
});

I reckon you should wrap your DIV #mydiv inside another DIV.
$.getJSON("http://api.flickr.com/services/feeds/photoset.gne?set=72157623591220769&nsid=21696934#N05&format=json&jsoncallback=?", function(data) {
$.each(data.items, function(i, item) {
$("<option>").attr("value", item.media.m).html('image ' + i).appendTo("#imagesLink");
});
});
$("#imagesLink").on('change', function() {
$('#mydivContainer').block({
message: 'Loading'
});
setTimeout(LoadImage, 10, this.value);
});
function LoadImage(imagePath)
{
$('#mydiv').html($('<img>').attr('src', imagePath));
$('#mydiv img').waitForImages(function() {
$('#mydivContainer').unblock();
// alert("Finished!");
});
}
#mydivContainer
{
width: 400px;
height: 400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://malsup.github.io/jquery.blockUI.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.waitforimages/2.4.0/jquery.waitforimages.js"></script>
choose an image <select id="imagesLink"></select>
<div id="mydivContainer">
<div id="mydiv"></div>
</div>
Or a fiddle jsFiddle where you can test it.

Related

Show Loader when submitting form In laravel collective

I am submitting a form directly without using Ajax request, I want to show loader when getting a response from the backend.
How is it possible?
{!! Form::open(['route' => ['patient_signup'], 'method' => 'post', 'name' => 'sign_up_form']) !!}
and in controller
public function patient_signup()
{
if ($result) {
return redirect(route('home'))->with('success', $message);
} else {
return Redirect::back()->withInput()->with('error', $message);
}
}
Everything working fine but I want to show loader when getting a response from the backend.
Please provide me a better solution.
You can add div tag after body tag like below
<body>
<div class="pageLoader" id="pageLoader"></div>
In css
.pageLoader{
background: url(../images/loader.gif) no-repeat center center;
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 9999999;
background-color: #ffffff8c;
}
then in JavaScript
$(window).on('beforeunload', function(){
$('#pageLoader').show();
});
$(function () {
$('#pageLoader').hide();
})
Updated
return redirect(route('home'))->with('success', $message)->with('loader',true);
then in JavaScript
$(window).on('beforeunload', function(){
#if(isset($loader))
$('#pageLoader').show();
#endif
});
$(function () {
$('#pageLoader').hide();
})
It feels like you're fudging this a little. Spinners typically work with ajax requests as the spinner provides a visual feedback that an action is ongoing. The action being a request has been sent to the server by the browser and the browser is now waiting on a response. The response is required in order to remove the spinner (response could also be a failure or timeout etc.) and the spinner is removed without a page refresh.
In your use case, the response from the server is in fact redirecting the user to another page, or back to the form page with errors.
So basically what you want to do is have a loading indicator (spinner, words, etc.) which is initially hidden and you display when the form is submitted and it will automatically disappear if the user is redirected back to your form page.
As an example:
<div class="relative grid place-items-center h-screen">
<form id="some-form">
<button id="form-submit" class="px-4 py-2 bg-gray-800 rounded text-white">Submit</button>
</form>
<div id="loader" class="hidden" style="display: none">
Loading ...
</div>
</div>
Then your javascript:
let form = document.querySelector('#some-form');
let loader = document.querySelector('#loader')
form.addEventListener('submit', function (event) {
event.preventDefault();
// using non css framework method with Style
loader.style.display = 'block';
// using a css framework such as TailwindCSS
loader.classList.remove('hidden');
// pretend the form has been sumitted and returned
setTimeout(() => loader.style.display = 'none', 1000);
});
You could use jQuery or whatever you want but you get the idea. Example jsFiddle here.

Using JQuery Waypoints to play a video when it is scrolled to

I'm trying to play an HTML5 video when the user scrolls to it using the waypoints plugin for jQuery.
Here is my code:
$(document).ready(function() { videoSetup(); });
function videoSetup() {
var video = $("#video");
video.waypoint(function(direction) {
video.get(0).play();
});
}
Put when the video is scrolled to nothing happens.
HTML markup would look like:
<div class="video-test">
<video id="video1" width="960">
<source src="video-folder/video.mp4" type="video/mp4">
</video>
</div>
Then your javascript to load the video at the video-test container waypoint would be:
$(document).ready(function() {
var myVideo=document.getElementById("video1");
$('.video-test').waypoint(function() {
myVideo.play();
}, {
offset: '50%', // middle of the page
triggerOnce: true // just my preference...
});
});

Events not working when using Mustache with Backbone.js

So I am making a test app using RequireJs, Mustache and Backbone.js. I had some success with rendering the collection of models with the Mustache template. But my Mustache template has a button and when I try to bind click event on the button in the view, the button click doesn't invoke the callback function. I am really stuck, can someone tell me where I am not doing right?
Here is my code:
ItemView.js:
define(['jquery', 'backbone', 'underscore', 'mustache', '../../atm/model/item'], function ($, Backbone, _, Mustache, Item) {
var ItemView = Backbone.View.extend({
initialize: function() {
},
tagName: 'li',
events: {
'click .button': 'showPriceChange'
},
render: function() {
var template = $('#template-atm').html();
var itemObj = this.model.toJSON();
itemObj['cid'] = this.model.cid;
var rendering = Mustache.to_html(template, itemObj);
this.el = rendering;
return this;
},
showPriceChange: function(event) {
alert('Changing...');
$('#' + elemId).empty();
$('#' + elemId).append(document.createTextNode('Changed'));
},
});
return ItemView;
});
atm.html:
<!DOCTYPE html>
<html>
<head>
<title>Elevator</title>
<script data-main="scripts/main" src="scripts/require-jquery.js"></script>
<style type="text/css">
</style>
</head>
<body>
<h1>Vending Machine</h1>
<div id="atm-items">
</div>
<script id="template-atm" type="html/template">
<li>
<p>Item: {{name}}</p>
<label for="price-{{cid}}">Price:</label>
<input id="price-{{cid}}" type="text" value="{{price}}"/>
<button class="button">Change</button>
<p id="status-{{name}}-{{cid}}">- -</p>
</li>
</script>
</body>
</html>
You're replacing the view's el inside render:
render: function() {
//...
this.el = rendering;
//...
}
When you do that, you're losing the jQuery delegate that is attached to this.el, that delegate handler (which Backbone adds) is responsible for the event routing.
Usually, you add things to this.el rather than replacing this.el. If your template looked like this:
<script id="template-atm" type="html/template">
<p>Item: {{name}}</p>
<label for="price-{{cid}}">Price:</label>
<input id="price-{{cid}}" type="text" value="{{price}}"/>
<button class="button">Change</button>
<p id="status-{{name}}-{{cid}}">- -</p>
</script>
then you would this.$el.append(rendering) in your view's render; this would give you an <li> in this.el since you've set your view's tagName to li.
Alternatively, if you really need to keep the <li> in the template, you could use setElement to replace this.el, this.$el, and take care of the event delegation:
this.setElement(rendering);
Presumably you're wrapping all these <li>s in a <ul>, <ol>, or <menu> somewhere else; if you're not then you're producing invalid HTML and the browser might try to correct it for you, the corrections might cause you trouble elsewhere as your HTML structure might not be what your selectors think it is.

image onclick event not working

im tryin to make a onclick event for my image, but its not workin..the alert is not showing up..
$(document).ready(function(){
$('img.closeAttrIcon').click(function(){
alert("ww");
});
});
even if i try like this with ..bind.. no hope...
$(document).ready(function(){
$('img.closeAttrIcon').bind('click',function(){
alert("ww");
});
});
the html will be created during this event:
$('a#btnAddStdntAttr').click(function(){
var newAttr = '<div class="attrParent"><br class="clear"><label></label><input type="text" id="stdntAttributeKey1" maxlength="250" style="width: 13%;" name="stdntAttributeKey1"/>';
newAttr+= '<input type="text" id="stdntAttributeValue1" maxlength="250" style="width: 13%;" name="stdntAttributeValue1"/>';
newAttr+= '<img src="<c:url value="/static/images/closeIcon.png"/>" onclick="removeStdntAttr();" class="closeAttrIcon" alt="Close" title="Close" /></div>';
$(this).after(newAttr);
});
what am i doing wrong here..please help..
it does not work because you are injecting it after the DOM is created for the first time, for that you need to use the live (if using til jQuery 1.7) or on if using (1.7+) binding method
change your call to:
$(function(){
$('img.closeAttrIcon').live('click', function() {
alert("ww");
});
});
if you're using jQuery 1.7+ then you can also do this:
$(document).on('click', 'img.closeAttrIcon', function() {
alert("ww");
});

Jquery not applying after html is replaced

I have some jquery functions that I call from the $(document).eady() function like the following :
<script type="text/javascript">
$(document).ready(function(){
$('.table_task_type tr').mouseover(function(){
$(this).addClass("hover");
});
$('.table_task_type tr').mouseleave(function(){
$(this).removeClass("hover");
});
$('input:checkbox').click(function() {
$(this).parent().parent().toggleClass('checked');
});
});
</script>
The thing is that I replace part of the html on some user action. I do it like :
$("#my_table").empty();
$("#my_table").html(data);
The jquery events are fired the first time the page is loaded, but as soon as the html of my table is replaced it doesn't work anymore.
Any workaround to that ?
use jquery live method
example:
$('.table_task_type tr').live('mouseover',function(){
$(this).addClass("hover");
});
You should use the .on() method as the previous posters have suggested. What you want to do is put the binding on a parent element of the container that is being refreshed.
<div id="content">
<div id="my_table">
<table>
<tr class="table_task_type">
<td>foo</td>
<td>bar</td>
<td>baz</td>
</tr>
</table>
</div>
</div>
$(function() {
$('#content').on('hover', '.table_task_type',
function() {
$(this).toggleClass('.rollover');
},
function() {
$(this).toggleClass('.rollover');
});
});
The listener is bound to the parent container of the one you are re-populating. Since the parent container (#content) is not re-populated, the binding won't break. It's also faster because the click event only has to bubble up one node in the DOM as opposed to bubbling all the way up to document.

Resources