how do I capture the submit event in this particular scenario( I am using Kohana):?
controller function (swo/test):
echo "Form succesfully submitted.<br/>";
$min = $_POST['price1'];
$max = $_POST['price2'];
echo "Minimum Value:" . $min . "<br/>";
echo "Maximum Value:" . $max;
$q = new Swo_Model;
$result = $q->searchRange($min, $max);
echo Kohana::debug($result);
$view= new View('template');
$view->slider = new View('slider');
$view->content = new View('advsearch');
$view->content->list = $result;
$view->render(TRUE);
HERE IS MY JQUERY SCRIPT
$(document).ready(function()
{
$('#slider').slider({
min:0,
steps: 50,
max:300,
range: true,
change: function(e,ui){
$("#min").text("$" + ui.values[0]);
$("#max").text("$" + ui.values[1]);
$("input[name='price1']").val(ui.values[0]);
$("input[name='price2']").val(ui.values[1]);
$("#advance").trigger("submit");
}
});
});
I have a slider. I slide it to a particular value, then trigger a form submit via jquery. What I want to do is load the output of the testSubmit function to a specific region in my page, without the slider being refreshed. I tried to do it with the submit(function(){}) already but to no avail.
You need to prevent the event from bubbling up - what is happening is that your function is running, and then the form is still submitting.
A quick solution is
<form ... onsubmit="return myfunction()">
And in myFunction, return false, which will stop the submit being posted. You could even trap errors in your jquery and return true to cause the proper submit if something goes wrong, which means graceful deprecation if there's a problem.
Related
I've got 3 separate files.
Forms (a basic wordpress page built within Wordpress). The data here shows up fine and works as expected.
<div class="select-wrapper">
<select class="paybill" name="provider-name" id="provider-name" onchange="formFilter(this.value)">
<option value="" disabled selected hidden>- Choose a Provider -</option>
<?php foreach( $providerslist as $providerlist ) {
$theprovidernname = get_the_title($providerlist);
$providerlocations = get_field('provider_locations', $providerlist);
$pcount = count($providerlocations);
for($i = 0; $i < $pcount; $i++){
$location_name = get_field_object('location_name', $providerlocations[$i]);
if(!empty($location_name)){
break;
}
}
if(empty($location_name)){
$location_name = array(value=>"TEXT");
}?>
<option value="<?php echo $location_name['value']?>"><?php echo $theprovidernname; ?></option>
<?php } ?>
</select>
</div>
A filtering Javascript file. The purpose of this file is to get the data from the select field and pass it using AJAX to the 3rd PHP file.
function formFilter(str){
//clears previous results
document.getElementById("form-results").innerHTML = "";
var value = str.value;
console.log(value);
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
var xmlhttp = new XMLHttpRequest();
} else {// code for IE6, IE5
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("form-results").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET",".../framework-forms-results.php?location="+value,true);
xmlhttp.send();
}
A custom PHP file living in the Child Theme folder of the site. What I'm trying to do is call a custom post type called 'location' and then work through the data. On other pages I'm able to get this exact code to work just fine but here it will not work at all. This is the entirety of this Page at the moment. If I remove the get_posts code and just echo some text, it will return the text so I know the issue is with the get_posts call. I just can't figure out why. If I try to load this page alone without going through the select options, it still returns a 500 error.
//Create Array of All Locations
$locations = get_posts(array(
'posts_per_page' => -1,
'post_type' => 'location',
));
print "<pre>";
print_r($locations);
print "</pre>";
Any thoughts as to why the get_posts call won't work on this custom page but will work if it's used via shortcodes on pages built within wordpress?
I've tried debugging, logging errors and reviewing the logs. I've tried to require the blog header to bring in other necessary files but nothing.
If you are calling this URL directly, which is not how WordPress ajax is intended to work, you can still get this code to run by adding this PHP code:
$parse_uri = explode( 'wp-content', $_SERVER['SCRIPT_FILENAME'] );
require_once( $parse_uri[0] . 'wp-load.php' ); to the top of the file.
Link: https://codex.wordpress.org/AJAX_in_Plugins (I know this says Ajax in plugins but this is also what you would do if developing a custom theme to keep your code WordPress-y).
I added custom field into config.xml. I want to save value of my custom field into other table, not the #__extensions table. How can I do it for extension options page.
The "short" answer is that you'd have to create your own custom JFormField class to handle this. I then have some Javascript making an AJAX call when the value changes.
Here's my example (edited from a similar exercise I did a while back):
Step 1: Create a JFormField class somewhere (I'm putting mine in /libraries/test/mycontrol.php for now):
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport('joomla.html.html');
jimport('joomla.form.formfield');//import the necessary class definition for formfield
class JFormFieldMyControl extends JFormField
{
protected function getInput()
{
$document = JFactory::getDocument();
$document->addScript(JURI::base() . '../libraries/test/config_test.js');
# This is a hidden control, because Joomla needs to save a value against any field in a config's xml
$control = '<input type="hidden" id="' . $this->id . '" name="' . $this->name . '">';
# Now let's create a textbox which will be the thing that actually saves to the DB via Javascript
$control .= '<input type="text" id="your_test_input" name="your_test_input" value="' . $this->value . '" />';
return $control;
}
}
Step 2: Create the JS file referenced in the above code snippet (so, in /libraries/test/config_test.js). This will trigger an AJAX call to another PHP file, savefieldvalue.php, when your textbox's value changes.
window.addEvent('domready', function() {
// Filter the validator dropdown
var jcategory = document.id('your_test_input');
jcategory.addEvent('change',function(event) {
saveFieldValue(this.get('value'));
});
});
function saveFieldValue(value)
{
var req = new Request({
url:'libraries/test/savefieldvalue.php',
method:'post',
autoCancel:true,
data:'save_value=' + value,
onRequest: function() {
},
onSuccess: function(s) {
alert('saved ok!');
}
}).send();
}
Step 3: The savefieldvalue.php file, which handles the AJAX request and saves the thing.
<?php
# Bootstrap
define('DS', DIRECTORY_SEPARATOR);
if (file_exists(dirname(__FILE__) . '/defines.php')) {
include_once dirname(__FILE__) . '/defines.php';
}
if (!defined('_JDEFINES')) {
define('JPATH_BASE', dirname(__FILE__) . '/../..'); # note, you may need to fiddle with these by adding or removing "../"'s until you get the depth right
require_once JPATH_BASE . '/includes/defines.php';
}
require_once JPATH_BASE.'/includes/framework.php';
// Instantiate the application.
$app = JFactory::getApplication('site');
// Initialise the application.
$app->initialise();
# ======================
$db = JFactory::getDbo();
$value = $_POST['save_value'];
# and then put your normal Joomla save code here
Step 4: Now introduce your new JFormField to your config XML, like so:
<fieldset name="test" label="Test Control" addfieldpath="/libraries/test/">
<field name="test-field" id="test-field" type="MyControl" label="My Custom Control" />
</fieldset>
Note how you use addfieldpath to indicate to Joomla where your custom JFormField lies, and then set the type of your field name to your control.
It's a bit convoluted, and you can adjust it to do all this on postback rather than on change, but I've found it works well for me. I'm using 2.5, so the bootstrap bit in savefieldvalue.php may need to reflect your normal /index.php.
Good luck!
In a ZF2 project I am developing, I would like to create a shell around the echo $this->content; statement in layout.phtml that would allow conditional formatting of the main content area. Specifically, I want to put the content into a column that is 75% wide and include some “ornamental” elements in a column that is 25% wide for most of the pages. However, I want to change to a single column for pages that need more space. My project is a CMS in which each page has an attribute that can tell either the view or the controller whether the page should be normal or wide. I have considered a number of methods for achieving what I’m after.
My “conditional formatting in the layout view” might look like this:
// module/Application/view/layout/layout.phtml:
//...
if ($templateNormal) {
echo "<div class='col-md-9'>";
} else {
echo "<div class='col-md-12'>";
}
echo $this->content;
if ($templateNormal) {
echo "</div>";
echo "<div class='col-md-3'>";
//... ornamentation
echo "</div>";
} else {
echo "</div>";
}
//...
While the above-method could work, for pure MVC I don’t think there is supposed to be any decision-making going on in the layout view.
My “conditional formatting in partial views” could look like this:
// module/Application/view/layout/layout.phtml:
//...
echo $this->partial('partial/open-shell.phtml');
echo $this->content;
echo $this->partial('partial/close-shell.phtml');
//...
// module/Application/view/partial/open-shell.phtml:
if ($templateNormal) {
echo "<div class='col-md-9'>";
} else {
echo "<div class='col-md-12'>";
}
// module/Application/view/partial/close-shell.phtml:
if ($templateNormal) {
echo "</div>";
echo "<div class='col-md-3'>";
//... ornamentation
echo "</div>";
} else {
echo "</div>";
}
Here the decision-making is taken out of the layout view, but it is simply put into other views so it's still in the view package and still not pure MVC.
In my “conditional formatting in the controller” solution, a pair of html script strings are developed in a controller function, and then passed on to the view. It might look like this:
// module/Application/view/layout/layout.phtml:
//...
echo $this->open-shell-script';
echo $this->content;
echo $this->close-shell-script';
//...
// some controller function:
//...
if ($templateNormal) {
$open-shell-script = "<div class='col-md-9'>";
$close-shell-script = "</div>";
$close-shell-script = "<div class='col-md-3'>";
$close-shell-script .= //... ornamentation
$close-shell-script .= "</div>";
} else {
$open-shell-script = "<div class='col-md-12'>";
$close-shell-script = "</div>";
}
//...
In this method, the decision-making is done in the controller where I assume it should be, but it seems odd to be writing html there.
Any comments or suggestions?
create two layout and in init() method of Module.php decide which layout should use .
public function init(ModuleManager $moduleManager) {
$sharedEvents = $moduleManager->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
// This event will only be fired when an ActionController under the MyModule namespace is dispatched.
$controller = $e->getTarget();
$controller->layout(" your chose layout ");
}
}
There are many ways to accomplish this. This is one method and the logic lives in the controller:
controller
public function yourSampleAction()
{
// assign variables as usual to this view model
$viewModel = new ViewModel(array(
//vars
);
// this will be the "wrapper" and can be single, double column or anything else.
$wrapperViewModel = new ViewModel();
$wrapperViewModel->addChild($viewModel, 'innerContent');
// use this line when you want one column
$wrapperViewModel->setTemplate('path/to/your/single-column-wrapper.phtml');
// when this line you want two columns
$wrapperViewModel->setTemplate('path/to/your/two-column-wrapper.phtml');
return $wrapperViewModel;
}
two-column-wrapper.phtml
<div class='col-md-9'>
<?php echo $innerConntent; ?>
</div>
<div class='col-md-3'>
<!--- something else in here? -->
</div>
single-column-wrapper.phtml
<div class='col-md-12'>
<?php echo $innerConntent; ?>
</div>
Instead of setting different templates, you can adjust the Bootstrap Twitter classes by making the necessary classes dependent on a layout variable. You can use the logic in your controllers action to pass variables directly to the layout (not the view) like so:
$this->layout()->setVariables
(
array
(
'layoutVar1' => 75,
'someColClass' => ($someSwitch ? 'col-md-9':'col-md-12' ),
'layoutVar1' => 75,
)
);
and then just access these variables in the Layout as you would variables sent to the View. You don't have to even prepend them with "layout", they won't clash.
<t:panelTab label="Detailed View" styleClass="tabFont" rendered="true" id="DetailedView">
<t:dataTable value="#{MyFinanceBB.amendDataList}" id="DetailedViewGrid" forceId="true"
var="myVo" rowIndexVar="gridExpRowNo"......>
...............
<t:inputText value="#{myVo.myval}" styleClass="BodyFont" forceId="true" id="myId2"
onchange="getTotalMyValAjax('myId2[#{gridExpRowNo}]',#{gridExpRowNo});">
/----------------------------------------------------------------/
function getMyAmountTotalGrid(myidVar,count){
var myAmt=document.getElementById(myidVar).value;
var id = 'myForm\\:targetView';
$j.ajax({
async:"false",
cache:"false",
type: "POST",
url:"/myProj/myController",
data:{myAmt:myAmt,count:count},
error:function(){
alert('Error Occurred.Please try later');
},
success:function(output){
alert('SUCCESS');
$j('#'+id).load("/pagesmyProj/Home/dingDongHome.jsf");
alert('after reloading grid');
}
});
}
when i execute the code alert message SUCCESS is getting printed and all the server side variables are getting updated.(I came to know this by sysouts). But nothing is really getting changed in the webpage. The alert message "after relaoding grid" is also getting printed. But the grid is not getting reloaded. The server side changes are not getting reflected in the browser.
For start you should add \\ to your id
instead of var id = 'myForm:targetView';
write var id = 'myForm\\:targetView'; otherwise jquery selector by id wont work (you need to escape the :)
You are referencing
$j('#'+id)...
just remove the "j", ex. $('#'+id)...
After a long struggle,I got the error.The url given to the jquery load function is not proper and it should be changed.
I have a page hosted in 'virtualcasa1' domain opening a modal dialog:
var options = {
title: "Repro",
width: 400,
height: 600,
url: http://domain2:999/sites/blank/_layouts/XDomainTest/XDomainTestTarget.aspx //[1]
//url: http://virtualcasa1/sites/blank/_layouts/XDomainTest/XDomainTestTarget.aspx [2]
};
SP.UI.ModalDialog.showModalDialog(options);
And I have this code to close it:
alert(document.domain);
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancelled clicked');
If both are in the same domain (case [2] above), the dialog closes well, no issues.
But - if target page hosted in the dialog (case [1] above), dialog does NOT close :-(
document.domain above shows the correct domain where page exists.
I suspect I'm facing a cross-domain issue here (duh), but how to fix it? Or am I wrong and issue is not XDomain-related?
Thanks much!
HTML5's postMessage is your answer.
https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage
Your parent window that initiates the dialog must have the following javascript:
function listener(event) {
//alert(event.data);
if (event.data == 'Cancel') {
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancel clicked');
}
else {
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, event.data);
}
}
if (window.addEventListener) {
addEventListener("message", listener, false)
} else {
attachEvent("onmessage", listener)
}
Javascript for OK and Cancel buttons in your popup:
<input type="button" value="OK" onclick="parent.postMessage('Message to be displayed by the parent', '*');" class="ms-ButtonHeightWidth" />
<input type="button" value="Cancel" onclick="parent.postMessage('Cancel', '*');" class="ms-ButtonHeightWidth" />
Ajay's answer from the 1st of August 2014 is good, but it needs a bit more explanation. The reason for the failure to close the dialog is simple. Cross site scripting security features of modern browsers disallow a few things, one of which is the use of window.frameElement from within the framed window. This is a read-only property on the window object and it becomes set to null (or with IE, it actually throws an exception when you try to access it). The ordinary Cancel event handlers in the modal dialog conclude with a call to window.frameElement.cancelPopup(). This will fail of course. The ordinary Save handler where the Save worked on the server side results in SharePoint sending back a single line as the replacement document, which is a scriptlet to call window.frameElement.commitPopup(). This also will not work, and it's a real pain to overcome because the page has been reloaded and there is no script available to handle anything. XSS won't give us access to the framed DOM from the calling page.
In order to make a cross domain hosted form work seamlessly, you need to add script to both the page that opens the dialog and the framed page. In the page that opens the dialog, you set the message listener as suggested by Ajay. In the framed form page, you need something like below:
(function() {
$(document).ready(function() {
var frameElement = null;
// Try/catch to overcome IE Access Denied exception on window.frameElement
try {
frameElement = window.frameElement;
} catch (Exception) {}
// Determine that the page is hosted in a dialog from a different domain
if (window.parent && !frameElement) {
// Set the correct height for #s4-workspace
var frameHeight = $(window).height();
var ribbonHeight = $('#s4-ribbonrow').height();
$('#s4-workspace').height(frameHeight - ribbonHeight);
// Finds the Save and Cancel buttons and hijacks the onclick
function applyClickHandlers(theDocument) {
$(theDocument).find('input[value="Cancel"]').removeAttr('onclick').on('click', doTheClose);
$(theDocument).find('a[id="Ribbon.ListForm.Edit.Commit.Cancel-Large"]').removeAttr('onclick').removeAttr('href').on('click', doTheClose);
$(theDocument).find('input[value="Save"]').removeAttr('onclick').on('click', doTheCommit);
$(theDocument).find('a[id="Ribbon.ListForm.Edit.Commit.Publish-Large"]').removeAttr('onclick').removeAttr('href').on('click', doTheCommit);
}
// Function to perform onclick for Cancel
function doTheClose(evt) {
evt.preventDefault();
parent.postMessage('Cancel', '*');
}
// Function to perform onclick for Save
function doTheCommit(evt) {
evt.preventDefault();
if (!PreSaveItem()) return false;
var targetName = $('input[value="Save"]').attr('name');
var oldOnSubmit = WebForm_OnSubmit;
WebForm_OnSubmit = function() {
var retVal = oldOnSubmit.call(this);
if (retVal) {
var theForm = $('#aspnetForm');
// not sure whether following line is needed,
// but doesn't hurt
$('#__EVENTTARGET').val(targetName);
var formData = new FormData(theForm[0]);
$.ajax(
{
url: theForm.attr('action'),
data: formData,
cache: false,
contentType: false,
processData: false,
method: 'POST',
type: 'POST', // For jQuery < 1.9
success: function(data, status, transport) {
console.log(arguments);
// hijack the response if it's just script to
// commit the popup (which will break)
if (data.startsWith('<script') &&
data.indexOf('.commitPopup()') > -1)
{
parent.postMessage('OK', '*');
return;
}
// popup not being committed, so actually
// submit the form and replace the page.
theForm.submit();
}
}).fail(function() {
console.log('Ajax post failed.');
console.log(arguments);
});
}
return false;
}
WebForm_DoPostBackWithOptions(
new WebForm_PostBackOptions(targetName,
"",
true,
"",
"",
false,
true)
);
WebForm_OnSubmit = oldOnSubmit;
}
applyClickHandlers(document);
}
});
})();
This solution makes use of the jQuery library, which our organization uses extensively. It is our preferred framework (chosen by me). I'm sure someone very clever could rewrite this without that dependency, but this is a good starting point. I hope someone finds it useful, as it represents a good two days work. Some things to note:
SharePoint does a postback on all sorts of events on the page, including putting the page into edit mode. Because of this, it makes more sense to trap the specific button clicks, both on the form and in the ribbon, rather than wholesale redefinition of, for example, the global WebForm_OnSubmit function. We briefly override that on a Save click and then set it back.
On any Save click event, we defeat the normal posting of the form and replace that with an identical POST request using AJAX. This allows us to discard the returned scriptlet when the form was successfully posted. When the form submission was not successful, perhaps because of blank required values, we just post the form properly to allow the page to be updated. This is fine, since the form will not have been processed. An earlier version of this solution took the resulting HTML document and replaced all of the page contents, but Internet Explorer doesn't like this.
The FormData api allows us to post the form as multipart-mime. This api has at least basic support in all modern browsers, and there are workarounds for older ones.
Another thing that seems to fail in the cross domain hosted dialog is the scrolling of the content window. For whatever reason, the height is not set correctly on the div with id s4-workspace, so we also set that in the solution.
EDIT:
Almost forgot. You may also need to add this control to your framed ASPX page, which can be done with SharePoint Designer:
<WebPartPages:AllowFraming runat="server"/>
I have exactly the same issue - a dialog opening a view page for an item works fine when opened from a site collection on the same web app/domain, but the Close button fails to work when opening the same item from a site collection hosted in a separate web application. I'm assuming it is a cross-domain thing so I've altered the solution to accomodate this restriction, however, I'm not 100% happy about it as it does make the overall solution a little awkward to use from a user-perspective. I've put the issue to one side for now due to project timescales, but I'm still curious as to why. The only things I can think of is the whole cross-domain thing causing it and that maybe it is there by design to prevent XSS security holes.