Populating textarea in a modal window - javascript

Here's my code:
// Open modal window with links
$('.links').colorbox({speed:100, opacity:0.75, html:'<div id="links-colorbox"><h2>Download links</h2><textarea name="links"></textarea></div>'});
// Populate textarea with links
for(i in linkList) {
$('#links-colorbox textarea').append('http://site.com/' + linkList[i][0] + '/' + linkList[i][1] + '\n');
}
The problem is the textarea in the modal window doesn't get populated, probably because it's inserted into the DOM on the fly with the modal window plugin I'm using.
Is there a way I can make this work? Thanks.

Use oncomplete callback:
$('.links').colorbox({
speed:100,
opacity:0.75,
html:'<div id="links-colorbox"><h2>Download links</h2><textarea name="links"></textarea></div>',
onComplete: function() {
for(i in linkList) {
$('#links-colorbox textarea').append('http://site.com/' + linkList[i][0] + '/' + linkList[i][1] + '\n');
}
}
});

Related

Changing CSS based on button state

in my application i post data to the server via ajax, while data is being posted to the server i want to be able to show the user that something is indeed happening, now a simple way to do this will be to display a loading gif. What i actually want to do is change the state of the button that was clicked. I have 4 classes in my css:
btn-ready-state
btn-working-state
btn-completed-state
btn-failed-state
Now each button has a class of btn-ready-state when you click the button the class changes to btn-working-state where the text of the button changes to "working" and a small loading icon appears inside the button. When the operation is done successfully it switches to btn-completed-state if it fails then btn-failed-state. Now i have been able to do this in my code with jquery but the code is so messy and untidy and doesn't work properly with angular. I have been told i can use directives to achieve this but since i am new to angular i am confused as to how to implement this with directives, i do know what a directive is and how to make one, my issue here is the implementation of this particular feature. This is how i did it with jquery:
<script type="text/javascript">
$(document).ready(function() {
var $loading = $('#loading');
$loading.on("change", function(){ //bind() for older jquery version
var index = parseInt($('#loading').val());
var done = parseInt($('#done').val());
if (done === 0) {
$('.btn.ticket:eq(' + [index] + ')').removeClass('btn-ready-state');
$('.btn.ticket:eq(' + [index] + ')').addClass('btn-working-state');
$('.btn.ticket:eq(' + [index] + ')').find('.text').text('Working..');
$('.btn.ticket:eq(' + [index] + ')').find('.state').addClass('loading');
$('.btn.ticket:eq(' + [index] + ')').find('i').replaceWith('<img src="/images/loading.gif">' + '</img>');
} else {
$('.btn.ticket:eq(' + [index] + ')').removeClass('btn-ready-state');
$('.btn.ticket:eq(' + [index] + ')').removeClass('btn-working-state');
$('.btn.ticket:eq(' + [index] + ')').addClass('btn-completed-state');
$('.btn.ticket:eq(' + [index] + ')').find('.text').text('Added');
$('.btn.ticket:eq(' + [index] + ')').find('.state').addClass('done');
$('.btn.ticket:eq(' + [index] + ')').find('i').replaceWith('<i class="glyphicon glyphicon-ok state"></i>');
$('.btn.ticket:eq(' + [index] + ')').find('img').replaceWith('<i class="glyphicon glyphicon-ok state"></i>');
}
}).change(); //could be change() or trigger('change')
});
$(document).on("click", ".btn.ticket", function() {
var index = $(".btn.ticket").index(this);
$('#loading').val(index).change();
});
$(document).on("click", ".btn.next", function() {
$(this).removeClass('btn-ready-state');
$(this).addClass('btn-working-state');
$(this).find('.text').text('Working..');
$(this).find('.state').addClass('loading');
$(this).find('i').replaceWith('<img src="/images/loading.gif">' + '</img>');
});
</script>
This is a sample html of the button:
<button class="btn-ready-state"><span class="img"></span><span class="text"></span></button>
90% of the script changes the style. You said you like to indicate ajax? Look at this:
<script>
jQuery.ajaxSetup({
ajaxStart:function(){
jQuery('body').toggleClass('ajaxing', true);
},
ajaxStop:function(){
jQuery('body').toggleClass('ajaxing', false);
}
})
</script>
This is better because you dont need to repeat yourself (DRY-Principle).
So instead of doing this in javascript:
$(this).find('i').replaceWith('<img src="/images/loading.gif">' + '</img>');
You can now do all the graphical stuff you did in javascript in CSS:
.ajaxing i {
background-image: url(/images/loading.gif);
}
// for text you can use this:
.ajaxing .btn.ticket:active:before{
position:relative;
content:'Working...';
}
Or in anguarjs:
angular.module('app', []).value('loadManager', {
c: 0,
requested: function() { c++; document.body.class="ajaxing";},
responded: function() { c--; if(!c)document.body.class="";}
}).factory('loadingInterceptor', function(loadManager) {
return {
request: function(e) {
loadManager.requested();
return e;
},
response: function(e) {
loadManager.responded();
return e;
},
}
});
$httpProvider.interceptors.push('loadManager');
All of this is only an example. I do not know the complete HTML you are using.

How to Show Dynamically Added Element

I'm trying to create tooltips with title attribute and jQuery but can't find method to show dynamically added element.
HTML
some page
CSS
.tooltip {
    …
display: none; /* I's needed for hard coded tooltips */
…
}
jQuery
$(function () {
if (window.matchMedia('(min-width: 980px)').matches) {
$('.dfn').hover(
function () {
var el = $(this);
var txtTitle = el.prop('title');
el.append('<p class="tooltip">' + txtTitle + '</p>');
                //That's it. My tooltip has been created, but it has not been shown
$(el + ' .tooltip').show('fast');
el.data('title', el.prop('title'));
el.removeAttr('title');
}, function () {
$(el + ' .tooltip').hide('fast').remove();
el.prop('title', el.data('title'));
}
);
}
});
As mentioned by others, $(el + ' .tooltip').show('fast'); is probably wrong.
The el is an object, not a string to concat', one way is to use el.find('.tooltip').show().
The other way is to use the context option: $('.tooltip', el).show();
You need to have correct code to find new element:
$('.tooltip', el).show('fast');
Your current one probably endup searching for something like [object] .tooltip or similar string depending on how JavaScript decides to convert HTML element to string.
As others have mentioned el.find('.tooltip').show() and el.find('.tooltip').hide().remove(); solve the problem.
Also, in HandlerOut function, you el was not declared. Fiddle here
$(function () {
//if (window.matchMedia('(min-width: 980px)').matches) {
$('.dfn').hover(
function () {
var el = $(this);
var txtTitle = el.prop('title');
el.append('<p class="tooltip">' + txtTitle + '</p>');
//That's it. My tooltip has been created, but it has not been shown
el.find('.tooltip').show()
el.data('title', el.prop('title'));
el.removeAttr('title');
}, function () {
var el = $(this);
el.find('.tooltip').hide().remove();
el.prop('title', el.data('title'));
}
);
//}
});

Accessing the wysihtml5 editor object to use it inside "events"?

I found this in the documentation of bootstrap-wysihtml5:
The underlying wysihtml5 object
You can access the wysihtml5 editor object like this:
var wysihtml5Editor = $('#some-textarea').wysihtml5().data("wysihtml5").editor;
wysihtml5Editor.composer.commands.exec("bold");
So I tried this:
<script type="text/javascript">
var myCustomTemplates = {
link : function(locale) {
return "<li>" +
"<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>" +
"<div class='modal-header'>" +
"<a class='close' data-dismiss='modal'>×</a>" +
"<h3>" + locale.link.insert + "</h3>" +
"</div>" +
"<div class='modal-body'>" +
"<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>" +
"</div>" +
"<div class='modal-footer'>" +
"<a href='#' class='btn' data-dismiss='modal'>" + locale.link.cancel + "</a>" +
"<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.link.insert + "</a>" +
"</div>" +
"</div>" +
"<a class='btn' data-wysihtml5-command='createLink' title='" + locale.link.insert + "'><i class='icon-link'></i></a>" +
"</li>";
},
"font-styles": function(locale, options) {
return "<li>" +
"<a class='logo'>Logo</a>" +
"</li>" +
"<li>" +
"<a class='btn btn-paragraph' data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='p'>" + locale.font_styles.p + "</a>" +
"</li>" +
"<li>" +
"<a class='btn btn-paragraph' data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='p'>" + locale.font_styles.p + "</a>" +
"</li>";
}
}
$('#wysihtml5-textarea').wysihtml5('deepExtend', {
"font-styles": true, //Font styling, e.g. h1, h2, etc. Default true
"emphasis": true, //Italics, bold, etc. Default true
"lists": true, //(Un)ordered lists, e.g. Bullets, Numbers. Default true
"html": true, //Button which allows you to edit the generated HTML. Default false
"image": false, //Button to insert an image. Default true,
"link": false,
"format-code": false, // enable syntax highlighting
customTemplates: myCustomTemplates,
"events": {
"focus": function() {
//var wysihtml5Editor = $('#wysihtml5-textarea').wysihtml5().data("wysihtml5").editor;
//wysihtml5Editor.composer.commands.exec("insertHTML", "<a href=...>");
}
},
parserRules: {
tags: {
p: {}
}
},
"stylesheets": ["<%= root_url %>wysiwyg-color.css", "<%= root_url %>github.css"], // CSS stylesheets to load
});
</script>
But it seems like it is breaking the code:
GET http://localhost:3000/posts/lib/css/wysiwyg-color.css 404 (Not Found)
And wysihtml5Editor.composer.commands.exec is not working either.
(The file loads just fine if I don't include the content inside "focus": function() {)
What the right way of doing this?
EDIT
Here's a minimally working code, to use as a starting point:
// I use this to keep this code out of the global scope.
// This takes this form: (function($){...})(jQuery);
// and allows me to use $ without worry about it interfering
// with other libraries and frameworks that share it's use.
(function priv($) {
// This is another scope thing; I can set the reference
// later on, but it will be in the parent scope, so I
// can cache these and then access them from within a
// window.onload handler, for instance, that I create
// further down.
var $editor,
opts;
// A more elegant, clean way of doing what was in the docs.
opts = {
// Note, it's not necessary to use quotes on labels in
// object notation, UNLESS there's something not allowed.
// This and format-code have comments ONLY because they
// have that infernal dash in there. No others in this
// list do, however.
'font-styles': false,
'format-code': false,
emphasis: true,
lists: true,
html: false,
image: false,
link: false,
events: {
// Passing a reference to a function I've declared
// later. I could not have this before the actual
// functions, though, if I use var onload = function...
// since "hoisting" does not occur. So, be careful
// emulating this too liberally if you don't under
// why it works.
load: onload,
focus: onfocus,
blur: onblur
}
};
// I'm using the `window.onload` method to setup my editor
// AFTER the page has loaded and the DOM is ready.
$(window).on('load', function load() {
// See, I set this up here, and can access it in the
// onload, onfocus, and onblur handlers without
// requerying. It's called caching a reference.
$editor = $('#wysihtml5-textarea');
$editor.wysihtml5(opts);
});
function onload() {
console.log('load');
}
function onfocus() {
console.log('focus');
}
function onblur() {
console.log('blur');
}
})(jQuery);​
http://jsfiddle.net/userdude/nWebx/5/
I put the wysihtml5 editor demo in a properly running fiddle and then modified it to run your referenced code:
$(window).on('load', function load(){
/*$('.textarea').wysihtml5();
$(prettyPrint);*/
$('#wysihtml5-textarea').wysihtml5('deepExtend', {
"font-styles": true, //Font styling, e.g. h1, h2, etc. Default true
"emphasis": true, //Italics, bold, etc. Default true
"lists": true, //(Un)ordered lists, e.g. Bullets, Numbers. Default true
"html": true, //Button which allows you to edit the generated HTML. Default false
"image": false, //Button to insert an image. Default true,
"link": false,
"format-code": false, // enable syntax highlighting
customTemplates: myCustomTemplates,
"events": {
"focus": function() {
var wysihtml5Editor = $('#wysihtml5-textarea').wysihtml5().data("wysihtml5").editor;
wysihtml5Editor.composer.commands.exec("insertHTML", "<a href=...>");
}
},
parserRules: {
tags: {
p: {}
}
},
"stylesheets": ["<%= root_url %>wysiwyg-color.css", "<%= root_url %>github.css"], // CSS stylesheets to load
});
})
http://jsfiddle.net/userdude/nWebx/2/
With this as-is, I receive this error in Chrome Console:
Uncaught ReferenceError: myCustomTemplates is not defined
So I comment that line out, and it runs. Try it:
http://jsfiddle.net/userdude/nWebx/1/
Now, I am running the editor code within a window.onload event using jQuery's $.on() event handler method:
$(window).on('load', function load(){
$('#wysihtml5-textarea').wysihtml5('deepExtend', {
...
});
}) // <<< I'd try to always using `;` at the end of statements.
And I also get no errors with the focus handler, although I need to check that it's event running to beginning with. So, what is in myCustomTemplates?
Try something like this:
var wysihtml5Editor = $('#some-textarea').wysihtml5().data("wysihtml5").editor;
wysihtml5Editor.composer.commands.exec("bold");
var focusHanlder = function(){
console.log(wysihtml5Editor);
wysihtml5Editor.composer.commands.exec("insertHTML", "<a href=...>");
}
var secondFocusHandler = function(){
console.log(this);
this.composer.commands.exec("insertHTML", "<a href=...>");
}.bind(wysihtml5Editor);
where focusHandler uses the exterior variable wysihtml5Editor and secondFocusHanlder uses that variable as this inside the call. Now pass one of those variable to the focus event.
Here is a little example of using the events on wysihtml5Editor: https://github.com/xing/wysihtml5/wiki/Events

Apply a jQuery function live() in 1 object

I have a Facebook-Like Chat. (You can see it # http://www.live-pin.com/). It gets the last messages from a JSON file and inserts into an individual UL for each user, it before checks if the ul exists and if it doesnt, it creates. Now the problem is that when I click on 1 chat bar, the 3 open at the same time, and only close if I click on the last one, what can I do? I want that this bars only open/close when clicked on chat bar but doesnt if click on not_clickable. Thanks for your help
$(document).ready(function(){
getOnJSON();
setInterval("getOnJSON()", 60000);
var Id;
var target;
});
function showChat(obj){
$(obj).animate({marginBottom : "0"}).removeClass("hidden_box").addClass("active_box").unbind('click')/*.click(function(){
hideChat(this);
})*/;
}
function hideChat(obj){
$(obj).animate({marginBottom : "-270px"}).removeClass("active_box").addClass("hidden_box").unbind('click')/*.click(function(){
showChat(this);
})*/;
}
function getOnJSON(){
var self = this; // Added this line, as this changes scope in each()
var from;var to;var msg_id;var msg_txt;var new_chat_string;
//Getting the data from the json file
$.getJSON("/ajax/chat.json.php",function(data){
$.each(data.notif, function(i,data){
from = data.from;to = data.to;msg_id = data.id;msg_txt = data.text;
if ($("#chat_"+from+"_lp").length === 0){
$("#boxes").append('<div id="chat_'+from+'_lp" class="chat_box hidden_box clickable_box"><div id="chat_'+from+'_nick" class="chat_name">'+from+'</div><div class="not_clickable"><ul id="chat_'+from+'_txt" class="chat_txt"><li id="' + msg_id + '">'+ msg_txt+'</li></ul><form class="chat_new_message" name="new_msg"><input type="text" placeholder="Enter your message..." class="chat_new_input"/></form></div></div>');
$('.hidden_box #chat_'+from+'_nick').live("click", function(){ showChat('#chat_'+from+'_lp'); });
$('.active_box #chat_'+from+'_nick').live("click", function(){ hideChat('#chat_'+from+'_lp'); });
}else{
$("#chat_"+from+"_txt").append('<li id="' + msg_id + '">'+ msg_txt+'</li>');
$('.hidden_box #chat_'+from+'_nick').live("click", function(){ showChat('#chat_'+from+'_lp'); });
$('.active_box #chat_'+from+'_nick').live("click", function(){ hideChat('#chat_'+from+'_lp'); });
}
});
});
}
You need to use jquery .live() function for your .click() to be applied to elements created after the document load complete.
For instance: $("a.offsite").live("click", function(){ alert("Goodbye!"); }); is an example from here

JQueryUI calling .accordion twice on one id

I'm trying to use AJAX to dynamically generate a JquerUI Accordion based on what is selected in a box. Currently I have
<div style="display:none" id="testselect">
</div>
With JS
$("#courseselect").change(function () {
$("#testselect").html(""); // Empty any previous data
$("#testselect").css("display", "block"); // Display it if it was hidden
$.getJSON('json.php?show=tests&courseid=' + $(this).val(), function(data) {
for(x in data)
{
$("#testselect").append("<h3 value=\"" + data[x].uno + "\">" + data[x].name + "</h3>");
$("#testselect").append("<div>Foo</div>");
}
$("#testselect").accordion({ change:function(event, ui) { courseid = ui.newHeader.attr("value");
} });
});
});
Now this works the first time I change my selection, but after that it reverts to plain old unformatted HTML. As if the call to .accordion() was never done. I'm guessing this has something to do with JQuery not wanting me to format something twice, but I really have no idea.
Try to destroy the accordion before you empty the div and start again:
$("#courseselect").change(function () {
$("#testselect")
.accordion("destroy")
.empty() // equivalent to .html("");
$.getJSON(...
More info here.
Good luck!

Categories