jQuery UI won't load properly with GWT - javascript

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(...);
}-*/;

Related

SignalR server to client method not working

Based on various resources the signalr code should be working, but I can't make it to send notifications from the server to client. Here is html/javascript part:
<script src="/Scripts/jquery-1.6.4.min.js"></script>
<script src="/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="/signalr/js"></script>
<script type="text/javascript">
$(function () {
var cHub = $.connection.cHub;
$.connection.hub.logging = true;
cHub.client.sendMessage = function (content) {
$("#container-hub").append($("<p />").html(content));
};
$.connection.hub.start().done(function() {
$('[id$=bGo]').click(
function() {
cHub.server.send('Sync process started');
});
});
});
</script>
<div id="container-hub" style="background: red; height: 100px; width: 100%;"></div>
Hub.cs class:
using Microsoft.AspNet.SignalR;
namespace CMS.Objects
{
public class CHub : Hub
{
public void Send(string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.sendMessage(message);
}
}
}
Startup.cs class:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(CMS.CStartup))]
namespace CMS
{
public class CStartup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
And here is how I am calling the method sendMessage method:
private void ShowMessage(string message)
{
var clients = GlobalHost.ConnectionManager.GetHubContext<CHub>().Clients;
clients.All.sendMessage(message);
}
When the button bGo is clicked the message is getting appended to the container-hub div, but nothing when I call sendMessage method.
EDIT
Some additional findings; when I call sendMessage from within the OnConnected method it works:
public override Task OnConnected()
{
Clients.All.sendMessage("Connection Initialised");
return base.OnConnected();
}
After spending some decent time to investigate the problem I have finally found the solution. Not 100% sure, but I think the problem was with using the UpdatePanel on the page. Wrapped signalR javascript code to Sys.Application.add_load instead of using jQuery's $(function () { and it started working.
The reason I mentioned that I am not 100% sure is that the UpdatePanel with the ScriptManager has been removed multiple times giving no results before posting the question.

prototype AJAX loading blank page onSuccess

I'm working on a magento project, and I'm trying to load more products on the click of the more button.
I can see them loading but then it will just load a blank page after it.
I have no idea what is happening or why.
This is the code I have
var loadMore = Class.create({
initialize: function (list, href, pattern) {
var that = this;
this.list = list;
this.list.insert({ after : '<div class="more"><span id="more_button" class="more-button">More</span></div>'});
this.href = href.readAttribute('href');
this.button = $('more_button');
this.holder = new Element('div', { 'class': 'response-holder' });
this.button.observe('click', function () {
if ( !that.button.hasClassName('loading') ) {
new Ajax.Request(that.href, {
onCreate: function () {
that.button.addClassName('loading');
},
onSuccess: function(response) {
if (200 == response.status) {
that.holder.update(response.responseText).select(pattern).each(function(elem) {
that.list.insert({ bottom : elem });
}),
that.href = that.holder.select('.next-page')[0].readAttribute('href');
that.button.removeClassName('loading');
if ( !that.href ) {
that.button.up().remove();
}
}
}
});
}
});
}
});
If anyone can help me out that would be awesome!
Thanks in advance.
I've having the same problem in my magento Iphone orginal theme, but the error is because of code injection, mostly "script" tags from google analytics, clicktale and similar stuff.
what i've done to fix it was to "parse" the ajax response and modify the opening "script" tag with the html entity:
below the line 117 (aprox in iphone.js)
if (200 == response.status) {
that.holder.update(response.responseText).select(pattern).each(function(elem) {
replace with this:
str = response.responseText;
str = str.replace(/<script/gi, '<script');
that.holder.update(str).select(pattern).each(function(elem) {
Might I suggest you rewrite your code and use thiz for that? Your code is extremely hard to read.
I do not see any reason to use the onCreate event of the Ajax Request, which by the way is reserved for Ajax Responders (per spec: http://prototypejs.org/doc/latest/ajax/Ajax/Request/)
Instead, you can add this classname at the moment you enter into !that.button.hasClassName('loading') ...
if ( !that.button.hasClassName('loading') ) {
that.button.addClassName('loading');
new Ajax.Request(that.href, {
....
There is a lot more going on behind the scene, like your CSS, magento of course, but also containing and parent html elements so it is very difficult to give any sound advice. What have you done in order to debug this?
Karl..

Calling jQuery plugin public function within plugin

I know, there are quite a few examples on the Web, but finding real one out of them all is tough for beginner. So I want to create jQuery plugin with public methods. Example code:
(function($) {
$.fn.peel = function(options) {
var defaults = {
};
var settings = $.extend({},defaults, options);
this.public = function() {
alert("public");
};
var private = function() {
alert("private");
}
return this.each(function() {
//this.public();
private();
});
};
})(jQuery);
As I found, this is the way to make public function, which could be called like this :
var peel = $('img').peel();
peel.public();
So far it works as expected - public() can be called. But what if i want to call that function within my plugin? I commented out in this.each() because it does not work. How can i achieve that?
One way to create publicly accessible methods within your plugins is to use the jQuery UI widget factory. This is the framework that jQuery UI uses for all of it's supported UI widgets. A quick example would look like this:
(function( $ ) {
$.widget( "something.mywidget", {
// Set up the widget
_create: function() {
},
publicFunction: function(){
//...
}
});
}( jQuery ) );
var $w = $('#someelement').mywidget();
$w.mywidget('publicFunction');

asp.net IScriptControl $create order

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);
}
}

asp.net ajaxtoolkit Custom control extender

Well im trying to write my own custom control extender but i can't get the javascript to work
Here you have a empty class:
Imports System.ComponentModel
Imports AjaxControlToolkit
Imports System.Web.UI
Imports System.Web.UI.WebControls
<Assembly: System.Web.UI.WebResource("GuiExtensions.PrintButtonBehavior.js", "text/javascript")>
<Designer(GetType(PrintButtonExtenderDesigner))>
<ClientScriptResource("Sys.Extended.UI.PrintButtonExtender", "GuiExtensions.PrintButtonBehavior.js")>
<TargetControlType(GetType(IButtonControl))> _
Public Class PrintButtonExtender
Inherits ExtenderControlBase
End Class
And here you have the javascript:
Type.registerNamespace('Sys.Extended.UI');
Sys.Extended.UI.PrintButtonExtender = function (element) {
Sys.Extended.UI.PrintButtonExtender.initializeBase(this, [element]);
}
Sys.Extended.UI.PrintButtonExtender.prototype = {
initialize: function () {
Sys.Extended.UI.PrintButtonExtender.callBaseMethod(this, 'initialize');
var element = this.get_element();
this._clickHandler = Function.createDelegate(this, this._onClick);
$addHandler(element, "click", this._clickHandler);
},
dispose: function () {
$removeHandler(this.get_element(), "click", this._clickHandler);
this._clickHandler = null;
Sys.Extended.UI.PrintButtonExtender.callBaseMethod(this, 'dispose');
},
_onClick: function () {
alert("Test");
return false;
}
}
Sys.Extended.UI.PrintButtonExtender.registerClass('Sys.Extended.UI.PrintButtonExtender', Sys.Extended.UI.BehaviorBase);
The problem here is that _onClick is never called when some one is clicking the button i assigned the extender to.. i have verified that "this.get_element();" returns the correct element but i have no luck getting the _onClick function to run.
So far i have hacked this together by looking at the source from codeplex but no success!
change the type this._onClick
this._clickHandler = Function.createDelegate(this, this._onClick);
to
this._clickHandler = Function.createDelegate(this, this._clickCallback);
hope this will get results :)

Categories

Resources