How do I hide the parent element of one that triggered an action with jQuery? - jquery-selectors

I have this code in html (notice the numers 1 and 2in the outside and inside elements):
<div class="list_item" id="item_1">
<div class="list_item_int">My first line</div>
<div class="eval_buttons">
<div class="approve" id="1"></div>
<div class="dismiss" id="1"></div>
</div>
<div class="list_item" id="item_2">
<div class="list_item_int">My second line</div>
<div class="eval_buttons">
<div class="approve" id="2"></div>
<div class="dismiss" id="2"></div>
</div>
Then I have this script:
$().ready(function(){
$(".approve").click(function(){
$.post(
"php/judge_work.php",
{action : "1", work_info : this.id},
function(data){
$("#item_" + this.id).hide("slow");
}
);
});
$(".dismiss").click(function(){
$.post(
"php/judge_work.php",
{action : "0", work_info : this.id},
function(data){
alert(data);
}
);
});
});
Is there a way to make $("#item_" + this.id).hide("slow"); work? thanks on your kind response.

You can use .closest(), like this:
$(this).closest(".list_item") //gets the ancestor <div class="list_item">
In your case since this won't be the clicked element in the $.post() callback, it'll look like this:
$(".approve").click(function(){
var li = $(this).closest(".list_item");
$.post(
"php/judge_work.php",
{action : "1", work_info : this.id},
function(data){
li.hide("slow");
}
);
});

Related

Bigcommerce redirect on cart page

Adding custom script into my cart.html file in bigcommerce to include a script that will redirect card holder to google.com when they click checkout (only going to google for now while testing script)
When the script is loaded I see the following error in the console (self.checkoutButton.on is not a function)
Here is the script + file
cart: true
<script>
document.addEventListener("DOMContentLoaded", function () {
var debug = true ? console.log.bind(console, '[DEBUG][Cart]') : function () {};
debug('Script loaded');
window.Cart = function (options) {
var self = {}
function init() {
self.options = Object.assign({
checkoutButtonSelector: document.getElementById("checkout"),
checkoutUrl: 'https://google.com',
}, options);
self.checkoutButton = (self.options.checkoutButtonSelector);
debug('Initialized with options', self.options);
inject();
}
function inject() {
debug('Inject');
self.checkoutButton.on('click', checkout);
}
function checkout(event) {
var checkoutUrl = getCheckoutURL(self.options.products);
debug('Checkout ->', checkoutUrl);
event.preventDefault();
window.location.href = checkoutUrl;
}
function getCartCookie(name) {
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match){
return match[2];
}
}
function getCheckoutURL(products) {
cookie = getCartCookie('cart');
var urlLineItems = Object.keys(products).reduce(function (output, productId) {
var quantity = products[productId];
return output.concat([ productId + ':' + quantity ]);
}, []).join(';');
return self.options.checkoutUrl + '?products=' + urlLineItems + '&cartId='+cookie;
}
init();
return self;
};
var instance = new Cart();
});
</script>
<div class="page">
<main class="page-content" data-cart>
{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}}
{{> components/cart/page-title}}
<div data-cart-status>
{{> components/cart/status-messages}}
</div>
{{#if cart.items.length}}
<div class="loadingOverlay"></div>
<div data-cart-content class="cart-content-padding-right">
{{> components/cart/content}}
</div>
<div data-cart-totals class="cart-content-padding-right">
{{> components/cart/totals}}
</div>
{{#if cart.show_primary_checkout_button}}
<div class="cart-actions cart-content-padding-right">
<a class="button button--primary" id='checkout' title="{{lang 'cart.checkout.title'}}">{{lang 'cart.checkout.button'}}</a>
{{#if cart.show_multiple_address_shipping}}
<a class="checkoutMultiple" href="{{urls.checkout.multiple_address}}">
{{lang 'cart.preview.checkout_multiple'}}
</a>
{{/if}}
</div>
{{else}}
<div class="cart-actions cart-content-padding-right">
<a class="button" href="{{urls.home}}" title="{{lang 'cart.continue_shopping'}}">{{lang 'cart.continue_shopping'}}</a>
</div>
{{/if}}
{{#if cart.additional_checkout_buttons}}
<div class="cart-additionalCheckoutButtons cart-content-padding-right">
{{#each cart.additional_checkout_buttons}}
{{{this}}}
{{/each}}
</div>
{{/if}}
{{else}}
<h3 tabindex="0">{{lang 'cart.checkout.empty_cart'}}</h3>
{{/if}}
</main>
</div>
{{/partial}}
{{> layout/base}}
Would you have any idea why I would be getting the following error? Thanks in advance
You are using .on which is a JQuery function. You’re not using JQuery to wrap your selector, you’re just using the vanilla JS getElementById. You need to use a vanilla JS function to add the event, such as addEventListener.

how to use jQuery Isotope to filter jQuery Fancybox gallery

I use FancyBox and Isotope on my personnal gallery website and I discover that FancyBox shows all pictures even if they are filtered by isotope.
I have a look on different solutions:
jQuery Isotope filtering with Fancybox
How to only show filtered images in fancybox when using isotope filters and multiple filters?
but no one works for me.
In my case, I have a js file to configure FancyBox, and FancyBox may be used without isotope, in other part of my gallery:
$(document).ready( function() {
$().fancybox({
selector : '[data-fancybox="images"]',
loop : true,
margin : [20, 0],
buttons : [
'thumbs',
'slideShow',
'close'
],
protect : true,
animationEffect : 'fade',
touch : {
vertical : false
},
slideShow : {
autoStart : false,
speed : 3000
},
clickContent : function( current, event ) {
return current.type === 'image' ? 'toggleControls' : false;
},
clickSlide : false,
clickOutside : false,
dblclickContent : function( current, event ) {
return current.type === 'image' ? 'next' : false;
},
caption : function( instance, item ) {
if ($(this).find('.caption').length) {
return $(this).find('.caption').html();
} else {
return $(this).attr('title');
};
},
mobile : {
thumbs : false,
idleTime : 3,
clickContent : function( current, event ) {
return current.type === 'image' ? 'toggleControls' : false;
},
dblclickContent : function( current, event ) {
return current.type === 'image' ? 'next' : false;
},
dblclickSlide : false,
},
});
});
my html and js code is a following
<div class="pager">
<div class="btn-group filters-button-group">
<button class="btn btn-default btn-sm active" data-filter="*">Toutes</button>
<button class="btn btn-default btn-sm" data-filter=".2010">2010</button>
<button class="btn btn-default btn-sm" data-filter=".2011">2011</button>
<button class="btn btn-default btn-sm" data-filter=".2012">2012</button>
</div>
</div>
<div id="isotope-wrap" class="margin-bottom-double">
<div class="gutter-sizer"></div>
<div class="image-item image-item-height2 2010">
<a class="thumb" href="/albums/fetes-des-lumieres-de-lyon/img_8743.jpg" title="Cathédrale Saint-Jean / 2012" data-fancybox="images">
<img src="/cache/fetes-des-lumieres-de-lyon/img_8743_w150_h235_cw150_ch235_thumb.jpg" alt="Cathédrale Saint-Jean / 2012" class="remove-attributes img-responsive" width="150" height="235" />
</a>
</div>
<div class="image-item image-item-width2 2011">
<a class="thumb" href="/albums/fetes-des-lumieres-de-lyon/img_2216.jpg" title="Fontaine Bartholdi / 2005" data-fancybox="images">
<img src="/cache/fetes-des-lumieres-de-lyon/img_2216_w235_h150_cw235_ch150_thumb.jpg" alt="Fontaine Bartholdi / 2005" class="remove-attributes img-responsive" width="235" height="150" />
</a>
</div>
<div class="image-item image-item-height2 2012">
<a class="thumb" href="/albums/fetes-des-lumieres-de-lyon/img_8709.jpg" title="Cathédrale Saint-Jean / 2012" data-fancybox="images">
<img src="/cache/fetes-des-lumieres-de-lyon/img_8709_w150_h235_cw150_ch235_thumb.jpg" alt="Cathédrale Saint-Jean / 2012" class="remove-attributes img-responsive" width="150" height="235" />
</a>
</div>
[...]
</div>
<script type="text/javascript">
// init Isotope after all images have loaded
var $containter = $('#isotope-wrap').imagesLoaded( function() {
$containter.isotope({
itemSelector: '.image-item',
layoutMode: 'packery',
// packery layout
packery: {
gutter: '.gutter-sizer',
}
});
});
// bind filter button click
$('.filters-button-group').on( 'click', 'button', function() {
var filterValue = $(this).attr('data-filter');
$containter.isotope({ filter: filterValue });
});
// change is-active class on buttons
$('.btn-group').each( function( i, buttonGroup ) {
var $buttonGroup = $(buttonGroup);
$buttonGroup.on( 'click', 'button', function() {
$buttonGroup.find('.active').removeClass('active');
$(this).addClass('active');
});
});
</script>
what can I do to dynamicaly configure FancyBox ot display only displayed pictures filtered by Isotope?
you can see my website and my issue in action here http://www.vincentbourganel.fr/fetes-des-lumieres-de-lyon/
Thanks for your help.
Tweak your selector so it returns only visible items, example:
selector : '.image-item:visible > a'
You can use any valid jQuery selector here.

Alfresco - Categories Picker

I want to use the JavaScript Alfresco.ObjectPicker component in order to have category picker into the file: dnd-upload.get.html.ftl
<div class="form-field inlineable">
<label >Catégories:</label>
<div class="object-finder inlineable" id="a_default_prop_cm_categories-cntrl">
<div class="current-values inlineable object-finder-items" id="b_default_prop_cm_categories-cntrl-currentValueDisplay"></div>
<input type="hidden" value="" name="prop_cm_categories" id="c_default_prop_cm_categories"/>
<div class="show-picker inlineable" id="d_default_prop_cm_categories-cntrl-itemGroupActions"><span class="yui-button yui-push-button" id="yui-gen7"><span class="first-child"><button type="button" tabindex="0" id="yui-gen7-button" >Sélectionner</button></span></span></div>
<script type="text/javascript"> //<![CDATA[
(function(){
var picker = new Alfresco.ObjectFinder("a_default_prop_cm_categories-cntrl", "c_default_prop_cm_categories").setOptions(
{
field: "prop_cm_categories",
compactMode: true,
mandatory: false,
currentValue: "",
selectActionLabel: "Sélectionner",
minSearchTermLength: 1,
maxSearchResults: 1000
}).setMessages(
{""}
);
picker.setOptions(
{
itemType: "cm:category",
multipleSelectMode: true,
parentNodeRef: "alfresco://category/root",
itemFamily: "category",
maintainAddedRemovedItems: false,
params: "",
createNewItemUri: "",
createNewItemIcon: ""
});
})();
//]]>
</script>
</div>
</div>
And I have declared a JS dependency in the same file: dnd-upload.get.html.ftl
<#script type="text/javascript" src="${url.context}/res/components/object-finder/object-finder.js" group="objectfinder"/>
When I click on the button : "Sélectionner" , nothing happens and I have no console error neither.
Do you , Please, have any idea about how to make this Picker Working ?
Regards,
Sofia.

Unable to get mizzao/meteor-autocomplete to work with collection

I am using mizzao/meteor-autocomplete and am having problems in trying to get it to work.
When viewing the page in my browser, I am getting no results at all when typing any text. I've created the appropriate collection:
Institutions = new Mongo.Collection("institutions");
and know that there is data in the actual db, however still no success.
I've included my files below.
publications.js (located in the server folder)
Meteor.publish('institutions', function(args) {
return Institutions.find({}, args);
});
registrationStart.js
I've two helpers; one that actually powers the search and the other that should be returning the institutions. I have also tried this with the token: '#' argument with no success.
if (Meteor.isClient) {
Template.registrationStart.helpers({
settings: function() {
return {
position: "top",
limit: 7,
rules: [{
collection: Institutions,
field: "name",
options: '',
matchAll: true,
template: Template.institutionSelectDisplay
}]
};
},
institutions: function() {
return Instititions.find();
}
});
Template.registrationStart.events({
"autocompleteselect input": function(event, template, doc) {
// Session.set(event.target.name, event.target.value);
console.log("selected: ", doc);
console.log("event.target.name: ", event.target.name);
console.log("event.target.value: ", event.target.value);
}
});
}
registrationStart.html template
<template name="registrationStart">
<div class="panel-body" id="loginForm">
<h2 class="pageTitle">veClient Registration</h2>
<form>
<div> </div>
<fieldset>
{{> inputAutocomplete settings=settings id="institution" class="input-xlarge" placeholder="type institution here"}}
</fieldset>
<div> </div>
<button type="submit" class="btn btn-primary btn-sm">Continue Registration</button>
</form>
</div>
</template>
And the template to be rendered
<template name="institutionSelectDisplay">
<p class="inst-state">{{city}}, {{state}}</p>
<p class="inst-name">{{name}}</p>
<p class="inst-description">{{email}}</p>
</template>
Problem resulted because there was no subscription to the "institutions" publication. So need to add a subscribe statement to the registrationStart.js file:
Meteor.subscribe('institutions');

Handle radio button form in Marionette js

I'm trying to construct a view in my app that will pop up polling questions in a modal dialog region. Maybe something like this for example:
What is your favorite color?
>Red
>Blue
>Green
>Yellow
>Other
Submit Vote
I've read that Marionette js doesn't support forms out of the box and that you are advised to handle on your own.
That structure above, branch and leaves (question and list of options), suggests CompositeView to me. Is that correct?
How do I trigger a model.save() to record the selection? An html form wants an action. I'm unclear on how to connect the form action to model.save().
My rough draft ItemView and CompositeView code is below. Am I in the ballpark? How should it be adjusted?
var PollOptionItemView = Marionette.ItemView.extend({
template: Handlebars.compile(
'<input type="radio" name="group{{pollNum}}" value="{{option}}">{{option}}<br>'
)
});
var PollOptionsListView = Marionette.CompositeView.extend({
template: Handlebars.compile(
//The question part
'<div id="poll">' +
'<div>{{question}}</div>' +
'</div>' +
//The list of options part
'<form name="pollQuestion" action="? what goes here ?">' +
'<div id="poll-options">' +
'</div>' +
'<input type="submit" value="Submit your vote">' +
'</form>'
),
itemView: PollOptionItemView,
appendHtml: function (compositeView, itemView, index) {
var childrenContainer = $(compositeView.$("#poll-options") || compositeView.el);
var children = childrenContainer.children();
if (children.size() === index) {
childrenContainer.append(itemView.el);
} else {
childrenContainer.children().eq(index).before(itemView.el);
}
}
});
MORE DETAILS:
My goal really is to build poll questions dynamically, meaning the questions and options are not known at runtime but rather are queried from a SQL database thereafter. If you were looking at my app I'd launch a poll on your screen via SignalR. In essence I'm telling your browser "hey, go get the contents of poll question #1 from the database and display them". My thought was that CompositeViews are best suited for this because they are data driven. The questions and corresponding options could be stored models and collections the CompositeView template could render them dynamically on demand. I have most of this wired and it looks good. My only issue seems to be the notion of what kind of template to render. A form? Or should my template just plop some radio buttons on the screen with a submit button below it and I write some javascript to try to determine what selection the user made? I'd like not to use a form at all and just use the backbone framework to handle the submission. That seems clean to me but perhaps not possible or wise? Not sure yet.
I'd use the following approach:
Create a collection of your survey questions
Create special itemviews for each type of question
In your CompositeView, choose the model itemView based on its type
Use a simple validation to see if all questions have been answered
Output an array of all questions and their results.
For an example implementation, see this fiddle: http://jsfiddle.net/Cardiff/QRdhT/
Fullscreen: http://jsfiddle.net/Cardiff/QRdhT/embedded/result/
Note:
Try it without answering all questions to see the validation at work
Check your console on success to view the results
The code
// Define data
var surveyData = [{
id: 1,
type: 'multiplechoice',
question: 'What color do you like?',
options: ["Red", "Green", "Insanely blue", "Yellow?"],
result: null,
validationmsg: "Please choose a color."
}, {
id: 2,
type: 'openquestion',
question: 'What food do you like?',
options: null,
result: null,
validationmsg: "Please explain what food you like."
}, {
id: 3,
type: 'checkbox',
question: 'What movie genres do you prefer?',
options: ["Comedy", "Action", "Awesome", "Adventure", "1D"],
result: null,
validationmsg: "Please choose at least one movie genre."
}];
// Setup models
var questionModel = Backbone.Model.extend({
defaults: {
type: null,
question: "",
options: null,
result: null,
validationmsg: "Please fill in this question."
},
validate: function () {
// Check if a result has been set, if not, invalidate
if (!this.get('result')) {
return false;
}
return true;
}
});
// Setup collection
var surveyCollection = Backbone.Collection.extend({
model: questionModel
});
var surveyCollectionInstance = new surveyCollection(surveyData);
console.log(surveyCollectionInstance);
// Define the ItemViews
/// Base itemView
var baseSurveyItemView = Marionette.ItemView.extend({
ui: {
warningmsg: '.warningmsg',
panel: '.panel'
},
events: {
'change': 'storeResult'
},
modelEvents: {
'showInvalidMessage': 'showInvalidMessage',
'hideInvalidMessage': 'hideInvalidMessage'
},
showInvalidMessage: function() {
// Show message
this.ui.warningmsg.show();
// Add warning class
this.ui.panel.addClass('panel-warningborder');
},
hideInvalidMessage: function() {
// Hide message
this.ui.warningmsg.hide();
// Remove warning class
this.ui.panel.removeClass('panel-warningborder');
}
});
/// Specific views
var multipleChoiceItemView = baseSurveyItemView.extend({
template: "#view-multiplechoice",
storeResult: function() {
var value = this.$el.find("input[type='radio']:checked").val();
this.model.set('result', value);
}
});
var openQuestionItemView = baseSurveyItemView.extend({
template: "#view-openquestion",
storeResult: function() {
var value = this.$el.find("textarea").val();
this.model.set('result', value);
}
});
var checkBoxItemView = baseSurveyItemView.extend({
template: "#view-checkbox",
storeResult: function() {
var value = $("input[type='checkbox']:checked").map(function(){
return $(this).val();
}).get();
this.model.set('result', (_.isEmpty(value)) ? null : value);
}
});
// Define a CompositeView
var surveyCompositeView = Marionette.CompositeView.extend({
template: "#survey",
ui: {
submitbutton: '.btn-primary'
},
events: {
'click #ui.submitbutton': 'submitSurvey'
},
itemViewContainer: ".questions",
itemViews: {
multiplechoice: multipleChoiceItemView,
openquestion: openQuestionItemView,
checkbox: checkBoxItemView
},
getItemView: function (item) {
// Get the view key for this item
var viewId = item.get('type');
// Get all defined views for this CompositeView
var itemViewObject = Marionette.getOption(this, "itemViews");
// Get correct view using given key
var itemView = itemViewObject[viewId];
if (!itemView) {
throwError("An `itemView` must be specified", "NoItemViewError");
}
return itemView;
},
submitSurvey: function() {
// Check if there are errors
var hasErrors = false;
_.each(this.collection.models, function(m) {
// Validate model
var modelValid = m.validate();
// If it's invalid, trigger event on model
if (!modelValid) {
m.trigger('showInvalidMessage');
hasErrors = true;
}
else {
m.trigger('hideInvalidMessage');
}
});
// Check to see if it has errors, if so, raise message, otherwise output.
if (hasErrors) {
alert('You haven\'t answered all questions yet, please check.');
}
else {
// No errors, parse results and log to console
var surveyResult = _.map(this.collection.models, function(m) {
return {
id: m.get('id'),
result: m.get('result')
}
});
// Log to console
alert('Success! Check your console for the results');
console.log(surveyResult);
// Close the survey view
rm.get('container').close();
}
}
});
// Create a region
var rm = new Marionette.RegionManager();
rm.addRegion("container", "#container");
// Create instance of composite view
var movieCompViewInstance = new surveyCompositeView({
collection: surveyCollectionInstance
});
// Show the survey
rm.get('container').show(movieCompViewInstance);
Templates
<script type="text/html" id="survey">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" > A cool survey regarding your life </h3>
</div>
<div class="panel-body">
<div class="questions"></div>
<div class="submitbutton">
<button type="button" class="btn btn-primary">Submit survey!</button>
</div>
</div>
</div >
</script>
<script type="text/template" id="view-multiplechoice">
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="panel-title" > <%= question %> </h4>
</div>
<div class="panel-body">
<div class="warningmsg"><%= validationmsg %></div>
<% _.each( options, function( option, index ){ %>
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="<%= index %>" value="<%= option %>"> <%= option %>
</label>
</div>
<% }); %>
</div>
</div>
</script>
<script type="text/template" id="view-openquestion">
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="panel-title" > <%= question %> </h4>
</div>
<div class="panel-body">
<div class="warningmsg"><%= validationmsg %></div>
<textarea class="form-control" rows="3"></textarea>
</div>
</div >
</script>
<script type="text/template" id="view-checkbox">
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="panel-title" > <%= question %> </h4>
</div>
<div class="panel-body">
<div class="warningmsg"><%= validationmsg %></div>
<% _.each( options, function( option, index ){ %>
<div class="checkbox">
<label>
<input type="checkbox" value="<%= option %>"> <%= option %>
</label>
</div>
<% }); %>
</div>
</div>
</script>
<div id="container"></div>
Update: Added handlebars example
Jsfiddle using handlebars: http://jsfiddle.net/Cardiff/YrEP8/