asp.net IScriptControl $create order - javascript

I have two script controls (code is very simplified):
class Form : IScriptControl
{
Panel pnl;
Button trigger;
public Form()
{
pnl = new Panel();
trigger = new Button();
IPresenter p = new Popup();
p.SetContent(this.pnl);
this.Controls.Add(trigger);
}
}
class Popup : IScriptControl, IPresenter
{
public void SetContent(Control content)
{
this.Controls.Add(content);
}
}
Now in the HTML output, i see the following (again very simplified):
<div id="ctrlForm">
<div id="ctrlPopup">
<div id="ctrlFormPnl"></div>
</div>
<div id="ctrlFormTrigger"></div>
</div>
And script:
Sys.Application.add_init(function() {
$create(Form, {"_presenter":"FormPresenter"}, null, null, $get("ctrlForm"));
});
Sys.Application.add_init(function() {
$create(Popup, {"_isOpen":false}, null, null, $get("ctrlPopup"));
});
Question: How I can do, that the script that creates the popup appears on page before script of form...in other words, when initializer of the ctrlForm control executes, I want to get reference to forms presenter.
I hope I clearly explained what I want to do. Thanks.

In order to archive you goal you should let the child controls to register with ScriptManager before your control.
This can be done if you register your control with ScriptManager inside overridden Render method, after calling base.Render(...)
like that:
protected override void Render(HtmlTextWriter writer)
{
// Let child controls to register with ScriptManager
base.Render(writer);
// Now, when all the nested controls have been registered with ScriptManager
// We register our control.
// This way $create statement for this control will be rendered
// AFTER the child controls' $create
if (this.DesignMode == false)
{
ScriptManager sm = ScriptManager.GetCurrent(this.Page);
if (sm != null)
sm.RegisterScriptDescriptors(this);
}
}

Related

Call a codebehind function from a javascript method

I am trying to call a codebehind function with javascript. I need to make some operations with my gridview.
Here is my javascript:
function hideColumn() {
var gridrows = $("#GridViewHdcvi tbody tr");
AddTeklif.RemoveTextBoxes();
for (var i = 0; i < gridrows.length; i++) {
gridrows[i].cells[5].style.display = "none";
}
return false;
};
And my codebehind:
[WebMethod]
public static void RemoveTextBoxes()
{
foreach (GridViewRow row in GridViewHdcvi.Rows)
{
TextBox txb = (TextBox)row.FindControl("txtAdet");
string adet = txb.Text;
txb.Visible = false;
Label lbl = (Label)row.FindControl("LblAdet");
lbl.Text = adet+" $";
}
}
I have an error like 'An object reference is required for the non-static field,method, or property CRM.AddTeklif.GridViewHdcvi' in 'GridViewHdcvi.Rows'. When I make method's name 'public void RemoveTextBoxes()' error gone but method doesn't working since it is not static.
It seems that you are mixing two different concepts. JavaScript is run from the browser and will not have any access to your server code. What you are doing here is attempting to call a WebMethod when your page is Rendered to be sent to the browser.
A better approach would be to convert your RemoveTextBoxes method to jQuery as what you are wanting to do is modify the DOM.
This is how you would call your JavaScript function hideColumn() from a code behind.
Put this in the method where you want to call your javascript function.
Page.ClientScript.RegisterStartupScript(this.GetType(), "hideColumn", "hideColumn(;", true);
To call a codebehind from a javascript function you have to play some tricks.
1.) create a hidden button control. You have to hide it within the CssClass
<asp:Button ID="hdnButton" runat="server" CssClass="hidden" />
.hidden {
display: none;
}
2.) Create a click hdnButton method in your code behind
3.) Call the hidden button click event from your javascript
function CallCodeBehind() {
document.getElementById('<%= hdnButton.ClientID%>').click();
}

Why does WebForms keep rendering this data- attribute?

WebForms keeps re-rendering a TextBox control with a data- attribute in spite of my code removing it on PostBack-- which I shouldn't have to do in the first place, since the PostBack process clears attributes. I've tried clearing the attributes in OnInit and OnUnload, but they somehow reappear after leaving code-behind. They only ever reset through the TextChanged event.
I'm going crazy trying to figure out if I have a cache setting somewhere in my web.config that would prevent ASP.NET from properly removing this attribute.
For reference, the (as far as I can determine) relevant sections of my code:
.aspx JavaScript:
$("[data-confirm]").each(function () {
var alertText = $(this).attr("<%= _data_confirm %>");
$(alertText).dialog({
modal: true,
draggable: false,
resizable: false,
closeOnEscape: false,
title: "Note",
width: 330,
buttons: {
"Continue with Application": function () {
$(this).dialog("close");
}
}
});
});
.aspx.cs C#:
protected override void OnInit(EventArgs e)
{
if (Page.IsPostBack)
{
ClearIraDistributionConfirmation();
}
iraDistribution.TextChanged += iraDistribution_TextChanged;
}
void iraDistribution_TextChanged(object sender, EventArgs e)
{
if (SessionFormData.ConfirmedIraDistribution == false
&& SessionFormData.IraDistribution.HasValue
&& SessionFormData.IraDistribution.Value > 0)
{
iraDistribution.Attributes[_data_confirm] =
"<div>You must submit a copy of the first page of your 2014 federal tax return to verify the rollover amount.</div>";
iraDistribution.Attributes[_aria_live] = "assertive";
SessionFormData.ConfirmedIraDistribution = true;
}
else if (SessionFormData.ConfirmedIraDistribution)
{
ClearIraDistributionConfirmation();
}
}
private void ClearIraDistributionConfirmation()
{
if (SessionFormData.ConfirmedIraDistribution)
{
iraDistribution.Attributes.Clear();
}
}
I've verified that at the end of the PostBack cycle, iraDistribution has no attributes set. As soon as my .aspx JS hits the very first line of JavaScript -- which is way before the JS I pasted here -- iraDistribution has its data-confirm attribute set.
What am I missing?
The answer to this question is: The Page Life Cycle.
I made the mistake of trying to check for TextBox values in OnInit when they weren't yet available. OnUnload didn't work either because the values had already been rendered to output at that point.
I've fixed this bug by reordering the code above and moving it into the OnLoadComplete event. My code now looks like (well -- not quite like this, but it's abbreviated to remove code that interacts with the Session, functions I defined to improve readability, etc.):
protected override void OnLoadComplete(EventArgs e)
{
base.OnLoadComplete(e);
if (SessionFormData.ConfirmedIraDistribution)
{
iraDistribution.Attributes.Clear();
}
else if (SessionFormData.ConfirmedIraDistribution == false
&& SessionFormData.IraDistribution.HasValue
&& SessionFormData.IraDistribution.Value > 0)
{
iraDistribution.Attributes[_data_confirm] =
"<div>You must submit a copy of the first page of your 2014 federal tax return to verify the rollover amount.</div>";
iraDistribution.Attributes[_aria_live] = "assertive";
SessionFormData.ConfirmedIraDistribution = true;
}
}
The moral of this story: The Page Life Cycle will eat your lunch.

jQuery UI won't load properly with GWT

I don't work much with javascript, but I'm trying to get dragging working with the Modal boxes from the GWT Bootstrap project. So I have a GWT project, I have an entrypoint module. I add a Modal dialog box to the document and give it a title. Then I try to call the draggable method from the jQuery UI framework on that widget. Since it's just a div, everything should work.
My first problem was that the stuff in the <script> tags was getting run before the element ever got added to the DOM. So I moved it into the notifyHostPage() function and hoped to call it from there. But jQuery UI seems to unload itself from the page after it exits the tag the first time. I've included the code to show what I've tried, and the output it results in. This is really crazy.
I've tried moving the <scripts> to below the nocache.js file, I've tried just putting them in the gwt.xml, but because of super dev mode or whatever it won't let me. I've tried using document.write() to add the scripts inside the notifyHostPage() function. I've tried just adding the class ui-draggable to the modal dialog, but because jQuery UI disappears that doesn't work either. I've tried using local resources and a CDN. I'm kind of at my wits end.
module.html
<script type="text/javascript" language="javascript" src="module/js/jquery-1.11.0.min.js"></script>
<script type="text/javascript" language="javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.js"></script>
<script type="text/javascript" language="javascript" src="module/module.nocache.js"></script>
<script type="text/javascript">
$(function() {
if (jQuery.ui) {
// UI loaded
console.log("yes");
console.log(jQuery.ui);
} else {
console.log("no");
}
});
function startDragging() {
if (jQuery.ui) {
// UI loaded
console.log("yes");
console.log(jQuery.ui);
} else {
console.log("no");
}
$("#myModal").draggable({
handle: ".modal-header"
});
};
</script>
Entrypoint module
public native void notifyHostPage() /*-{
if ($wnd.jQuery.ui) {
// UI loaded
console.log("yes");
console.log(jQuery.ui);
} else {
console.log("no");
}
$wnd.startDragging();
}-*/;
Output
yes
Object
accordion: function ( options, element ) {
autocomplete: function ( options, element ) {
button: function ( options, element ) {
buttonset: function ( options, element ) {
datepicker: Object
ddmanager: Object
dialog: function ( options, element ) {
draggable: function ( options, element ) {
droppable: function ( options, element ) {
hasScroll: function ( el, a ) {
ie: false
intersect: function (draggable, droppable, toleranceMode) {
keyCode: Object
menu: function ( options, element ) {
mouse: function ( options, element ) {
plugin: Object
position: Object
progressbar: function ( options, element ) {
resizable: function ( options, element ) {
selectable: function ( options, element ) {
slider: function ( options, element ) {
sortable: function ( options, element ) {
spinner: function ( options, element ) {
tabs: function ( options, element ) {
tooltip: function ( options, element ) {
version: "1.10.1"
__proto__: Object
no
no
Final Solution:
I've updated my files as so:
entrypoint.java
public class RecondoHISModern implements EntryPoint {
final RecondoHISServletInterfaceAsync recondoHIS = GWT.create(RecondoHISServletInterface.class);
public void onModuleLoad() {
loadScripts();
}
private void loadScripts() {
// ScriptInjector.fromString("public/js/jquery-ui-1.10.4.custom.min.js").inject();
// ScriptInjector.fromString("public/js/nprogress.js").inject();
List<String> scripts = Arrays.asList( //"//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.js",
"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js",
"//cdnjs.cloudflare.com/ajax/libs/nprogress/0.1.2/nprogress.min.js");
injectScriptsInOrder(scripts);
}
private void injectScriptsInOrder(final List<String> scripts) {
if (scripts.size() > 0) {
ScriptInjector.fromUrl(scripts.get(0))
.setRemoveTag(false)
.setWindow(ScriptInjector.TOP_WINDOW)
.setCallback(new Callback<Void, Exception>() {
#Override
public void onFailure(Exception reason) {
GWT.log("The script " + scripts.get(0) + " did not install correctly");
}
#Override
public void onSuccess(Void result) {
GWT.log("The script " + scripts.get(0) + " installed correctly");
injectScriptsInOrder(scripts.subList(1, scripts.size()));
}
}).inject();
} else {
createModal();
}
}
public void createModal() {
Modal modal = new Modal();
modal.setTitle("Java Created Modal");
modal.setClosable(true);
ModalBody modalBody = new ModalBody();
modalBody.add(new Span("Create in Java Code!"));
ModalFooter modalFooter = new ModalFooter();
modal.add(modalBody);
modal.add(modalFooter);
modal.setId("myModal");
modal.show();
draggable();
}
private native void draggable() /*-{
$wnd.jQuery("#myModal").draggable({
handle: ".modal-header"
});
}-*/;
}
At first it was crashing at this function in modal.show();
private native void modal(final Element e, final String arg) /*-{
$wnd.jQuery(e).modal(arg);
}-*/;
But then I realized that maybe I shouldn't be loading jQuery twice, so I removed jQuery from the ScriptInjector list and everything started working fine!
You shouldn't load JS dependencies via <script> tags in your HTML file.
Either specify them in your module .gwt.xml file via <script> or better use ScriptInjector for compatibility with SuperDevMode.
Create an EntryPoint for your module and inject the JS dependencies there. See how we did it in our GwtBootstrap3 project. Since you're using GwtBootstrap3 you don't need to inject jQuery. This will already be done by GwtBootstrap3. Just inject jQuery UI and make sure to specify your <entry-point> after all <inherits>.
Once this is resolved you should be able to run something like this from your presenter:
private native void draggable() /*-{
var $modal = $wnd.jQuery("#myModal");
$modal.draggable(...);
}-*/;

Custom button override in Salesforce

I want to create a custom button override in Salesforce. I'd like to override the delete button so that instead of deleting, I just want it to change the record type.
My custom object is Absence__c
Try this:
You only have to edit the Page Layout, remove the "delete" button,
Then create a custom button named "delete", set the javascript to button's behavior. Finally add that button to the page layout.
This is an example code for the custom button:
{!REQUIRESCRIPT("/soap/ajax/15.0/connection.js")}
var AbsenceUpdate = new sforce.SObject("Absence__c");
AbsenceUpdate.Id='{! Absence__c.Id }';
AbsenceUpdate.RecordTypeId = '{new record type id}';
if(AbsenceUpdate!=null)
{
try
{
updateOpp = sforce.connection.update([AbsenceUpdate]);
window.location.reload();
}
catch(e)
{
alert('error : ' + e);
}
}
I think your best bet is a controller extension and an override of the existing Delete button.
<apex:Page action="changeRTRedirect"
standardController="Absence__c" extensions="DeleteOverrideExtension">
</apex:page>
public class DeleteOverrideExtension {
private SObject record;
public DeleteOverrideExtension(ApexPages.StandardController controller) {
record = controller.getRecord();
}
public PageReference changeRTRedirect() {
record.RecordTypeId = '[YOUR NEW RT ID]';
update record;
//where do you want to send users now, maybe the Absence__c tab?
return Page.MyPageHere;
}
}

how to retrieve property value in js file?

I am creating one asp page. In that page i defined one property like below
.cs
private long _sequence;
public long Sequence { get { return _sequence; } set { _sequence = value; } }
Now i want to retrieve this property value in js file. Actually i can retrieve it in .aspx but i want it in .js file.
here is my js function and .aspx code which i am trying but it could not find property value
.aspx
<asp:Button ID="btnShowSimple" runat="server" Text="Notes Dialog" OnClientClick="NotesDialog(this)" />
.js
function NotesDialog(ctr) {
var ControlName = document.getElementById(ctr.id);
$("#btnShowSimple").click(function (e) {
ShowDialog(false);
e.preventDefault();
LoadData("GetNotes", '"sequence":<%= this.Sequence %>');
});
}
Anything I am missing?? If anyone have any idea about it than please help me..I am facing this problem since two days..
Your js files are static files on the server. You cannot use those <%= %> tags in them.
You could pass the property via a global javascript variable, that you set in your aspx page and use in your js file.
i.e.
.aspx
<script type="text/javascript">
myProp = <%= this.Sequence %>;
</script>
.js
function NotesDialog(ctr) {
var ControlName = document.getElementById(ctr.id);
$("#btnShowSimple").click(function (e) {
ShowDialog(false);
e.preventDefault();
LoadData("GetNotes", '"sequence":' + myProp);
});
}
Nope you cannot do this in JS file as it is not processed by asp.net runtime. The best you can do is declare a variable in aspx and use it in js like:
aspx:
var _seq="<%= this.Sequence %>";
JS:
LoadData("GetNotes", '"sequence":' + _seq); //USE ASPX VARIABLE
You should try to separate you JavaScript code from you HTML.
Instead och creating a asp:Button use an HTML button and set an data-attribute you can retrive.
<button type="button" id="btnShowSimple" data-sequence="<%= this.Sequence %>">Notes Dialog</button>
And in your javascript-file bind an click event to your button that picks up the data-sequence.
/** Put this in the bottom of you javascript file **/
(function (window) {
var document = window.document,
view;
view = {
/**
* Invoked in jQuery event context
* #param e
*/
bindClickEvent : function (e) {
$("#btnShowSimple").click(function (e) {
e.preventDefault();
var sequence = $(this).data('sequence');
ShowDialog(false);
LoadData("GetNotes", '"sequence":' + sequence);
});
}
}
$(document).ready(view.bindClickEvent);
} (window));
From your current code you when you click the asp:Button you just bind a new click event and never execute it.
Also from some of the other answer, you should NEVER declare arbitrary global variables in JavaScript

Categories

Resources