I am new to AngularJS1 and Js. Here i am uploading a file which will be saved on my drive as well as in mongodb. What I am trying to do is to get the uploaded file name which can easily be seen here in attached picture. Kindly help me out with this.
$scope.uploadedFileList.push(p);
$('#addproFile').ajaxfileupload({
action: 'http://' + window.location.hostname + ':' + window.location.port + '/api/upload',
valid_extensions : ['md','csv','css', 'txt'],
params: {
dummy_name: p
},
onComplete: function(response) {
console.log('custom handler for file:');
alert(JSON.stringify(response));
/* $scope.nameString = uploadedFileList.join(',');
$scope.$apply();*/
},
onCancel: function() {
console.log('no file selected');
}
});
This is my controller
(function($) {
$.fn.ajaxfileupload = function(options) {
var settings = {
params: {},
action: '',
onStart: function() { },
onComplete: function(response) { },
onCancel: function() { },
validate_extensions : true,
valid_extensions : ['gif','png','jpg','jpeg'],
submit_button : null
};
var uploading_file = false;
if ( options ) {
$.extend( settings, options );
}
// 'this' is a jQuery collection of one or more (hopefully)
// file elements, but doesn't check for this yet
return this.each(function() {
var $element = $(this);
// Skip elements that are already setup. May replace this
// with uninit() later, to allow updating that settings
if($element.data('ajaxUploader-setup') === true) return;
$element.change(function()
{
// since a new image was selected, reset the marker
uploading_file = false;
// only update the file from here if we haven't assigned a submit button
if (settings.submit_button == null)
{
upload_file();
}
});
if (settings.submit_button == null)
{
// do nothing
} else
{
settings.submit_button.click(function(e)
{
// Prevent non-AJAXy submit
e.preventDefault();
// only attempt to upload file if we're not uploading
if (!uploading_file)
{
upload_file();
}
});
}
var upload_file = function()
{
if($element.val() == '') return settings.onCancel.apply($element, [settings.params]);
// make sure extension is valid
var ext = $element.val().split('.').pop().toLowerCase();
if(true == settings.validate_extensions && $.inArray(ext, settings.valid_extensions) == -1)
{
// Pass back to the user
settings.onComplete.apply($element, [{status: false, message: 'The select file type is invalid. File must be ' + settings.valid_extensions.join(', ') + '.'}, settings.params]);
} else
{
uploading_file = true;
// Creates the form, extra inputs and iframe used to
// submit / upload the file
wrapElement($element);
// Call user-supplied (or default) onStart(), setting
// it's this context to the file DOM element
var ret = settings.onStart.apply($element, [settings.params]);
// let onStart have the option to cancel the upload
if(ret !== false)
{
$element.parent('form').submit(function(e) { e.stopPropagation(); }).submit();
} else {
uploading_file = false;
}
}
};
// Mark this element as setup
$element.data('ajaxUploader-setup', true);
/*
// Internal handler that tries to parse the response
// and clean up after ourselves.
*/
var handleResponse = function(loadedFrame, element) {
var response, responseStr = $(loadedFrame).contents().text();
try {
//response = $.parseJSON($.trim(responseStr));
response = JSON.parse(responseStr);
} catch(e) {
response = responseStr;
}
// Tear-down the wrapper form
element.siblings().remove();
element.unwrap();
uploading_file = false;
// Pass back to the user
settings.onComplete.apply(element, [response, settings.params]);
};
/*
// Wraps element in a <form> tag, and inserts hidden inputs for each
// key:value pair in settings.params so they can be sent along with
// the upload. Then, creates an iframe that the whole thing is
// uploaded through.
*/
var wrapElement = function(element) {
// Create an iframe to submit through, using a semi-unique ID
var frame_id = 'ajaxUploader-iframe-' + Math.round(new Date().getTime() / 1000)
$('body').after('<iframe width="0" height="0" style="display:none;" name="'+frame_id+'" id="'+frame_id+'"/>');
$('#'+frame_id).get(0).onload = function() {
handleResponse(this, element);
};
// Wrap it in a form
element.wrap(function() {
return '<form action="' + settings.action + '" method="POST" enctype="multipart/form-data" target="'+frame_id+'" />'
})
// Insert <input type='hidden'>'s for each param
.before(function() {
var key, html = '';
for(key in settings.params) {
var paramVal = settings.params[key];
if (typeof paramVal === 'function') {
paramVal = paramVal();
}
html += '<input type="hidden" name="' + key + '" value="' + paramVal + '" />';
}
return html;
});
}
});
}
})( jQuery )
this is my ajax file upload function
I have strange issue showed up recently on my script and not sure what causes this issue to happen. It is popping up on Chrome browser mainly and I guess this function 'offsetHeight' is either deprecated or invalid.
here is the full code:
var Rep_Templates = {
// array of pre-defined reasons
answers: null,
// popup container
context_menu: null,
// popup copntiner height
menu_height: 0,
error_msg: null,
// ajax form and its param values
pseudoform: null,
url: null,
postid: 0,
// information phrases to display to user
thanks_phrase: '',
description_msg: '',
timer_id: null,
/**
* inits the popup
* #param answers array of pre-defined reasons
* #param error_msg to display in case of empty message
* #param url of current page
* #param thanks_phrase diaplyed after successful submission
*/
init: function(answers, url, phrases) {
if (AJAX_Compatible)
{
this.answers = answers;
this.error_msg = phrases['error'];
this.thanks_phrase = phrases['thanks'];
this.description_msg = phrases['description'];
this.context_menu = new YAHOO.widget.Menu("rep_tmpl_popup",
{clicktohide: false,
effect: {
effect: YAHOO.widget.ContainerEffect.FADE,
duration: 0.25
}});
// Fix for IE7 z-index bug
if (YAHOO.env.ua.ie && YAHOO.env.ua.ie < 8)
{
this.context_menu.cfg.setProperty("position", "dynamic");
this.context_menu.cfg.setProperty("iframe", true);
this.context_menu.cfg.setProperty("zindex", 10100);
}
this.context_menu.render(document.body);
var menu_object = fetch_object("rep_tmpl_menu_inner");
this.menu_height = menu_object.offsetHeight;
var links = YAHOO.util.Dom.getElementsByClassName("report", "a", document.body);
for ( var i = 0; i < links .length; i++ ) {
var index = links[i].href.indexOf("p=");
if (index > 0)
{
var postid = links[i].href.substr(index+2);
YAHOO.util.Event.on(links[i], "click", this.show_popup, postid);
}
}
this.pseudoform = new vB_Hidden_Form('ajax.php');
this.pseudoform.add_variable('ajax', 1);
this.pseudoform.add_variable('s', fetch_sessionhash());
this.pseudoform.add_variable('securitytoken', SECURITYTOKEN);
this.pseudoform.add_variable('do', 'email_report');
this.url = url;
}
},
/**
* inserts pre-defined reason into textarea
* #param id of selected reason
*/
set_answer: function(id) {
var textarea = fetch_object('rep_tmpl_message');
textarea.value = '';
if (id > 0 && id <= this.answers.length)
{
textarea.value = this.answers[id-1];
var error_msg = fetch_object('rep_tmpl_error');
error_msg.innerHTML = "";
}
},
/**
* show popup to the user
* #param event click event
* #param postid id of the post
*/
show_popup: function(event,postid) {
Rep_Templates.reset_data();
YAHOO.util.Event.stopEvent(event);
var elem = event.srcElement? event.srcElement : event.target;
Rep_Templates.postid = postid;
var xy = [0,0];
xy[0] = YAHOO.util.Dom.getX(elem) + 25;
xy[1] = YAHOO.util.Dom.getY(elem) - Rep_Templates.menu_height;
if (xy[1] < 0)
{
xy[1] = 0;
}
Rep_Templates.context_menu.moveTo(xy[0],xy[1]);
Rep_Templates.context_menu.show();
fetch_object('rep_tmpl_message').focus();
YAHOO.util.Event.on(document.body, "click", Rep_Templates.hide_menu);
},
/**
* hides the menu when users click Hide button or click outside of the popup. Resets data
* #param optional event. If specified, then user clicked outside.
*/
hide_menu: function(event) {
var is_inside = false;
if (event)
{
// check if click was inside or outside popup
var obj = event.srcElement? event.srcElement : event.target;
do {
if (obj.id == 'rep_tmpl_popup') {
is_inside = true;
break;
}
} while (obj = obj.parentNode);
if (!is_inside)
{
YAHOO.util.Event.removeListener(document.body, "click", Rep_Templates.hide_menu);
}
}
if (!event || !is_inside)
{
Rep_Templates.context_menu.hide();
Rep_Templates.postid = 0;
}
},
/**
* reset all fields with default values
*/
reset_data: function() {
var error_msg = fetch_object('rep_tmpl_error');
error_msg.innerHTML = "";
var phrase = fetch_object('rep_tmpl_phrase');
phrase.innerHTML = this.description_msg;
YAHOO.util.Dom.removeClass(phrase, 'rep_tmpl_thanks_message');
var button = fetch_object('rep_tmpl_submit');
YAHOO.util.Dom.removeClass(button, 'disabled');
button.disabled = false;
var image = fetch_object('rep_tmpl_progress');
image.style.display = 'none';
},
/**
* sends AJAX request
* #param event click event
*/
send_data: function(event) {
var textarea = fetch_object('rep_tmpl_message');
if (textarea && textarea.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') != '')
{
this.pseudoform.add_variable('postid', this.postid);
this.pseudoform.add_variable('url',this.url + "&p="+ this.postid + "#post" + this.postid);
var button = event.srcElement? event.srcElement : event.target;
button.disabled = true;
YAHOO.util.Dom.addClass(button, 'disabled');
var image = fetch_object('rep_tmpl_progress');
image.style.display = '';
YAHOO.util.Connect.asyncRequest("POST", 'ajax.php', {
success: this.handle_ajax_response,
failure: vBulletin_AJAX_Error_Handler,
timeout: vB_Default_Timeout,
scope: this
}, this.pseudoform.build_query_string() + '&reason=' + textarea.value);
}
else
{
var error_msg = fetch_object('rep_tmpl_error');
error_msg.innerHTML = this.error_msg;
}
return false;
},
/**
* handles AJAX request
* #param ajax data returned
*/
handle_ajax_response: function(ajax) {
if (ajax.responseXML)
{
// check for error first
var error = ajax.responseXML.getElementsByTagName('error');
if (error.length)
{
this.reset_data();
var error_msg = fetch_object('rep_tmpl_error');
error_msg.innerHTML = error[0].firstChild.nodeValue;
}
else
{
var result = ajax.responseXML.getElementsByTagName('result');
if (result.length)
{
var image = fetch_object('rep_tmpl_progress');
image.style.display = 'none';
var phrase = fetch_object('rep_tmpl_phrase');
phrase.innerHTML = this.thanks_phrase;
YAHOO.util.Dom.addClass(phrase, 'rep_tmpl_thanks_message');
this.timer_id = setTimeout('Rep_Templates.handle_timer_expiration()',1000);
}
}
}
},
/**
* hides popup on timer expiration
*/
handle_timer_expiration: function() {
clearTimeout(this.timer_id);
this.hide_menu();
}
}
any idea how to solve this issue!!
Thanks
Your problem is that the object menu_object is null. My guess is that the element that you are looking for does not exist. Check out your element and make sure that it has the correct identifier (class or id) to match fetch_object("rep_tmpl_menu_inner")
Ok i have site with old version of jquery, then i imported modul, where i have newer version of jquery, in my modul page i have this line of jquery
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
Somehow i have conflict. I cant remove old version from header cuz some function dont work, in the other side in my module page if i remove newer version spinner function dont work. I cant use both jquery versions in same time. is there some way how to resolve this conflict.
Code where i have error is: In this script i need older version not before loaded new version jquery-1.10.2.js
var notice = new Array();
$(document).ready( function() {
/*setTimeout(function(){ $(".notice").fadeTo('slow',1), 500; });
setTimeout(function(){ $(".notice").fadeTo('slow',0.4); }, 1500);*/
/*setTimeout(function(){
$(".notice").animate( { backgroundColor: '#B8B8B8' }, 1000)
});*/
setTimeout(function(){
$(".notice").animate( { backgroundColor: '#e0e0e0' }, 1000)
});
$.safetynet({
message : isDirtyWarning
});
});
/**
* Funkcija ce Sve vrednosti Combo Boksa upisati u hidden polje razdvojeno
* zarezom
*
* #param hidden_field_id
* #return
*/
function ComboFieldsToValue(combo_selector, hidden_field_id) {
var vrednosti = "";
$(combo_selector + ' option').each( function() {
vrednosti += $(this).val() + ',';
});
$(hidden_field_id).attr( {
value :vrednosti.substring(0, vrednosti.length - 1)
});
// alert($(hidden_field_id).attr("value"));
}
/**
* Proverava da li Combo ima item sa zadatom vrednoscu
* Vraca true ako ima, false ako nema
* #param combo_selector
* #param key
* #return
*/
function IsItemInCombo(combo_selector, key) {
var is_in_combo = false;
$(combo_selector + ' option').each( function() {
if ($(this).val() == key) {
is_in_combo = true;
}
});
return is_in_combo;
}
/**
* Potrda brisanja
* #param link
* #return
*/
function PotvrdiBrisanje(link, str) {
if(str == "") str = "Potvrdi brisanje?";
if (confirm("" + str)) {
document.location = link;
}
}
function ajaxPotvrdiBrisanje(link, str, autoconfirm, flexi_id) {
if(str == "") str = "Potvrdi brisanje?";
if(autoconfirm == "") autoconfirm = false;
if(flexi_id == "" || !flexi_id) flexi_id = 'flex1';
if (autoconfirm || confirm("" + str)) {
$.ajax({
url: link,
async : false,
success: function(data) {
if (data.substr(0, 4) == "msg:") {
notice[notice.length] = data.substr(4,data.length);
}
}
});
}
return false;
}
function addToNotice(data)
{
if (data.substr(0, 4) == "msg:") {
notice[notice.length] = data.substr(4,data.length);
}
}
function PrikaziNotice() {
if (notice.length == 0) return;
$('p.flexy_notice').html('');
$('p.flexy_notice').css({ backgroundColor: '#FB2D2B' });
$('p.flexy_notice').hide('');
/*
* Uknjamoi osmnovni notce
*
*/
if ($('.notice').length != 0) {
$('.notice').hide();
}
html = "";
for ( var i in notice ) {
html += '<p>' + notice[i] + '</p>';
}
$('p.flexy_notice').html(html);
$('p.flexy_notice').show();
$(".flexy_notice").animate( { backgroundColor: '#e0e0e0' }, 1000);
notice = new Array();
}
function reloadFlexi() { $("#flex1").flexReload(); }
function ShowAudit(id) {
$(".audit_" + id).toggle();
}
function setDirtyTiny(){
$.safetynet.raiseChange($('textarea'));
}
Can someone explain me how to adjust this js file
If you need to run two versions of jquery, you can use noconflict.
Example:
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script>
newJquery = jQuery.noConflict(true);
newJquery(document).ready( function() {
...
...
Here is a blog dealing with this problem:
http://blog.nemikor.com/2009/10/03/using-multiple-versions-of-jquery/
Just add this to your html page in which the conflict occurs:
<script>
$.noConflict();
</script>
Ok, so backstory is we have a bunch of identical (in function) forms on a page to add variants to a product,
The form consists of three major parts.
The Attribute Editor
This component allows the user to add attributes to a product.
Each attribute has a visibility status, an attribute key, an attribute value and a delete button which together form one row.
The component also has an Add Attribute button, which when clicked adds a new row to the bottom of the list.
Each attribute key select list has a new attribute option, which upon selecting launches a modal dialog with a form to enter the new attribute name, this form then submits via AJAX and returns an ID, the new option is then appended to every attribute key select on the page to allow it to be selected.
When a key is selected in an instance of the component all other attribute key select's in the group get that option disabled to prevent duplicate attributes.
The attribute editor gets submitted as part of the main form below.
The Main Form
This component consists of the general description fields of the variant.
The form is submitted via AJAX and has the jQuery Validation Engine attached for form validation.
Because we are adding new input's dynamically with the attribute editor we must constantly detach, and re-attach the validation engine.
The Alert System
This component handles displaying/hiding the error/success/status messages on form by form basis.
The Issue
Now there are also a couple of forms that are very similar, but are slight variantions on a couple of the event handlers, so I wanted to create the code so I could replace bits and pieces of it at will without having to copy the entire code.
So after following the tips from this question I ended up with the code below, but I am getting the error: Uncaught TypeError: object is not a function which is on this line: var variantAlert = new VariantAlert(form); which I believe is because I am not returning anything, but I don't know what I should return to get the code to do what I want!
Short Version
$(function () {
$("form.variant-form").each(function (i, form) {
var variantAlert = new VariantAlert(form);
var variantForm = new VariantForm(form, variantAlert);
variantForm.init();
var attributeEditor = new AttributeEditor(form, variantForm);
attributeEditor.init();
});
});
var AttributeEditor = (function (form, formSetup) {
form = $('form');
var someVar = 123;
var init = function () {
someEventHandler();
};
var someEventHandler = function () {
$('.selector', form).on('some event', function (e) {
form.css('background-color', '#f00');
});
};
return AttributeEditor;
})();
var VariantForm = (function (form, variantAlert) {
form = $('form');
var init = function () {
anotherEventHandler();
};
var anotherEventHandler = function () {
$('.anotherSelector', form).on('another event', function () {
form.doStuff();
});
};
})();
var VariantAlert = (function (form) {
var timer;
form = $('form');
var message = function (type, message) {
doMoreStuff(type, message);
}
})();
Full Version
$(function () {
/*********************************
* Loop over each variant and setup
* the attribute editor and form
*********************************/
$("form.variant-form").each(function (i, form) {
var variantAlert = new VariantAlert(form);
var variantForm = new VariantForm(form, variantAlert);
variantForm.init();
var attributeEditor = new AttributeEditor(form, variantForm);
attributeEditor.init();
});
});
var AttributeEditor = (function (form, formSetup) {
/*********************************
* Variables
*********************************/
form = $('form');
var template = $('.variant_demo_row', form);
var attributes = $('.variant_select', form).length;
var modal = form.siblings('.newAttribute').appendTo('body');
var manualHide = false;
var triggerSelect = null;
var oldOption = null;
var init = function () {
//setup the handlers
//doing it this way allows us to overwrite the individual handlers with ease
addNewAttributeHandler();
removeAttributeHandler();
selectFocusHandler();
selectChangeHandler();
attributeVisibilityHandler();
modalFormSubmissionHandler();
modalShowHandler();
modalCancelClickHandler();
};
/*********************************
* Add new attribute button handler
*********************************/
var addNewAttributeHandler = function () {
$('.variant_attribute_add_new a', form).on('click keypress', function (e) {
form.css('background-color', '#f00');
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
//clone the template row so we can edit it
var newRow = template.clone().css('display', 'none').removeClass('hidden variant_demo_row').addClass('variant_row');
//give each element in the clone it's unique name
$('.variant_select', newRow).prop('name', 'attribute_key_' + attributes);
$('.variant_input', newRow).prop('name', 'attribute_value_' + attributes);
$('.variant_visible', newRow).prop('name', 'attribute_visible_' + attributes);
//insert the new attribute row at the bottom of the attributes
newRow.insertBefore($('.variant_attribute_add_new', form)).show('fast', function () {
$('select', newRow).focus();
});
//we have added new nodes so we need to reset the validationEngine
form.validationEngine('detach');
formSetup.init();
attributes++;
});
};
/*********************************
* Remove attribute button handler
*********************************/
var removeAttributeHandler = function () {
form.on('click keypress', '.removeAttribute', {}, function (e) {
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
attributes--;
var val = $(this).siblings('select').val();
//re-enable whatever attribute key was in use
if (val != "") {
$('.variant_select option[value=' + val + ']', form).removeAttr('disabled');
}
//animate the removal of the attribute
$(this).closest('.controls-row').hide('fast', function () {
$(this).remove();
});
});
};
/*********************************
* Attribute key select focus handler
*********************************/
var selectFocusHandler = function () {
form.on('focus', '.variant_select', {}, function () {
//store the old option so we know what option to
//re-enable if a change is made
oldOption = $('option:selected', this).val();
});
};
/*********************************
* Attribute key select change handler
*********************************/
var selectChangeHandler = function () {
form.on('change', '.variant_select', {}, function () {
var select = $(this);
//empty class is used for "placeholder" simulation
select.removeClass('empty');
//re-enable whatever option was previously selected
if (oldOption !== null) {
$('.variant_select option[value=' + oldOption + ']', form).removeAttr('disabled');
}
if ($('option:selected', select).hasClass('newAttribute')) { //Add new attribute selected
triggerSelect = select;
modal.modal('show');
} else if ($('option:selected', select).val() == "") { //Placeholder selected
select.addClass('empty');
} else { //Value selected
//disable the selected value in other attribute key selects
$('.variant_select', form).not(select).children('option[value=' + select.val() + ']').prop('disabled', 'disabled');
}
oldOption = select.val();
});
};
/*********************************
* Toggle visibility button handler
*********************************/
var attributeVisibilityHandler = function () {
form.on('click', '.toggleVisibility', {}, function () {
//the titles of the button
var hidden = 'Hidden Attribute';
var visible = 'Visible Attribute';
var btn = $(this);
var icon = btn.children('i');
var box = btn.siblings('.variant_visible');
//toggle the state between visible and hidden
btn.toggleClass('btn-success btn-warning').attr('title', btn.attr('title') == hidden ? visible : hidden);
icon.toggleClass('icon-eye-open icon-eye-close');
box.prop("checked", !box.prop("checked"))
});
};
/*********************************
* New attribute submission handler
*********************************/
var modalFormSubmissionHandler = function () {
$('.newAttributeForm', modal).validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status) {
var text = $('.newAttributeName', modal).val();
$('.newAttributeName', modal).val('');
form.spin();
$.ajax({
type:'POST',
url:'/cfox/cart/variants/addattribute',
data:{name:text},
success:function (data) {
//add new attribute key to attribute key selects everywhere
$('.variant_select').append($('<option>', { value:data.id}).text(data.name));
//set the triggering selects value to the new key
triggerSelect.val(data.id);
triggerSelect.trigger('change');
manualHide = true;
modal.modal('hide');
triggerSelect.siblings('input').focus();
form.spin(false);
},
dataType:'JSON'
});
}
}});
};
var modalCancelClickHandler = function () {
$('.btn-danger', modal).on('click', function () {
if (!manualHide) {
triggerSelect[0].selectedIndex = 1;
triggerSelect.trigger('change');
}
manualHide = false;
});
};
var modalShowHandler = function () {
modal.on('show shown', function () {
$('.newAttributeName', modal).focus();
});
}
return AttributeEditor;
})();
var VariantForm = (function (form, variantAlert) {
/*********************************
* Variables
*********************************/
form = $('form');
var init = function () {
nameChangeHandler();
submitHandler();
};
/*********************************
* Variant name change handler
* Changes the heading on the accordion if the
* name form input changes
*********************************/
var nameChangeHandler = function () {
var accordion_heading = form.closest('.accordion-body').siblings('.accordion-heading').find('.accordion-toggle');
$('.name-input', form).on('change', function () {
accordion_heading.text($(this).val());
});
};
/*********************************
* Form submit handler
*********************************/
var submitHandler = function () {
form.validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status == true) {
$.ajax({
type:'POST',
url:form.attr('action'),
data:form.serialize(),
dataType:'json',
beforeSend:function () {
cfox.disableForm(form);
form.spin();
form.children('.variant_status_message').hide('fast');
},
success:function (response) {
cfox.enableForm(form);//need to do this here so browser doesn't cache disabled fields
if (typeof response != "object" || response === null) {
variantAlert.message('failed');
} else {
switch (response.status) {
case 0:
variantAlert.message('errors', response.errors);
break;
case 1:
variantAlert.message('success');
break;
default:
variantAlert.message('failed');
break;
}
}
form.spin(false);
},
error:function () {
variantAlert.message('failed');
form.spin(false);
cfox.enableForm(form);
}
});
}
}
});
}
})();
var VariantAlert = (function (form) {
/*********************************
* Variables
*********************************/
var timer;
form = $('form');
/*********************************
* handles showing/hiding any messages
* in the variant forms
*********************************/
var message = function (type, message) {
var alert;
clearTimeout(timer);
$('.variant_status_message', form).hide('fast');
if (type == 'success') {
alert = $('.variant_status_message.success', form);
} else if (type == 'errors') {
alert = $('.variant_status_message.errors', form);
$('.alert-message', alert).html(message);
} else if (type == 'failed') {
alert = $('.variant_status_message.failed', form);
}
alert.show('fast', function () {
$('html, body').animate({
scrollTop:alert.closest('.accordion-group').offset().top
}, 150, 'linear');
timer = setTimeout(function () {
alert.hide('fast')
}, 5000);
});
}
})();
Yours variantAlert uses like
variantAlert.message('failed');
That means constructor must return object containing message function
var VariantAlert = function (form) {
var timer;
/*********************************
* handles showing/hiding any messages
* in the variant forms
*********************************/
var message = function (type, message) {
var alert;
clearTimeout(timer);
$('.variant_status_message', form).hide('fast');
if (type == 'success') {
alert = $('.variant_status_message.success', form);
} else if (type == 'errors') {
alert = $('.variant_status_message.errors', form);
$('.alert-message', alert).html(message);
} else if (type == 'failed') {
alert = $('.variant_status_message.failed', form);
}
alert.show('fast', function () {
$('html, body').animate({
scrollTop:alert.closest('.accordion-group').offset().top
}, 150, 'linear');
timer = setTimeout(function () {
alert.hide('fast')
}, 5000);
});
}
return {
message: message
};
}
Finally got it to work using a different method, my code is below for anyone to compare and for reference.
$(function () {
/*********************************
* Loop over each variant and setup
* the attribute editor and form
*********************************/
var editors = [];
$("form.variant-form").each(function (i, form) {
var variantEditor = new VariantEditor(form);
editors.push(variantEditor);
variantEditor.attributeEditor.init();
variantEditor.form.init();
});
});
var VariantEditor = function (form) {
var that = this;
that.formElement = $(form);
/*********************************
* Sets up the attribute editor
*********************************/
that.attributeEditor = {
/*********************************
* Variables
*********************************/
template:null,
attribute:null,
modal:null,
manualHide:false,
triggerSelect:null,
oldOption:null,
/*********************************
* Sets up the attribute editor
*********************************/
init:function () {
var that = this;
//The Template row
that.template = $('.variant_demo_row', that.formElement);
//How many attributes are pre-loaded
that.attributes = $('.variant_select', that.formElement).length;
//Append the attribute editor modal to the body to avoid style corruption
that.modal = that.formElement.siblings('.newAttribute').appendTo('body');
//setup the handlers
//doing it this way allows us to overwrite the individual handlers with ease
that.addNewAttributeHandler();
that.removeAttributeHandler();
that.selectFocusHandler();
that.selectChangeHandler();
that.attributeVisibilityHandler();
that.modalFormSubmissionHandler();
that.modalShowHandler();
that.modalCancelClickHandler();
$('.variant_select', that.formElement).each(function (i, select) {
that.oldOption = null;
$(select).change();
});
},
/*********************************
* Add new attribute button handler
*********************************/
addNewAttributeHandler:function () {
var that = this;
$('.variant_attribute_add_new a', that.formElement).on('click keypress', function (e) {
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
//clone the template row so we can edit it
var newRow = that.template.clone().css('display', 'none').removeClass('hidden variant_demo_row').addClass('variant_row');
//give each element in the clone it's unique name
$('.variant_select', newRow).prop('name', 'attribute_key_' + that.attributes);
$('.variant_input', newRow).prop('name', 'attribute_value_' + that.attributes);
$('.variant_visible', newRow).prop('name', 'attribute_visible_' + that.attributes);
//insert the new attribute row at the bottom of the attributes
newRow.insertBefore($('.variant_attribute_add_new', that.formElement)).show('fast', function () {
$('select', newRow).focus();
});
//we have added new nodes so we need to reset the validationEngine
that.formElement.validationEngine('detach');
that.form.init();
that.attributes++;
});
},
/*********************************
* Remove attribute button handler
*********************************/
removeAttributeHandler:function () {
var that = this;
that.formElement.on('click keypress', '.removeAttribute', {}, function (e) {
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
that.attributes--;
var val = $(this).siblings('select').val();
//re-enable whatever attribute key was in use
if (val != "") {
$('.variant_select option[value=' + val + ']', that.formElement).removeAttr('disabled');
}
//animate the removal of the attribute
$(this).closest('.controls-row').hide('fast', function () {
$(this).remove();
});
});
},
/*********************************
* Attribute key select focus handler
*********************************/
selectFocusHandler:function () {
var that = this;
that.formElement.on('focus', '.variant_select', {}, function () {
//store the old option so we know what option to
//re-enable if a change is made
that.oldOption = $('option:selected', this).val();
});
},
/*********************************
* Attribute key select change handler
*********************************/
selectChangeHandler:function () {
var that = this;
that.formElement.on('change', '.variant_select', {}, function () {
var select = $(this);
//empty class is used for "placeholder" simulation
select.removeClass('empty');
//re-enable whatever option was previously selected
if (that.oldOption !== null) {
$('.variant_select option[value=' + that.oldOption + ']', that.formElement).removeAttr('disabled');
}
if ($('option:selected', select).hasClass('newAttribute')) { //Add new attribute selected
that.triggerSelect = select;
that.modal.modal('show');
} else if ($('option:selected', select).val() == "") { //Placeholder selected
select.addClass('empty');
} else { //Value selected
//disable the selected value in other attribute key selects
$('.variant_select', that.formElement).not(select).children('option[value=' + select.val() + ']').prop('disabled', 'disabled');
}
that.oldOption = select.val();
});
},
/*********************************
* Toggle visibility button handler
*********************************/
attributeVisibilityHandler:function () {
var that = this;
that.formElement.on('click', '.toggleVisibility', {}, function () {
//the titles of the button
var hidden = 'Hidden Attribute';
var visible = 'Visible Attribute';
var btn = $(this);
var icon = btn.children('i');
var box = btn.siblings('.variant_visible');
//toggle the state between visible and hidden
btn.toggleClass('btn-success btn-warning').attr('title', btn.attr('title') == hidden ? visible : hidden);
icon.toggleClass('icon-eye-open icon-eye-close');
box.prop("checked", !box.prop("checked"))
});
},
/*********************************
* New attribute submission handler
*********************************/
modalFormSubmissionHandler:function () {
var that = this;
$('.newAttributeForm', that.modal).validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status) {
var text = $('.newAttributeName', that.modal).val();
$('.newAttributeName', that.modal).val('');
form.spin();
$.ajax({
type:'POST',
url:'/cfox/cart/variants/addattribute',
data:{name:text},
success:function (data) {
//add new attribute key to attribute key selects everywhere
$('.variant_select').append($('<option>', { value:data.id}).text(data.name));
//set the triggering selects value to the new key
that.triggerSelect.val(data.id);
that.triggerSelect.trigger('change');
that.manualHide = true;
that.modal.modal('hide');
that.triggerSelect.siblings('input').focus();
form.spin(false);
},
dataType:'JSON'
});
}
}});
},
modalCancelClickHandler:function () {
var that = this;
$('.btn-danger', that.modal).on('click', function () {
if (!that.manualHide) {
that.triggerSelect[0].selectedIndex = 1;
that.triggerSelect.trigger('change');
}
that.manualHide = false;
});
},
modalShowHandler:function () {
var that = this;
that.modal.on('show shown', function () {
$('.newAttributeName', that.modal).focus();
});
}
};
/*********************************
* Sets up the variant main form
* The above function focuses on setting up the attribute editor
* This function sets up the rest of the form and handles the
* form submissions
*********************************/
that.form = {
init:function () {
var that = this;
that.nameChangeHandler();
that.submitHandler();
that.statusChangeHandler();
},
/*********************************
* Variant name change handler
* Changes the heading on the accordion if the
* name form input changes
*********************************/
nameChangeHandler:function () {
var that = this;
var accordion_heading = that.formElement.closest('.accordion-body').siblings('.accordion-heading').find('.accordion-toggle .name');
$('.name-input', that.formElement).on('change', function () {
accordion_heading.text($(this).val());
});
},
statusChangeHandler: function(){
var that = this;
console.log($('input[name=status]', that.formElement).parent());
$('input[name=status]', that.formElement).parent().on('click keypress', function(e){
//patched support for enter key
if (e.type === 'keypress' && e.which != 13) {
return true;
}
console.log('called');
var checked = $(this).prop('checked');
var label = that.formElement.closest('.accordion-body').siblings('.accordion-heading').find('.accordion-toggle .label');
label.text(checked ? 'Online' : 'Offline').toggleClass('label-important label-success');
});
},
/*********************************
* Form submit handler
*********************************/
submitHandler:function () {
var that = this;
that.formElement.validationEngine('attach', {
onValidationComplete:function (form, status) {
if (status == true) {
$.ajax({
type:'POST',
url:form.attr('action'),
data:form.serialize(),
dataType:'json',
beforeSend:function () {
cfox.disableForm(form);
form.spin();
form.children('.variant_status_message').hide('fast');
},
success:function (response) {
cfox.enableForm(form);//need to do this here so browser doesn't cache disabled fields
if (typeof response != "object" || response === null) {
that.message('failed');
} else {
switch (response.status) {
case 0:
that.message('errors', response.errors);
break;
case 1:
that.message('success');
break;
default:
that.message('failed');
break;
}
}
form.spin(false);
},
error:function () {
cfox.alert('alert-error', "An error was encountered when submitting this form. Please try again.");
form.spin(false);
cfox.enableForm(form);
}
});
}
}
});
}
};
/*********************************
* handles showing/hiding any messages
* in the variant forms
*********************************/
that.message = function (type, message) {
var that = this;
var alert;
clearTimeout(that.timer);
$('.variant_status_message', that.formElement).hide('fast');
if (type == 'success') {
alert = $('.variant_status_message.success', that.formElement);
} else if (type == 'errors') {
alert = $('.variant_status_message.errors', that.formElement);
$('.alert-message', alert).html(message);
} else if (type == 'failed') {
alert = $('.variant_status_message.failed', that.formElement);
}
alert.show('fast', function () {
$('html, body').animate({
scrollTop:alert.closest('.accordion-group').offset().top
}, 150, 'linear');
that.timer = setTimeout(function () {
alert.hide('fast')
}, 5000);
});
}
that.attributeEditor.formElement = that.formElement;
that.attributeEditor.form = that.form;
that.attributeEditor.message = that.message;
that.form.formElement = that.formElement;
that.form.attributeEditor = that.attributeEditor;
that.form.message = that.message;
that.message.formElement = that.formElement;
that.message.attributeEditor = that.attributeEditor;
that.message.form = that.form;
return that;
};
VariantEditor.prototype = {};
I have this code
$(document).ready(function (){
var Form_addTurbo = $('form#Form_addTurbo');
Form_addTurbo.submit(function (e){
e.preventDefault;
v = new Notification('Creating Turbo.', 'information', 'Working..', function(){return;});
$.post('/api/turbos/new.php', {
action : 'createNew'
}, function (r){
v.hide();
if(r.success){
new Notification('Turbo Create.', 'saved', '', function(){return;});
}else if(r.error){
}else{
new Notification('Something went wrong.', 'error', '', function(){return;});
}
}, 'json');
return false;
});
});
Which uses this api
$(document).ready(function(e) {$("body").prepend('<ul id="notifications"></ul>');});
/**
* Global notification system
*
* #param String Message to be displayed
* #param String Type of notification
*
* #author Bram Jetten
* #version 28-03-2011
*/
Notification.fn = Notification.prototype;
function Notification(value, type, tag, onclickfunc) {
this.log(value, type);
this.element = $('<li><span class="image '+ type +'"></span>' + value + '</li>');
if(typeof tag !== "undefined" && tag !== '') {
$(this.element).append('<span class="tag">' + tag + '</span>');
}
if(typeof onclickfunc == 'function'){
this.element.click(onclickfunc);
}
$("#notifications").append(this.element);
this.show();
}
/**
* Show notification
*/
Notification.fn.show = function() {
$(this.element).slideDown(200);
$(this.element).click(this.hide);
}
/**
* Hide notification
*/
Notification.fn.hide = function() {
$(this).animate({opacity: .01}, 200, function() {
$(this).slideUp(200, function() {
$(this).remove();
});
});
}
/**
* Log notification
*
* #param String Message to be logged
* #param String Type of notification
*/
Notification.fn.log = function(value, type) {
switch(type) {
case "information":
console.info("*** " + value + " ***");
break;
case "success":
console.log(value);
break;
case "warning":
console.warn(value);
break;
case "error":
console.error(value);
break;
case "saved":
console.log(value);
break;
default:
console.log(value);
break;
}
}
So what happens is that I try close the notification using the hide function that I believe it gives but I get this error.
Uncaught TypeError: Cannot read property 'defaultView' of undefined
I believe it doesn't know what "this" is but how would I be able to get this to work.
Made some minor changes to your example. Try it out http://jsfiddle.net/FLE39/
Had a closer look at your code and made a new jsfiddle. See updated link.