How to remove jQuery element added by .append()? - javascript

General info
I'm working on a intranet based administration system for a distribution centre.
Situation
Basicly I have a contenteditable table with all user data. Except for the passwords of course. You could compare it with a webbased Excel sheet. Using a jQuery UI dialog, I'm popping op a form that allows the admin (company manager) of the system to change the employees passwords if clicked on a button.To make sure the password change will be applied to the correct user, I'm passing along the used id to my function that pops up the dialog. Using .append() I'm adding this id to the form. Up to this point everything works perfectly fine.
Problem
If the password change is cancelled, the id must be removed from the form again. Otherwise you end up appending more and more ids to the form on each user clicked. The same goes for when the password change is succeeded. I've tried doing this with jQuery .remove(), but it doesn't seem to work, even though I can't find any issue with the code.
Code
function changePass(id){
var addID = $("<input>")
.attr("type", "text")
.attr("id", "userid")
.attr("name", "userid").val(id);
$('#passChangeForm').append($(addID));
$("#changePass").dialog({
modal: true,
resizable: false,
title: "Change password",
buttons: [
{
text: "Cancel",
click: function() {
$("#passChangeForm").remove("#userid");
$(this).dialog("close");
}
},
{
text: "Ok",
click: function() {
$("#passChangeForm").submit();
}
}
]
});
}
$("#passChangeForm").on("submit", function(e){
e.preventDefault();
var password = document.getElementById("chPass1").value;
var password2 = document.getElementById("chPass2").value;
var userid = document.getElementById("userid").value;
$.ajax({
url: "system/changepass.php",
type: "POST",
data:'pass1='+password+'&pass2='+password2+'&id='+userid,
success: function(text){
alert(text);
$("#passChangeForm").remove("#userid");
$("#changePass").dialog("close");
}
});
});

Simply use this :
$( "#userid" ).remove();

Change the line
$("#passChangeForm").remove("#userid");
to
$("#userid").remove();

Related

Display loading sweet alert dialog while waiting ajax finnish

I'm using https://sweetalert2.github.io/
I tried using one single sweet dialog, but due to the others I couldn't make it work, and i've seen examples with fetch, but I'm using ajax, I saw a example with nested dialogs but once again, with fetch. In the code I put there are 2 comments where I would like to handle the loading dialog.
This is my script:
$(document).on("submit", "#formNuevoEstudiante", function (event) {
event.preventDefault();
$("#btnSubmit").prop("disabled", true);
let ap_paterno = $("#ap_paterno").val();
let ap_materno = $("#ap_materno").val();
let nombre = $("#nombre").val();
let sexo = $("#sexo option:selected").val();
let no_control = $("#no_control").val();
let carrera = $("#carrera option:selected").val();
let semestre = $("#semestre option:selected").val();
let sexo2 = sexo == "F" ? "Femenino" : "Masculino";
let mensaje = `x`;
let mensaje2 = `x`;
//Here is where I wan't to integrate the loading dialog
$.ajax({
url: "utils/ajax/nuevo_estudiante.php",
method: "POST",
data: {
ap_paterno: ap_paterno,
ap_materno: ap_materno,
nombre: nombre,
sexo: sexo,
no_control: no_control,
carrera: carrera,
semestre: semestre,
},
success: function (resp) {
if (resp == "existe") {
Swal.fire({
title: "Ya se encuentra registrado",
text: "x",
icon: "warning",
confirmButtonText: "Aceptar",
confirmButtonColor: "#0275D8",
}).then(function () {
window.location.href = "index2.php";
});
} else if (resp == "error") {
Swal.fire({
title: "Error",
text: "x",
icon: "error",
confirmButtonText: "Aceptar",
confirmButtonColor: "#0275D8",
});
} else if (resp == "ok") {
//Here is where I wan't to close the loading dialog
Swal.fire({
title: "Registro exitoso",
html: "<pre>" + mensaje + "</pre>" + mensaje2,
icon: "success",
confirmButtonText: "Aceptar",
confirmButtonColor: "#0275D8",
}).then(function () {
window.location.href = "index2.php";
});
}
},
});
});
The example given in the SWAL2 website isn't very suited for your use as it creates an input form itself while you already have an HTML form that gets input from the user. A basic easy-to-implement solution would be to use the showLoading and hideLoading methods with what you already have. From the documentation :
Swal.showLoading(): Shows loader (spinner), this is useful with AJAX
requests.
By default the loader be shown instead of the "Confirm" button, but if
you want another button to be replaced with a loader, just pass it
like this: Swal.showLoading(Swal.getDenyButton())
Swal.hideLoading(): Hides loader and shows back the button which was
hidden by .showLoading()
Just after the event.preventDefault(); line, you can add a loading dialog that will just display a loading message:
Swal.fire({
title: "Loading...",
html: "Please wait a moment"
})
Swal.showLoading()
Then, at the beginning of the success callback of your ajax request, just before entering the if condition, simply add a Swal.hideLoading() to stop displaying the loading animation.
Why does hideLoading and showLoading work on an already displayed popup?
The reason is because SweetAlert2 kind of (it seems to work like that but I didn't confirm it) works using static methods which takes their execution to a "global" scope, meaning that when you call one of SweetAlert2 methods, it runs and stores data in the same place: the Swal class which is shared everywhere. (If you want to know more about static class, there are several articles you can read on the internet)
Disclaimer! Now, I didn't take a look at how Swal stores data, or how it handles everything, but for the sake of argument, let's say it stores inside static properties like currentTitle, isLoading (which dictates whether or not a loading animation should be added to the popup), and more. That is effectively one reason why there's only one popup displayed at a given time (although by definition, there should be only one displayed).
So, when you call Swal.fire(), it essentially updates the Swal class properties (setting the currentTitle to Hello for example). When you call it again, it updates it again and effectively overwrites the values set by the previous call of fire(), replacing them with new ones.
But, unlike fire() which completely overwrites every property for the currently displayed popup, hideLoading and showLoading methods only overwrite ONE property: isLoading (reminder: this is how we've postulated SweetAlert works, the implementation could be made otherwise but for simplicity's sake, we assume it's like that) and let the others as is. That is why, when you use fire(), a new popup is displayed, but when using hideLoading and showLoading, the current popup displayed is changed.

How to check if user has entered typeahed value

I have the following code:
var students = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('fullName'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/api/students?query=%QUERY',
wildcard: '%QUERY'
}
});
$('#student').typeahead({
minLength: 2,
highlight: true,
},
{
name: 'students',
display: function (item) { return item.fullName },
source: students.ttAdapter(),
templates: {
empty: [
'<div class="tt-empty-message">' +
'No results found' +
'</div>'
]
}
}).on("typeahead:select",
function (e, student) {
console.log("inside isselect");
isSelected = true;
vm.studentId = student.id;
});
I am trying to capture a scenario where if a user enters some gibberish or something apart from typeahead values and clicks on submit button, then I need to display an error message. To do that, I need to capture the typeahead list and see if the typeeahed list contains the input value. How can I accomplish this?
I have searched for this solution for 5 hours now. I have looked and implemented similar answers on other threads but nothing seemed to work. For instance take a look at this answer:
http://jsfiddle.net/Fresh/bbzt9hcr/
I tried the baove code but the typeahed does not even come up. Whereas my code works perfectly fine. Please let me know how I can solve this. Thank you in advance.
There are multiple way to approach this, the simplest:
you could listen the typeahead change event and use a variable to store the selected value, then on submit check and send that variable: http://jsfiddle.net/alfredopacino/bbzt9hcr/290/ .
yourTypehead.on('typeahead:selected', function($e, datum) { // suggestion selected
selectedMovie = datum.value
});
$('#submit').click(function() {
if(selectedMovie) {
//your ajax call
} else {
alert("no valid movie")
}
});
The problem with this is it doesn't covers the case the user enters manually a valid value.
To cover this scenario you could follow two ways:
onSubmit you can add a 'remote validation': basically an additional ajax request to check if the value is valid using the server
convert your typeahead selection in a "tag selection", limit the tags to 1 and forbid any custom value https://bootstrap-tagsinput.github.io/bootstrap-tagsinput/examples/ (there are TONS of plugin doing that)

CKEDITOR: Disable plugin button when text is not highlighted

I have a CKEDITOR plugin that I'm having trouble disabling when there is no selected copy in the editor. Right now, the user can click the button without any highlighted text in the editor. I would like to modify it so that the plugin button is only active when there is copy highlighted in the editor. I've followed the suggestion here, but it isn't working.
Main Plugin Code:
CKEDITOR.plugins.add('cta', {
icons: 'cta',
init: function (editor) {
// Funciton depending on editor selection (taken from the scope) will set the state of our command.
function RefreshState() {
console.log('RefreshState');
var editable = editor.editable(),
// Command that we want to control.
command = editor.getCommand('source'),
range,
commandState;
if (!editable) {
// It might be a case that editable is not yet ready.
console.log("editable not ready yet");
return;
}
// We assume only one range.
range = editable.getDocument().getSelection().getRanges()[0];
console.log(`range: `);
console.log(range);
// The state we're about to set for the command.
commandState = (range && !range.collapsed) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
console.log('commandState');
console.log(commandState);
command.setState(commandState);
}
// We'll use throttled function calls, because this event can be fired very, very frequently.
var throttledFunction = CKEDITOR.tools.eventsBuffer(250, RefreshState);
// Now this is the event that detects all the selection changes.
editor.on('selectionCheck', throttledFunction.input);
// You'll most likely also want to execute this function as soon as editor is ready.
editor.on('instanceReady', function (evt) {
// Also do state refresh on instanceReady.
RefreshState();
});
editor.addCommand('ctabtn', new CKEDITOR.dialogCommand('ctaDialog'));
editor.ui.addButton('cta', {
label: 'Insert Call to Action button',
command: 'ctabtn',
toolbar: 'insert'
});
CKEDITOR.dialog.add('ctaDialog', this.path + 'dialogs/cta.js');
}
});
My dialog code is here:
CKEDITOR.dialog.add('ctaDialog', function (editor) {
return {
// Basic properties of the dialog window: title, minimum size.
title: 'Call to Action',
minWidth: 400,
minHeight: 200,
// Dialog window content definition.
contents: [{
// Definition of the Basic Settings dialog tab (page).
id: 'tab-basic',
label: 'Basic Settings',
// The tab content.
elements: [{
// Text input field for the Call to Action text.
type: 'text',
id: 'cta',
label: 'Call to Action',
// Validation checking whether the field is not empty.
validate: CKEDITOR.dialog.validate.notEmpty("Call to Action field cannot be empty.")
},
{
// Text input field for the link text.
type: 'text',
id: 'url',
label: 'URL',
// Validation checking whether the field is not empty.
validate: CKEDITOR.dialog.validate.notEmpty("URL field cannot be empty.")
}
]
}],
// method invoked when the dialog button is clicked
onShow: function () {
var element = editor.getSelection();
var link = CKEDITOR.plugins.link;
var _this = this.getParentEditor();
var CTAhref = link.getSelectedLink(_this);
this.setValueOf('tab-basic', 'cta', element.getSelectedText().toString());
if (CTAhref != '' && CTAhref !== null) {
this.setValueOf('tab-basic', 'url', CTAhref.$.href);
}
},
// This method is invoked once a user clicks the OK button, confirming the dialog.
onOk: function () {
var dialog = this;
var CTA = editor.document.createElement('a');
CTA.setAttribute('href', dialog.getValueOf('tab-basic', 'url'));
CTA.setAttribute('class', 'btn btn-special--lg');
CTA.setText(dialog.getValueOf('tab-basic', 'cta'));
editor.insertElement(CTA);
}
};
});
Any ideas on why the plugin icon button on the toolbar doesn't become inactive when there is no copy highlighted in the editor? I can see in the console that CKEDITOR.dom.range.collapsed is toggling between TRUE/FALSE depending upon whether text is highlighted or not. It's just not disabling the button.
As stated, the suggested way of handling this was not working for me. What was working was using range.collapsed in returning a true value if a selection was made in the editor. With that, I turned to using Jquery to handle the rest.
// Hacky. But it gets the job done.
// a.cke_button.cke_button__cta.cke_button_off is the selector for my toolbar button.
// The onclick function listed was pulled from looking at the CKeditor functions
// to initiate my plugins modal.
// The setting of the "onclick" prop to null is needed to override the modal onclick
// binding when there is no selection.
range = editable.getDocument().getSelection().getRanges()[0];
if (range.collapsed === false) {
$('a.cke_button.cke_button__cta.cke_button_off').attr("onclick", 'CKEDITOR.tools.callFunction(83,this);return false;');
$('a.cke_button__cta').toggleClass('cta_button_disabled');
} else {
$('a.cke_button.cke_button__cta.cke_button_off').prop("onclick", null);
}

Form in Bootbox Dialog

I want to display a Bootbox dialog that includes an "OK" button. When the user clicks the "OK" button, it should POST back, with the ID of the message to confirm that the user has viewed the message. The Bootbox dialog is the form. I don't see a way to make the dialog buttons a submit form with hidden fields, which is what I assume is the right way to accomplish my goals.
Thanks to the helpful comments from Isabel Inc and Mistalis, I have a working solution.
Notes specific to my implementation:
The messages contain images that need to be responsive, so I add the appropriate Bootstrap classes to each image
The messages may have links. Clicking a link is equivalent to clicking "OK" on the dialog
And the JavaScript that makes it happen...
jQuery(function($, window, bootbox, undefined) {
var accept = function(callback) {
$.ajax({
type: 'POST',
data: {message_id: 244826},
success: callback()
});
};
var $message = $('<p><img src="https://www.gravatar.com/avatar/80fa81938a6d1df92cd101d7fe997a71" alt></p><p>Here is a message from Sonny.</p>');
$message.find('img').addClass('img-responsive center-block');
$message.find('a').on('click', function(e) {
var href = $(this).attr('href');
if (0 === href.length) {
return;
}
e.preventDefault();
accept(function() { window.location.href = href; });
});
bootbox.dialog({
message: $message,
closeButton: false,
buttons: {
accept: {
label: 'OK',
callback: function() {
accept(function() { window.location.reload(); });
}
}
}
});
}(jQuery, window, bootbox));

how to disable typeahead:active when focusing a filled-in text field in a remote typeahead.js

I'm using typeahead.js and it's great but here's my use case: I have a text field that is already filled in with a string on the server side when the page is loaded, so I don't want the suggestions menu to be shown when the user focuses the text field.
typeahead.js seems to always show the menu when focusing the text field. This makes sense since minLength is 2 and the text field value is something like "Tony" (or whatever). But I've tried using hint: false and calling $('.typeahead').typeahead('close') inside a callback for the typeahead:active event, and neither seem to stop the menu from being shown.
Here's the init code I'm using:
$('#locationInput').typeahead({
hint: false,
highlight: false,
minLength: 2
},
{
name: 'locations',
display: 'name',
source: typeaheadLocations, // a simple Bloodhound instance
templates: {
suggestion: function(locationObj) {
return $('<div>' + locationObj.name + '</div>');
}
}
});
There is a slight delay between when I focus the text field and the menu is actually shown, because the remote GET has to be run. So I'm guessing I would need to prevent that somehow, after it's focused.
Looks like closing the menu in the typeahead:open event does the trick, but this seems pretty hack-ish to me. :(
$('#locationInput').typeahead({
hint: true,
highlight: true,
minLength: 2
},
{
name: 'locations',
display: 'name',
source: typeaheadLocations,
templates: {
suggestion: function suggestion(locationObj) {
return $('<div>' + locationObj.name + '</div>');
}
}
}).on('typeahead:open', function(e) {
var $input = $(e.currentTarget);
if (!$input.data('wasFocusedOnce')) {
$input.data('wasFocusedOnce', true);
$input.typeahead('close');
}
}).on('typeahead:close', function(e) {
$(e.currentTarget).removeData('wasFocusedOnce');
}).on('keydown', function(e) {
$(e.currentTarget).data('wasFocusedOnce', true);
});
If anyone knows of a better way to do this, I'm all ears!

Categories

Resources