I am currently working on a web app using python and Django, and i have a screen with a popup using the fancybox jquery plugin.
When the link is clicked it opens a url on my server which is basically a form.
What i am trying to achieve is the ability to pass the values of the form inputs to my main page once the popup is closed.
I have a funny feeling that is isnt going to be possible and i might be better off using hidden divs (which hide so on command) rather than a popup.
my test page:
<div class='link'>
<a class='fancy' href='create/' > click me </a>
</div
the javascript atm:
$(function(){
$('.fancy').fancybox(
{
type:'ajax',
afterClose: function(){
alert('done!');
}
}
});
The main idea is the popup has a form which has values which will be added to the Django database, but there is also a table on the main window which also displays these.
I wanted to make the main window to be the one which creates the object, saves it and then loads it into the form ( this is taken care of from a API call which i use ajax)
any help at all would be great
Following is a very simplistic pub/sub that creates a stored object and updates object and page elements using change event of form inputs
Html:
<!-- table, match "data-bind" to form input name -->
<td data-bind="fname" class="subscriber">Foo</td>
<td data-bind="lname" class="subscriber">Bar</td>
<!-- form -->
<input type="text" name="fname" class="data_source" />
JS:
/* declare empty object */
var storedData = {};
var $subscribers=$('.subscriber');
/* this event triggered when input changes*/
$(document).on('upDataData', function( event, key, value){
storedData[key]=value;
$subscribers.filter( '[data-bind="'+key+'"]').text( value );
});
/* change handler for form inputs*/
$(document).on('change', 'form input.data_source', inputChange);
function inputChange(){
$(document).trigger('upDataData',[ this.name, this.value]);
}
/* populate storedData from table elements when page loads*/
function createInitialData(){
$subscribers.each(function(){
storedData[ $(this).data('bind')]= $(this).text();
});
}
createInitialData()
Then in your fancybox code send object to server and parse values into form with server code:
$('.fancy').fancybox({
type:'ajax',
/* same as "options" for "$.ajax"*/
ajax: { data : storedData},
afterClose: function(){
alert('done!');
}
});
DEMO: http://jsfiddle.net/xg9ML/2/
Related
I am building a custom WordPress plugin that requires me to build into it a custom media library button that lets a user associate an image with a certain option for a post. The user needs to be able to add the elements dynamically, so there are multiple options, i.e. multiple medial library buttons.
The issue that I am running into is that if I have 5 options with five buttons, setting the first image works fine. But if I click buttons 2-5 to set the images for the additional options, they are not getting set but the first option is changing.
It's almost like once the initial element is set on click, then it never changes.
Here is a sample of the HTML (the generic.jpg is the default image before the image is set from the library):
<div class="image-preview-wrapper">
<img class="image-preview" src="https://WEBSITE/wp-content/plugins/atas_spec_writer/admin/assets/generic.jpg" style="max-height: 100px; width: 100px;" width="100" height="100">
<input type="button" class="button upload_image_button" value="Add Image">
<input type="hidden" name="options[section_4][3][img_id]" class="image_attachment_id" value="">
</div>
Here is the JS code:
// Uploading files
var j = jQuery;
var file_frame;
j(document).on('click', '.upload_image_button', function(event) {
var el = j(this);
event.preventDefault();
// If the media frame already exists, reopen it.
if (file_frame) {
// Open frame
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frames.file_frame = wp.media({
title: 'Select a image to upload',
button: {
text: 'Use this image',
},
multiple: false // Set to true to allow multiple files to be selected
});
// When an image is selected, run a callback.
file_frame.on('select', function() {
// We set multiple to false so only get one image from the uploader
attachment = file_frame.state().get('selection').first().toJSON();
el.siblings('.image-preview').attr('src', attachment.url);
el.siblings('.image_attachment_id').val(attachment.id);
});
// Finally, open the modal
file_frame.open();
// Restore the main ID when the add media button is pressed
j('a.add_media').on('click', function() {
wp.media.model.settings.post.id = wp_media_post_id;
});
I've switched up using j(this), event.target, and they both seem to stick with the first element clicked.
I originally thought that it might just go to the first element in the DOM that matches what is clicked, but if I add 2 options with images and then come back two days later and add two more, the click event sticks with the first element that was set that day, not the first element in the DOM.
So I am completely at a loss......
Any help is much appreciated!!
Looks like once you open a frame file_frame variable will never be nullified or resetted.
I guess problem lies in the following return statement:
if (file_frame) {
// Open frame
file_frame.open();
return;
}
I am new to Bootstrap designing and currently using the Bootstrap v3.1.1 version of it in my ASP.NET MVC5 Project.
I am opening a form on "Edit profile" Click of button and editing some fields such as email.
What I want to do is to reflect them on the main form on close of modal popup.
Here is my code:
$('#EditProfile').on('hidden.bs.modal', function () {
debugger;
var newEmail = $("#txtEmailId").val();
$("#txtEmail").val() = newEmail;// = newEmail;
});
Also I am showing email id on main form using following code:
<tr>
<th>Email</th>
<td>
<input readonly id="txtEmail" name="txtEmail" type="text" class="form-control"placeholder="Email" size="254" style="width: 200px;"/>
</td>
</tr>
You need to use:
$("#txtEmail").val(newEmail);
instead of:
$("#txtEmail").val() = newEmail;
Bootstrap 3 documentation refers two events you can use
hide.bs.modal: This event is fired immediately when the hide instance method has been called.
hidden.bs.modal: This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).
And provides an example on how to use them:
$('#myModal').on('hidden.bs.modal', function () {
$("#txtEmail").val(newEmail);
});
Recommend you to read more on .val() here
Additional note (not related to your question) Do not use inline style in your html like how you have used this width: 200px;
You have to use :
$("#txtEmail").attr('value',newEmail);
instead of
$("#txtEmail").val() = newEmail;
in your code.
Try this:
$("#txtEmail").text(newEmail);
Or this:
$("#txtEmail").html(newEmail);
JQuery Mobile template which utilises a side panel. For simplicity I want to be able to load this panel from an 'external page' / seperate document so that it can be built once and used on many pages.
A bit of research has resulted in me getting the following code to load a string of html into a variable and then loading that variable into each page as the side panel:
/* Get the sidebar-panel as a var */
var side_var = '<div data-role="panel" id="left-panel" data-position="left" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
/* Load the side-panel var to the DOM / page */
$(document).one('pagebeforecreate', function () {
$.mobile.pageContainer.prepend( side_var );
$("#left-panel").panel();
});
This works perfectly, however it still doesn't address the need to build the sidebar / panel as a separate html file.
A bit more work and I discovered this snippet to load a page into a variable:
$.get("http://www.somepage.com", function( side_var ) {}, 'html');
So in theory adding the two together should give me the desired result;
/* Get the sidebar-panel as a var */
$.get("mypage.html", function( side_var ) {}, 'html');
/* Load the side-panel var to the DOM / page */
$(document).one('pagebeforecreate', function () {
$.mobile.pageContainer.prepend( side_var );
$("#left-panel").panel();
});
However, all I get when running this is an eternally rotating AJAX loader.
What am I missing &/or doing wrong??
COMPLETE SOLUTION
Omar's solution below goes most of the way but needs one small but important addition to make the JQM elements display as expected. Here is the complete solution:
$(document).one("pagebeforecreate", function () {
$.get('side-panel.html', function(data) {
//$(data).prependTo($.mobile.pageContainer); //or .prependTo("body");
$.mobile.pageContainer.prepend(data);
$("[data-role=panel]").panel().enhanceWithin(); // initialize panel
}, "html");
});
Each element to be enhanced as a JQM element needs the data-theme adding to tell it which theme to use. Additionally in the JavaScript the initialised panel widget needs to .enhanceWithin() in order for the elements to be rendered with the desired style.
the $.get() function should be wrapped in pagebeforecreate event, to append contents directly once retrieved. Also, you need to initialize retrieved contents.
$(document).one("pagebeforecreate", function () {
$.get('mypage.html', function(data){
$(data).prependTo("body"); // or .prependTo($.mobile.pageContainer);
$("[data-role=panel]").panel(); // initialize panel
}, "html");
});
I have a form with drop-down hierarchical fields with functionality derived from a JavaScript plugin called mcDropdown jQuery Plug-in.
The actual form is on a secondary page (Test.php) and set up to display on the main page through a Colorbox popup with the results also displayed in the Colorbox upon form submission.
The form submits and displays correctly in the Colorbox in its native HTML format when the JavaScript is removed (i.e. just using plain drop-down boxes).
However, when the Javascript is implemented in the form allowing the hierarchial drop-down structure of the fields there is no JS functionality when rendered through Colorbox.
Since the actual page that the form is on (Test.php) works fine by itself with the Javascript, there appears to be some issue rendering the JS through the Colorbox.
My research has indicated that this may be due to trying to access an element before it has been loaded into the document.
The Colorbox website states that this can be resolved by moving the JavaScript into ColorBox's onComplete callback; however, even with the example given, I cannot figure out how to do this correctly as I am a complete novice when it comes to JS.
Here is the drop-down script on the secondary page that has the form and ties into the external plugin (note that there are three fields in this form that use this JS hierarchical configuration):
<script type="text/javascript">
$(document).ready(function (){
$("#category").mcDropdown("#categorymenu",
{
targetColumnSize: 3,
}
);
$("#category1").mcDropdown("#categorymenu1",
{
targetColumnSize: 3,
}
);
$("#category2").mcDropdown("#categorymenu2",
{
targetColumnSize: 3,
}
);
});
</script>
Here is the Colorbox script on the main page that opens the secondary page in the Colorbox window:
<script type="text/javascript"> <!--<Check-Out Colorbox Script>-->
jQuery(function(){
jQuery('#link_content').colorbox({opacity:0.3, height:"100%", scrolling: false, onComplete: function(){
link_content_submit();
}});
});
function link_content_submit()
{
jQuery("#pre-process").submit(function(){
jQuery.post(
jQuery(this).attr('action'),
jQuery(this).serialize(),
function(data){
jQuery().colorbox({html: data, onComplete: function(){
link_content_submit();
}});
}
);
return false;
});
}
</script>
The three external files are: jquery.mcdropdown.js, jquery-1.2.6.min.js and jquery.bgiframe.js.
How can this Colorbox script on the main page be modified so the JS functionality of the form is preserved when displayed through Colorbox?
Thank you in advance for any detailed answers for this beginner.
Here is the answer:
<script type="text/javascript"> <!--<Check-Out Colorbox Script>-->
jQuery(function(){
jQuery('#link_content').colorbox({opacity:0.3, height:"100%", scrolling: false, onComplete: function(){
link_content_submit(), $('#category').mcDropdown('#categorymenu'),$('#category1').mcDropdown('#categorymenu1'),$('#category2').mcDropdown('#categorymenu2');
}});
});
function link_content_submit()
{
jQuery("#pre-process").submit(function(){
jQuery.post(
jQuery(this).attr('action'),
jQuery(this).serialize(),
function(data){
jQuery().colorbox({html: data, onComplete: function(){
link_content_submit();
}});
}
);
return false;
});
}
</script>
The respective JavaScript functions for each drop-down box in the JS form are integrated into the Colorbox onComplete: function() so each of these form elements is loaded before it is accessed through Colorbox.
I'm using the FileStreamResult (or FileResult) method to display a chart on a razor view page (from a Controller action) and this works as expected.
However, I'm wondering if it's possible to display the chart ONLY when an html element is clicked.
e.g. Click on an element, display chart in modal pop-up.
I can get a modal to display using Jquery...but ONLY if I have already loaded the chart into a div.
I'd like to have the page load without the chart (for performance reasons), and then only generate/load the chart when the is clicked.
I guess I need an Ajax call of somekind...but I'm a little stuck as to how to proceed and googling didn't return anything useful (just lightbox for photos)
Pseudo Code:
HTML:
<img src='small chart icon.jpg' alt='click me to see chart' id='showchart'/>
<div>
rest of page goes here...
</div>
C#:
public FileStreamResult GetChart(){
//generate any chart
return FileStreamResult(newchartstream, "image/png");
}
JS:
<script>
$(document).ready(function(){
$('#showchart').click(function(){
//make ajax call to generate chart
//show in modal with "close" button
//OR
//open a new page as a modal?
});
});
</script>
EDIT
Clarification:
Controller generates a ViewModel (from an EF4 model) which contains the results of lots of calculations, and some "summary" rows (totals, averages etc)
View displays the results (ViewModel) as tables.
Requirement:
Click on one of the summary rows, opens modal window displaying a chart for that summary row.
Would like to avoid sendind the parameters for the ViewModel and re-generating it from scratch (doing all the calcs again etc) for two reasons
1) The figures in the back-end db may have changed...so the chart doesn't reflect whats being shown in the tables.
2) It takes time to do the calcs!
I'd also like to ONLY generate the chart if the row is clicked, as opposed to loading the chart always and hide() show() with jquery.
I've thought about an ajax call, but unsure about how to return an image, or how to open a new page.
Can't see a way to pass a complex model in the Url.Action() method.
Think caching may be the best option, and have the click method call "old fashioned" javascript for a new window, passing over the parameters to get the object from cache?
You have many ways to do that, but here is what I would do.
1/ Create an action which returns a tag with the good src (assuming that your controller's name is ChartsController).
public ActionResult GetImage(int chartId = 0)
{
var image = #"<img id='chart' src='" + Url.Action("GetChart", new {controller = "Charts", chartId = chartId}) + #"'/>";
return this.Content(image);
}
2/ I assume that, in your view, you have a div somewhere which contains your modal's content (like jQuery-ui would do) with an img inside, for the chart.
<div id="modal-div">
<div id="chart-div"></div>
</div>
3/ For every row, you have to create an Ajax link who will call your "GetImage" action and replace "chart-div" with your . You can specify a "OnBegin" Javascript function, this is where you will put your code to launch the modal.
#Ajax.ActionLink("Show me the chart!", "GetImage", "User", new { chartId = #Model.Rows[i]}, new AjaxOptions()
{
HttpMethod="GET",
OnBegin = "showModalWindow",
UpdateTargetId="modal-div",
InsertionMode = InsertionMode.Replace
});
Everytime you will click on an Ajax link, the modal will be launched and the inside will be replaced (in fact, all the content of the modal will be replaced).
Don't forget to include "Scripts/jquery.unobtrusive-ajax.js" and "Scripts/jquery.validate.unobtrusive.js" for the Ajax links to work.
You have some difference question mixed in one. You should split them each in one question. For your question's title, -loading an image by AJAX- you can use code-snippet below:
HTML:
<div id="chartholder"></div>
<a id="showchart">Show the chart</a> <!-- or any element else you want to fire show event -->
JS:
$(document).ready(function(){
$("#showchart").click(function(){
// Put your controller and action (and id if presented) below:
var file = "/YourControllerToGetChart/GetChart/id"
$("<img />").attr("src", file).load(function () {
$(this) // the loaded image
.css({"some-css-you-want":"some-value"})
.appendTo($("#chartholder")); // fixed syntax
});
});
});
Let me know if you have any questions or need clarifications on any part or you want to know how to css the div id="chartholder" to display it as an modal. Cheers.