I update a version of all plugins, PHP, Jquery in my site
and now this code doesn't work.
when i go to this line :
$('#order_line_items .item .create-discount-for-item-'+ order_item_id).click();
it need go to this line:
$('body').on('click', this.selector, function(e)
but it no go there, and I don't have any errors
modalDiscountItem function:
$.fn.modalDiscountItem = function (options){
var settings = $.extend({
onChargeSuccess: false,
onChargeFailed: false,
orderId: 0,
order_item_id : false,
}, options);
var deferred = $.Deferred();
$('body').on('click', this.selector, function(e){
e.preventDefault();
var url = product_picker.ajax_url + "?action=discount_for_item";
url += "&order_id=" + settings.orderId;
url += "&order_item_id=" + settings.order_item_id;
url += "&TB_iframe=true&width=800&height=700";
tb_show("Discount for Item ", url);
icreditChargeModal.success = function(){
tb_remove();
deferred.resolve();
};
icreditChargeModal.failed = function(){
tb_remove();
deferred.fail()
}
});
return deferred;
}
anther function:
order_items_container.on('click', '.create-discount-for-item', function (e) {
var order_id = $('#post_ID').val();
var order_item_id = $(this).closest('tr.item').data('order_item_id');
if (!$('#order_line_items .item .create-discount-for-item-' + order_item_id).hasClass('active')) {
var deferred = $('#order_line_items .item .create-discount-for-item-' + order_item_id).modalDiscountItem({
orderId: order_id,
order_item_id: order_item_id
});
deferred.then(function () {
location.reload(true);
}, function () {
});
}
$('#order_line_items .item .create-discount-for-item-' + order_item_id).click();
$('#order_line_items .item .create-discount-for-item-' + order_item_id).addClass('active');
});
the output of $('#order_line_items .item .create-discount-for-item-' + order_item_id).length is 1
Related
I am learning javascript design patterns. So am converting my rough jquery code into cleaner module pattern. The question is, how will i call a click event after ajax has loaded in module pattern (Object literal). I used to solve it using $(document).ajaxcomplete(callback).
here is the working supergetti code
$('.meidaBtn, #media_load_btn').on('click', function(event) {
event.preventDefault();
$('.media').show(500);
$('#mediaBox').html('Loading...');
var link = location.origin + '/dashboard/media';
$.ajax({
url: link
}).done(function(data) { // data what is sent back by the php page
$('#mediaBox').html(data); // display data
// Click through
$('.imageBox img').bind('click', function() {
var src = $(this).attr('src');
var alt = $(this).attr('alt');
src = src.replace('tumbnail_', '');
tinyMCE.execCommand('mceInsertContent', false, '<img src="' + src + '" alt="' + alt + '">');
$('.media').hide();
});
});
});
Here is the javascript module pattern / object literal
var mediaPlugin = {
init: function() {
this.cacheDom();
this.bindEvents();
},
// Cache Dom
cacheDom: function() {
this.baseUrl = location.origin + '/dashboard/media';
this.$button = $('.meidaBtn, #media_load_btn');
this.$media = $('.media');
this.$mediaBox = $('#mediaBox');
this.$imageBox = $('.imageBox img');
},
// Bind Events
bindEvents: function() {
this.$button.on('click', this.render.bind(this));
this.$imageBox.on('click', this.addImage.bind(this));
},
// Show Data
render: function(e) {
e.preventDefault();
this.$media.show(500);
this.loadData();
},
// Load the data
loadData: function() {
var that = this;
$.ajax({
url: this.baseUrl,
type: 'GET',
success: function(data) {
// console.log(that.$mediaBox);
that.$mediaBox.html(data);
},
error: function() {
console.log("An error occored!");
},
complete: function() {
// console.log("I am now complete");
// that.loadMore();
}
});
},
// Add Image
addImage: function() {
var src = $(this).attr('src');
var alt = $(this).attr('alt');
src = src.replace('tumbnail_', '');
tinyMCE.execCommand('mceInsertContent', false, '<img src="' + src + '" alt="' + alt + '">');
this.$media.hide();
}
};
mediaPlugin.init();
The method provided below adds a simple property to the object which is used as a delegate/callback. You simply point your function to it and then it is called automatically since it is called in the complete event.
var mediaPlugin = {
init: function() {
this.cacheDom();
this.bindEvents();
},
// Cache Dom
cacheDom: function() {
this.baseUrl = location.origin + '/dashboard/media';
this.$button = $('.meidaBtn, #media_load_btn');
this.$media = $('.media');
this.$mediaBox = $('#mediaBox');
this.$imageBox = $('.imageBox img');
},
// Bind Events
bindEvents: function() {
this.$button.on('click', this.render.bind(this));
this.$imageBox.on('click', this.addImage.bind(this));
},
// Show Data
render: function(e) {
e.preventDefault();
this.$media.show(500);
this.loadData();
},
loadDataComplete: function() {},
// Load the data
loadData: function() {
var that = this;
$.ajax({
url: this.baseUrl,
type: 'GET',
success: function(data) {
// console.log(that.$mediaBox);
that.$mediaBox.html(data);
},
error: function() {
console.log("An error occored!");
},
complete: function() {
// console.log("I am now complete");
// that.loadMore();
that.loadDataComplete();
}
});
},
// Add Image
addImage: function() {
var src = $(this).attr('src');
var alt = $(this).attr('alt');
src = src.replace('tumbnail_', '');
tinyMCE.execCommand('mceInsertContent', false, '<img src="' + src + '" alt="' + alt + '">');
this.$media.hide();
}
};
var myCompleteFunction = function myCompleteFunction() {}
mediaPlugin.init();
mediaPlugin.loadDataComplete = myCompleteFunction;
mediaPlugin.loadData();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I finally figured how to get this code working. I used jquery .delegate() and i now work like magic. Below is the working code. thanks #abc123 for stoping by.
var media = (function(){
// Cache dom
var baseUrl = location.origin+'/dashboard/media';
var $button = $('.meidaBtn, #media_load_btn');
var $media = $('.media');
var $mediaBox = $('#mediaBox');
var $imageBox = $mediaBox.find('img');
var options = {
url: baseUrl,
type: 'GET',
success: function(data){
$mediaBox.html(data);
},
error: function(){
console.log("An error occored!");
},
complete: function(){
// console.log("I am now complete");
// that.loadMore();
}
};
// Bind Events
$button.on('click', _render);
$mediaBox.delegate('.imageBox', 'click', _addImage);
function _render(e){
e.preventDefault();
$media.show(500);
_loadData();
}
// Load images
function _loadData(){
$.ajax(options);
}
// Add Images
function _addImage(){
img = $(this).find('img');
console.log(img.attr('src')); // This should display the image url
}
})();
I have a open function that once triggered, simply plays video in a dedicated panel.
This function can be triggered in two ways - one with a click and another one with a page load (window load) with url that contains a valid anchor tag.
They all work fine but some codes of the window load handler are repetitive and I'm not too sure how I can keep this DRY.
Please take a look and point me in some directions on how I can write this better.
I commented in open function which is for which.
$.videoWatch.prototype = {
init: function() {
this.$openLinks = this.$element.find(".open");
this.$closeLinks = this.$element.find(".close");
this.open();
this.close();
},
_getContent: function(element) {
var $parent = element.parent(),
id = element.attr('href').substring(1),
title = $parent.data('title'),
desc = $parent.data('desc');
return {
title: title,
desc: desc,
id: id
}
},
open: function() {
var self = this;
//open theatre with window load with #hash id
window.onload = function() {
var hash = location.hash;
var $a = $('a[href="' + hash + '"]'),
content = self._getContent($a),
$li = $a.parents("li"),
$theatreVideo = $(".playing"),
$theatreTitle = $(".theatre-title"),
$theatreText = $(".theatre-text");
$(".theatre").attr('id', content.id);
$theatreTitle.text(content.title);
$theatreText.text(content.desc);
if ($theatreText.text().length >= 90) {
$(".theatre-text").css({
'overflow': 'hidden',
'max-height': '90px',
});
$moreButton.insertAfter($theatreText);
}
$a.parent().addClass("active");
$(".theatre").insertAfter($li);
$(".theatre").slideDown('fast', scrollToTheatre);
oldIndex = $li.index();
}
//open theatre with click event
self.$openLinks.on("click", function(e) {
// e.preventDefault();
if (curID == $(this).parent().attr("id")) {
$("figure").removeClass("active");
$("button.more").remove();
$(".theatre").slideUp('fast');
$('.playing').attr("src", "");
removeHash();
oldIndex = -1;
curID = "";
return false
} else {
curID = $(this).parent().attr("id");
}
var $a = $(this),
content = self._getContent($a),
$li = $a.parents("li"),
$theatreVideo = $(".playing"),
$theatreTitle = $(".theatre-title"),
$theatreText = $(".theatre-text");
$(".theatre").attr('id', content.id);
$theatreTitle.text(content.title);
$theatreText.text(content.desc);
if ($theatreText.text().length >= 90) {
$(".theatre-text").css({
'overflow': 'hidden',
'max-height': '90px',
});
$moreButton.insertAfter($theatreText);
}
if (!($li.index() == oldIndex)) {
$("figure").removeClass("active");
$(".theatre").hide(function(){
$a.parent().addClass("active");
$(".theatre").insertAfter($li);
$(".theatre").slideDown('fast', scrollToTheatre);
oldIndex = $li.index();
});
} else {
$(".theatre").insertAfter($li);
scrollToTheatre();
$("figure").removeClass("active");
$a.parent().addClass("active");
}
});
},
...
Simplified and refactored open method:
open: function() {
var self = this;
var serviceObj = {
theatreVideo : $(".playing"),
theatre: $(".theatre"),
theatreTitle : $(".theatre-title"),
theatreText : $(".theatre-text"),
setTheatreContent: function(content){
this.theatre.attr('id', content.id);
this.theatreTitle.text(content.title);
this.theatreText.text(content.desc);
if (this.theatreText.text().length >= 90) {
this.theatreText.css({
'overflow': 'hidden',
'max-height': '90px',
});
$moreButton.insertAfter(this.theatreText);
}
},
activateTeatre: function(a, li){
a.parent().addClass("active");
this.theatre.insertAfter(li);
this.theatre.slideDown('fast', scrollToTheatre);
oldIndex = li.index();
}
};
//open theatre with window load with #hash id
window.onload = function() {
var hash = location.hash;
var $a = $('a[href="' + hash + '"]'),
content = self._getContent($a),
$li = $a.parents("li");
serviceObj.setTheatreContent(content);
serviceObj.activateTeatre($a, $li);
}
//open theatre with click event
self.$openLinks.on("click", function(e) {
// e.preventDefault();
if (curID == $(this).parent().attr("id")) {
$("figure").removeClass("active");
$("button.more").remove();
$(".theatre").slideUp('fast');
$('.playing').attr("src", "");
removeHash();
oldIndex = -1;
curID = "";
return false
} else {
curID = $(this).parent().attr("id");
}
var $a = $(this),
content = self._getContent($a),
$li = $a.parents("li");
serviceObj.setTheatreContent(content);
if (!($li.index() == oldIndex)) {
$("figure").removeClass("active");
$(".theatre").hide(function(){
serviceObj.activateTeatre($a, $li);
});
} else {
$(".theatre").insertAfter($li);
scrollToTheatre();
$("figure").removeClass("active");
$a.parent().addClass("active");
}
});
},
1st of all there are variables that don't depend on the input, you could pull them to the class (I'll show just one example, as you asked for directions):
init: function() {
this.$theatreVideo = $(".playing");
All the variables that do depend on the input, like $li could be moved to a function:
var $a = $(this),
$dependsOnA = self.dependsOnA($a);
self.actionDependsOnA($dependsOnA); // see below
function dependsOnA($a) {
return {
a: $a,
li: $a.parents("li"),
content: self._getContent($a)
}
}
Also the code that "repeats" can be moved to a function:
function actionDependsOnA($dependsOnA)
$(".theatre").attr('id', $dependsOnA.content.id);
$theatreTitle.text($dependsOnA.content.title);
$theatreText.text($dependsOnA.content.desc);
}
I have a problem with ajax call after success.
I am trying to call my following javascript codes:
function imgResize($, sr) {
var debounce = function(func, threshold, execAsap) {
var timeout;
return function debounced() {
var obj = this,
args = arguments;
function delayed() {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}
// smartresize
jQuery.fn[sr] = function(fn) {
return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr);
};
};
//CALL ON PAGE LOAD OR ANY TIME YOU WANT TO USE IT
imgResize(jQuery, 'smartresize');
/* Wait for DOM to be ready */
// Detect resize event
$(window).smartresize(function() {
// Set photo image size
$('.photo-row').each(function() {
var $pi = $(this).find('.photo-item'),
cWidth = $(this).parent('.photo').width();
// Generate array containing all image aspect ratios
var ratios = $pi.map(function() {
return $(this).find('img').data('org-width') / $(this).find('img').data('org-height');
}).get();
// Get sum of widths
var sumRatios = 0,
sumMargins = 0,
minRatio = Math.min.apply(Math, ratios);
for (var i = 0; i < $pi.length; i++) {
sumRatios += ratios[i] / minRatio;
};
$pi.each(function() {
sumMargins += parseInt($(this).css('margin-left')) + parseInt($(this).css('margin-right'));
});
// Calculate dimensions
$pi.each(function(i) {
var minWidth = (cWidth - sumMargins) / sumRatios;
$(this).find('img')
.height(Math.floor(minWidth / minRatio))
.width(Math.floor(minWidth / minRatio) * ratios[i]);
});
});
});
/* Wait for images to be loaded */
$(window).load(function() {
$(".photo").each(function() {
var imgGrab = $(this).find('.photo-item');
var imgLength = imgGrab.length;
for (i = 0; i < imgLength; i = i + 3) {
imgGrab.eq(i + 1)
.add(imgGrab.eq(i + 1))
.add(imgGrab.eq(i + 2))
.wrapAll('<div class="photo-row"></div>');
}
$(this).find(".photo-item").each(function() {
if ($(this).parent().is(":not(.photo-row)")) {
$(this).wrap('<div class="photo-row"></div>');
}
});
// Store original image dimensions
$(this).find('.photo-item img').each(function() {
$(this)
.data('org-width', $(this)[0].naturalWidth)
.data('org-height', $(this)[0].naturalHeight);
});
});
$(window).resize();
});
And here is my ajax code for LOAD MORE POST
$('body').on("click",'.morep', function(event) {
event.preventDefault();
var ID = $(this).attr("id");
var P_ID = $(this).attr("rel");
var URL = $.base_url + 'more_post.php';
var dataString = "lastpid=" + ID + "&post_id=" + P_ID;
if (ID) {
$.ajax({
type: "POST",
url: URL,
data: dataString,
cache: false,
beforeSend: function() {
$("#more" + ID).html('<img src="loaders/ajaxloader.gif" />');
},
success: function(html) {
$("div.post-content").append(html);
$("#more" + ID).remove();
imgResize(jQuery, 'smartresize');
}
});
} else {
$("#more").html('FINISHED');
}
return false;
});
The ajax should call imgResize(jQuery, 'smartresize'); but it is not working. What I am missing here anyone can help me here ?
I'm looking for the opposite of that everyone's been looking for. I have this anonymous jQuery function that I want to keep that way, but I want to attach multiple events handlers to it on different events (two events exactly).
When the textarea has text inside it changed (keyup)
When document is clicke (click).
I know that grabbing the callback function and putting it in a function declaration, then using the function on both cases would do the job, but is there something around that wont require me to put the callback function in a normal function and just leave it as is?
This is the code I currently have:
urls.keyup(function(){
delay('remote', function(){
if (urls.val().length >= char_start)
{
var has_lbrs = /\r|\n/i.test(urls.val());
if (has_lbrs)
{
urls_array = urls.val().split("\n");
for (var i = 0; i < urls_array.length; i++)
{
if (!validate_url(urls_array[i]))
{
urls_array.splice(i, 1);
continue;
}
}
}
else
{
if (!validate_url(urls.val()))
{
display_alert('You might have inserted an invalid URL.', 'danger', 3000, 'top');
return;
}
}
final_send = (has_lbrs && urls_array.length > 0) ? urls_array : urls.val();
if (!final_send)
{
display_alert('There went something wrong while uploading your images.', 'danger', 3000, 'top');
return;
}
var template = '<input type="text" class="remote-progress" value="0" />';
$('.pre-upload').text('').append(template);
$('.remote-progress').val(0).trigger('change').delay(2000);
$('.remote-progress').knob({
'min':0,
'max': 100,
'readOnly': true,
'width': 128,
'height': 128,
'fgColor': '#ad3b3b',
'bgColor': '#e2e2e2',
'displayInput': false,
'cursor': true,
'dynamicDraw': true,
'thickness': 0.3,
'tickColorizeValues': true,
});
var tmr = self.setInterval(function(){myDelay()}, 50);
var m = 0;
function myDelay(){
m++;
$('.remote-progress').val(m).trigger('change');
if (m == 100)
{
// window.clearInterval(tmr);
m = 0;
}
}
$.ajax({
type: 'POST',
url: 'upload.php',
data: {
upload_type: 'remote',
urls: JSON.stringify(final_send),
thumbnail_width: $('.options input[checked]').val(),
resize_width: $('.options .resize_width').val(),
album_id: $('#album_id').val(),
usid: $('#usid').val(),
},
success: function(data) {
// console.log(data); return;
var response = $.parseJSON(data);
if (response)
{
$('.middle').hide();
$('.remote-area').hide();
window.clearInterval(tmr);
}
if ('error' in response)
{
//console.log(response.error);
if (!$('.top-alert').is(':visible'))
{
display_alert(response.error, 'danger', 3000, 'top');
}
return;
}
if (!target.is(':visible'))
{
target.show().addClass('inner');
}
else
{
target.addClass('inner');
}
for (var key in response)
{
var image_url = response[key];
var thumb_uri = image_url.replace('/i/', '/t/');
var forum_uri = '[img]' + image_url + '[/img]';
var html_uri = '<a href="' + image_url + '">' + image_url + '</a>';
var view_url = image_url.replace(/store\/i\/([A-Za-z0-9]+)(?=\.)/i, "image/$1");
view_url = strstr(view_url, '.', true);
// Append the upload box
target.append(upload_box(key));
// Hide knob
$('.knobber').hide();
// Put the image box
putImage($('.' + key), view_url, image_url, thumb_uri, forum_uri, html_uri);
}
},
});
}
}, 2000); // Delay
}); // Remote upload
How do I make this code run on document click as well?
Thank you.
As you yourself has said in you question, the answer is to create an external named reference to the callback function and use it as the callback.
Like
jQuery(function () {
function callback(e) {
console.log('event2', e.type);
}
$('input').keyup(callback);
$(document).click(callback)
})
But since you have asked for a different style have a look at, it essentially does the same as the above one
jQuery(function () {
var callback;
$('input').keyup(callback = function (e) {
console.log('event', e.type);
});
$(document).click(callback)
})
Demo: Fiddle
I'm using Isotope with AJAX to pull in some posts in WordPress, pretty much everything is there, except for the default Isotope animation runs when I AJAX in content, which looks a bit weird. I still wanted it to animate when filtered though.
So I thought I could just use add/removeClass within my AJAX function to turn it off/on when needed, but if I do the animation never runs.
Any ideas where I'm going wrong here?
var page = 1;
var loading = true;
var $window = $(window);
var $content = $('.isotope');
if( $('body').hasClass('home') ) {
var loopHandler = '/inc/loop-handler.php';
} else {
var loopHandler = '/inc/loop-handler-archive.php';
}
var load_posts = function(){
$.ajax({
type : "GET",
data : {numPosts : 1, pageNumber: page},
dataType : "html",
url : templateDir+loopHandler,
beforeSend : function(){
if(page != 1){
$('.loader').append('<div id="temp_load" style="text-align:center; z-index:9999;">\
<img src="'+templateDir+'/img/ajax-loader.gif" />\
</div>');
}
},
success : function(data){
$data = $(data);
if($data.length){
var itemHeight = $('.item').height();
var height = $content.height()+itemHeight*2;
$content.append($data);
$content.css('min-height', height);
$data.hide();
// should stop the animation
$('.isotope').addClass('no-transition');
$content.isotope('destroy');
$content.imagesLoaded( function(){
$content.isotope({
// options
layoutMode: 'fitRows',
itemSelector : '.item'
});
});
$data.fadeIn(700, function(){
$("#temp_load").fadeOut(700).remove();
loading = false;
});
// should start up the animation again
$('.isotope').removeClass('no-transition');
$content.css('min-height', '0');
} else {
$("#temp_load").remove();
}
},
error : function(jqXHR, textStatus, errorThrown) {
$("#temp_load").remove();
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
}
$window.scroll(function() {
var content_offset = $content.offset();
console.log(content_offset.top);
if(!loading && ($window.scrollTop() +
$window.height()) > ($content.scrollTop() +
$content.height() + content_offset.top)) {
loading = true;
page++;
load_posts();
}
});
load_posts();
If you need any of the HTML/PHP I'm happy to post it up. Also, here's the dev site if you want to check it out.
I don't know Isotope and I have not tested if it works. But I have refactor your code with annotations to help you better understand the problem.
I think it comes from how you call removeClass and addClass successively, the two instantly cancel.
var page = 1;
var loading = true;
var $window = $(window);
var $content = $('.isotope');
var loopHandler = '/inc/loop-handler.php';
var isotopeController = {
append: function($data) {
// Add AJAX data
var itemHeight = $('.item').height();
var height = $content.height() + itemHeight * 2;
$content.append($data);
$content.css('min-height', height);
// Stop
isotopeController.stop($data);
// Restart
$content.imagesLoaded(function() {
// When images loaded !
isotopeController.start($data);
});
},
start: function($data) {
// Start isotope
$content.isotope({
layoutMode: 'fitRows',
itemSelector: '.item'
});
// Show data
$data.fadeIn(700, function() {
$("#temp_load").fadeOut(700).remove();
loading = false;
});
// Start the animation
$content.removeClass('no-transition');
$content.css('min-height', '0');
},
stop: function($data) {
// Hide data
$data.hide();
// Stop the animation
$content.addClass('no-transition');
// Stop isotope
$content.isotope('destroy');
},
loadPosts: function() {
$.ajax({
type: "GET",
data: {
numPosts: 1,
pageNumber: page
},
dataType: "html",
url: templateDir + loopHandler,
beforeSend: function() {
if (page != 1) {
$('.loader').append('' +
'<div id="temp_load" style="text-align:center; z-index:9999;">' +
'<img src="' + templateDir + '/img/ajax-loader.gif" />' +
'</div>'
);
}
},
success: function(data) {
var $data = $(data);
if ($data.length) {
isotopeController.append($data);
} else {
$("#temp_load").remove();
}
},
error: function(jqXHR, textStatus, errorThrown) {
$("#temp_load").remove();
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
}
});
}
};
$window.scroll(function() {
var content_offset = $content.offset();
if (!loading && ($window.scrollTop() + $window.height()) > ($content.scrollTop() + $content.height() + content_offset.top)) {
loading = true;
page++;
isotopeController.loadPosts();
}
});
// On load
$(function() {
if (!$('body').hasClass('home')) {
loopHandler = '/inc/loop-handler-archive.php';
}
isotopeController.loadPosts();
});