AJAX | Dmytro Shteflyuk's Home https://kpumuk.info In my blog I'll try to describe about interesting technologies, my discovery in IT and some useful things about programming. Tue, 08 Sep 2015 00:24:41 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Synchronous page method call in ASP.NET AJAX library https://kpumuk.info/asp-net/synchronous-page-method-call-in-asp-net-ajax-library/ https://kpumuk.info/asp-net/synchronous-page-method-call-in-asp-net-ajax-library/#comments Mon, 10 Sep 2007 21:15:28 +0000 http://kpumuk.info/asp-net/synchronous-page-method-call-in-asp-net-ajax-library/ Sometimes we need to do some tasks, that libraries developers even have not foreseen. One of such cases is to make synchronous AJAX call (Asynchronous JavaScript And XML). Below you could find quick solution. Please note: my solution is just copy/past of the XmlHttpExecutor code with two small changes: I have passed false as third […]

The post Synchronous page method call in ASP.NET AJAX library first appeared on Dmytro Shteflyuk's Home.]]>
Sometimes we need to do some tasks, that libraries developers even have not foreseen. One of such cases is to make synchronous AJAX call (Asynchronous JavaScript And XML). Below you could find quick solution.

Please note: my solution is just copy/past of the XmlHttpExecutor code with two small changes:

  • I have passed false as third parameter of the XMLHttpRequest.open method to make synchronous call.
  • I have cached request results in XMLHttpSyncExecutor members before freeing XMLHttpRequest in the _onReadyStateChange function.

So let’s get started. First of all we would define XMLHttpSyncExecutor class, descendant of the WebRequestExecutor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Type.registerNamespace('Sys.Net');

Sys.Net.XMLHttpSyncExecutor = function()
{
    if (arguments.length !== 0) throw Error.parameterCount();
    Sys.Net.XMLHttpSyncExecutor.initializeBase(this);

    var _this = this;
    this._xmlHttpRequest = null;
    this._webRequest = null;
    this._responseAvailable = false;
    this._timedOut = false;
    this._timer = null;
    this._aborted = false;
    this._started = false;

    this._responseData = null;
    this._statusCode = null;
    this._statusText = null;
    this._headers = null;

    this._onReadyStateChange = function () {
        if (_this._xmlHttpRequest.readyState === 4 ) {
            _this._clearTimer();
            _this._responseAvailable = true;

            _this._responseData = _this._xmlHttpRequest.responseText;
            _this._statusCode = _this._xmlHttpRequest.status;
            _this._statusText = _this._xmlHttpRequest.statusText;
            _this._headers = _this._xmlHttpRequest.getAllResponseHeaders();

            _this._webRequest.completed(Sys.EventArgs.Empty);
            if (_this._xmlHttpRequest != null) {
                _this._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
                _this._xmlHttpRequest = null;
            }
        }
    }

    this._clearTimer = function this$_clearTimer() {
        if (_this._timer != null) {
            window.clearTimeout(_this._timer);
            _this._timer = null;
        }
    }

    this._onTimeout = function this$_onTimeout() {
        if (!_this._responseAvailable) {
            _this._clearTimer();
            _this._timedOut = true;
            _this._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
            _this._xmlHttpRequest.abort();
            _this._webRequest.completed(Sys.EventArgs.Empty);
            _this._xmlHttpRequest = null;
        }
    }
}

This is very simple and clean, so I’ll just show you other methods of the XMLHttpSyncExecutor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
function Sys$Net$XMLHttpSyncExecutor$get_timedOut() {
    /// <value type="Boolean"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    return this._timedOut;
}

function Sys$Net$XMLHttpSyncExecutor$get_started() {
    /// <value type="Boolean"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    return this._started;
}

function Sys$Net$XMLHttpSyncExecutor$get_responseAvailable() {
    /// <value type="Boolean"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    return this._responseAvailable;
}

function Sys$Net$XMLHttpSyncExecutor$get_aborted() {
    /// <value type="Boolean"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    return this._aborted;
}

function Sys$Net$XMLHttpSyncExecutor$executeRequest() {
    if (arguments.length !== 0) throw Error.parameterCount();
    this._webRequest = this.get_webRequest();

    if (this._started) {
        throw Error.invalidOperation(String.format(Sys.Res.cannotCallOnceStarted, 'executeRequest'));
    }
    if (this._webRequest === null) {
        throw Error.invalidOperation(Sys.Res.nullWebRequest);
    }

    var body = this._webRequest.get_body();
    var headers = this._webRequest.get_headers();
    this._xmlHttpRequest = new XMLHttpRequest();
    this._xmlHttpRequest.onreadystatechange = this._onReadyStateChange;
    var verb = this._webRequest.get_httpVerb();
    this._xmlHttpRequest.open(verb, this._webRequest.getResolvedUrl(), false); // False to call Synchronously
    if (headers) {
        for (var header in headers) {
            var val = headers[header];
            if (typeof(val) !== "function")
                this._xmlHttpRequest.setRequestHeader(header, val);
        }
    }

    if (verb.toLowerCase() === "post") {
        if ((headers === null) || !headers['Content-Type']) {
            this._xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        }

        if (!body) {
            body = "";
        }
    }

    var timeout = this._webRequest.get_timeout();
    if (timeout > 0) {
        this._timer = window.setTimeout(Function.createDelegate(this, this._onTimeout), timeout);
    }
    this._xmlHttpRequest.send(body);
    this._started = true;
}

 function Sys$Net$XMLHttpSyncExecutor$getAllResponseHeaders() {
    /// <returns type="String"></returns>
    if (arguments.length !== 0) throw Error.parameterCount();
    if (!this._responseAvailable) {
        throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'getAllResponseHeaders'));
    }

    return this._headers;
}

function Sys$Net$XMLHttpSyncExecutor$get_responseData() {
    /// <value type="String"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    if (!this._responseAvailable)
    {
        throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_responseData'));
    }

    return this._responseData;
}

function Sys$Net$XMLHttpSyncExecutor$get_statusCode() {
    /// <value type="Number"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    if (!this._responseAvailable)
    {
        throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusCode'));
    }

    return this._statusCode;
}

function Sys$Net$XMLHttpSyncExecutor$get_statusText() {
    /// <value type="String"></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    if (!this._responseAvailable)
    {
        throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_statusText'));
    }

    return this._statusText;
}

function Sys$Net$XMLHttpSyncExecutor$get_xml() {
    /// <value></value>
    if (arguments.length !== 0) throw Error.parameterCount();
    if (!this._responseAvailable)
    {
        throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse, 'get_xml'));
    }

    var xml = this._responseData;
    if ((!xml) || (!xml.documentElement))
    {
        xml = new XMLDOM(this._responseData);
        if ((!xml) || (!xml.documentElement))
        {
            return null;
        }
    }
    else if (navigator.userAgent.indexOf('MSIE') !== -1)
    {
        xml.setProperty('SelectionLanguage', 'XPath');
    }

    if ((xml.documentElement.namespaceURI === "http://www.mozilla.org/newlayout/xml/parsererror.xml") &&
        (xml.documentElement.tagName === "parsererror"))
    {
        return null;
    }

    if (xml.documentElement.firstChild && xml.documentElement.firstChild.tagName === "parsererror")
    {
        return null;
    }

    return xml;
}

function Sys$Net$XMLHttpSyncExecutor$abort() {
    if (arguments.length !== 0) throw Error.parameterCount();
    if (!this._started) {
        throw Error.invalidOperation(Sys.Res.cannotAbortBeforeStart);
    }

    if (this._aborted || this._responseAvailable || this._timedOut)
        return;

    this._aborted = true;

    this._clearTimer();

    if (this._xmlHttpRequest && !this._responseAvailable) {
        this._xmlHttpRequest.onreadystatechange = Function.emptyMethod;
        this._xmlHttpRequest.abort();

        this._xmlHttpRequest = null;
        var handler = this._webRequest._get_eventHandlerList().getHandler("completed");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    }
}

Sys.Net.XMLHttpSyncExecutor.prototype = {
    get_timedOut: Sys$Net$XMLHttpSyncExecutor$get_timedOut,
    get_started: Sys$Net$XMLHttpSyncExecutor$get_started,
    get_responseAvailable: Sys$Net$XMLHttpSyncExecutor$get_responseAvailable,
    get_aborted: Sys$Net$XMLHttpSyncExecutor$get_aborted,
    executeRequest: Sys$Net$XMLHttpSyncExecutor$executeRequest,
    getAllResponseHeaders: Sys$Net$XMLHttpSyncExecutor$getAllResponseHeaders,
    get_responseData: Sys$Net$XMLHttpSyncExecutor$get_responseData,
    get_statusCode: Sys$Net$XMLHttpSyncExecutor$get_statusCode,
    get_statusText: Sys$Net$XMLHttpSyncExecutor$get_statusText,
    get_xml: Sys$Net$XMLHttpSyncExecutor$get_xml,
    abort: Sys$Net$XMLHttpSyncExecutor$abort
}
Sys.Net.XMLHttpSyncExecutor.registerClass('Sys.Net.XMLHttpSyncExecutor', Sys.Net.WebRequestExecutor);

And finally we will notify ASP.NET AJAX that script have been loaded.

1
2
3
4
if (typeof(Sys) != 'undefined')
{
    Sys.Application.notifyScriptLoaded();
}

Usage is not so simple as wanted, but it’s still quite easy to understand:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function getServerTime() {
    // Instantiate a WebRequest.
    var wRequest = new Sys.Net.WebRequest();
    // Set the request URL.
    wRequest.set_url(PageMethods.get_path() + "/GetServerTime");
    // Set the request verb.
    wRequest.set_httpVerb('POST');
   
    wRequest.get_headers()['Content-Type'] = 'application/json; charset=utf-8';

    var executor = new Sys.Net.XMLHttpSyncExecutor();
    wRequest.set_executor(executor);
    // Execute the request.
    wRequest.invoke();

    if (executor.get_responseAvailable()) {
        return executor.get_object();
    }
    return false;
}

When you are using ScriptService, you will not see these difficulties, because ASP.NET will generate wrappers by itself. But if you need synchronous AJAX call — sorry, but in this case you should do it manually. Sample solution could be found here.

The post Synchronous page method call in ASP.NET AJAX library first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/asp-net/synchronous-page-method-call-in-asp-net-ajax-library/feed/ 10
Best technical video on the Net https://kpumuk.info/resume/best-technical-video-on-the-net/ https://kpumuk.info/resume/best-technical-video-on-the-net/#comments Fri, 17 Nov 2006 05:34:30 +0000 http://kpumuk.info/internet/best-technical-video-on-the-net/ Few days ago my best friend Alexey Kovyrin started new site which name is BestTechVideos.com. As he mentioned, this site has been created because there are lots really interesting videos on the Net, but if you’d like to fine some good tech video, it is not so simple to find them because of tons of […]

The post Best technical video on the Net first appeared on Dmytro Shteflyuk's Home.]]>
BestTechVideosFew days ago my best friend Alexey Kovyrin started new site which name is BestTechVideos.com. As he mentioned, this site has been created because there are lots really interesting videos on the Net, but if you’d like to fine some good tech video, it is not so simple to find them because of tons of crappy “funny videos” like “funny cats” and so on.

This site is interesting for me because I really like to see smarty people and listen their thoughts. Project is just started therefor video collection is not so large as I want, but it grows every day. I found interesting screencasts about AJAX, Web 2.0 and others here.

So, If you like to attend technical conferences and watch conference sessions on video, if you like idea of screencasts, etc, then this site is for you! Welcome to Best Tech Videos you’ll be impressed by amount of hi-quality and useful videos on the Net.

The post Best technical video on the Net first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/resume/best-technical-video-on-the-net/feed/ 3
Ruby on Rails related cheat sheets https://kpumuk.info/ruby-on-rails/ruby-on-rails-related-cheat-sheets/ https://kpumuk.info/ruby-on-rails/ruby-on-rails-related-cheat-sheets/#comments Fri, 17 Nov 2006 05:32:47 +0000 http://kpumuk.info/ajax/ruby-on-rails-related-cheat-sheets/ There are couple of cheat sheets about Ruby on Rails and related technologies can be found in the web. I decided to collect all of them (almost all) in one post just to keep them in mind. All of them are in full color PDFs or PNGs. Ruby on Rails Development Cheat Sheets Ruby Cheatsheet […]

The post Ruby on Rails related cheat sheets first appeared on Dmytro Shteflyuk's Home.]]>
There are couple of cheat sheets about Ruby on Rails and related technologies can be found in the web. I decided to collect all of them (almost all) in one post just to keep them in mind. All of them are in full color PDFs or PNGs.

Ruby on Rails Development Cheat Sheets

JavaScript Development Cheat Sheets

Databases / SQL Cheat Sheets

Web Development Cheat Sheets

Other Cheat Sheets

The post Ruby on Rails related cheat sheets first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/ruby-on-rails-related-cheat-sheets/feed/ 13
AJAX-enabled Smarty plugins Part 2: ajax_form https://kpumuk.info/php/ajax-enabled-smarty-plugins-part-2-ajax_form/ https://kpumuk.info/php/ajax-enabled-smarty-plugins-part-2-ajax_form/#comments Tue, 21 Feb 2006 07:47:28 +0000 http://kpumuk.info/ajax/ajax-enabled-smarty-plugins-part-2-ajax_formajax-%d0%bf%d0%bb%d0%b0%d0%b3%d0%b8%d0%bd%d1%8b-%d0%b4%d0%bb%d1%8f-smarty-%d1%87%d0%b0%d1%81%d1%82%d1%8c-2-ajax_form/ In my previous post I’ve described several simple AJAX plugins. Now I’ll show how to use one of them — ajax_form — in real applications. I think this is the most powerful plugin therefor I’ll dwell on it more elaborately. Most of Web-forms has variuos validation mechanisms. Simplest way is to process form on the […]

The post AJAX-enabled Smarty plugins Part 2: ajax_form first appeared on Dmytro Shteflyuk's Home.]]>
In my previous post I’ve described several simple AJAX plugins. Now I’ll show how to use one of them — ajax_form — in real applications. I think this is the most powerful plugin therefor I’ll dwell on it more elaborately.

Most of Web-forms has variuos validation mechanisms. Simplest way is to process form on the server and parse result on client, where return data can be in following format:

1
2
true;User was registered successfully;http://example.com/login/
false;Please enter your name;Entered passwords doesn't match

Result string can be splitted on client and results can be shown in some part of page. Process function may looks like following (it’s part of smarty_ajax):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var SmartyAjax = {
  onSubmit: function(originalRequest) {
    var results = originalRequest.responseText.split(";");

    if (results[0] == "true") {
      SmartyAjax.Messages.set(results[1],
        SmartyAjax.Messages.MT_WARNING)
    } else {
      SmartyAjax.Messages.clear();
      SmartyAjax.Messages.setType(SmartyAjax.Messages.MT_ERROR);
      for (var i = 1; i < results.length; i++) {
        SmartyAjax.Messages.add(results[i]);
      }
    }
  }
}

This function uses several functions from SmartyAjax.Messages object which depends on following HTML elements:

1
2
3
4
<div id="messages">
  <p id="messages-title"></p>
  <ul id="messages-list"></ul>
</div>

To manage messages I’ve created Smarty template parts/warnings.tpl. You can use it in your PHP file in simple way:

1
2
3
4
// is messages contains warning (or error)
$t->assign('messages_warning', true);
// array of messages
$t->assign('messages', array('Please provide your account information'));

Another thing we need to examine is message which informs user about processing AJAX request. There is SmartyAjax.Process object in the sample which has two methods: hide() and show() which can be used to hide and display message. They are depends on HTML-element with id=”ajax-process”. It’s necessary to add “position: absolute” style because of this messages will be shown in top-right corner of screen independing on scroll position.

ajax_form is simple to use:

1
2
3
{ajax_form method="post" id="form_register"}
Any form-element can be placed here
{/ajax_form}

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • params – URL-encoded parameters
  • id – form ID
  • callback – JavaScript function which will be called when query will be completed

Example can be found here, and full sources can be downloaded here.

The post AJAX-enabled Smarty plugins Part 2: ajax_form first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/ajax-enabled-smarty-plugins-part-2-ajax_form/feed/ 52
AJAX-enabled Smarty plugins https://kpumuk.info/php/ajax-enabled-smarty-plugins/ https://kpumuk.info/php/ajax-enabled-smarty-plugins/#comments Sat, 18 Feb 2006 23:49:25 +0000 http://kpumuk.info/ajax/ajax-enabled-smarty-pluginsajax-%d0%bf%d0%bb%d0%b0%d0%b3%d0%b8%d0%bd%d1%8b-%d0%b4%d0%bb%d1%8f-smarty/ Today I’ve created simple AJAX-enabled plugins for Smarty. I don’t try to develop powerful reach-applications framework. I can give you only idea how to integrate AJAX-technology into Smarty. But if you have any offers how to improve anything I’ve described or if you just want to leave feedback please post you comments on my site. […]

The post AJAX-enabled Smarty plugins first appeared on Dmytro Shteflyuk's Home.]]>
Today I’ve created simple AJAX-enabled plugins for Smarty. I don’t try to develop powerful reach-applications framework. I can give you only idea how to integrate AJAX-technology into Smarty. But if you have any offers how to improve anything I’ve described or if you just want to leave feedback please post you comments on my site.

In my practice I need several things from AJAX: to update some nodes in DOM, to send forms without post-back, to retrieve some values or to perform server-side calculation (maybe using database or other server-side resources). It’s necessary to write tons of JavaScript to implement my requirements in spite of using cool JavaScript library Prototype.

I decided to integrate Smarty with AJAX. There are three Smarty plugins has been created: ajax_update, ajax_call, ajax_form. Below all this plugins will be described.

ajax_update

This Smarty function can be used for update some parts of web-page.

Sample usage:

1
2
<a href="#" onclick="{ajax_update update_id='intro_content'
  function='update_intro' params='page=about'}"
>About</a>

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • update_id – ID of HTML element for update
  • function – function which will be called
  • params – URL-encoded parameters

ajax_call

This Smarty function can be used for call PHP function on server side and retrieve its output.

Sample usage:

1
2
<a href="#" onclick="{ajax_call function='calculate'
  params_func='calc_params' callback='calc_cb'}"
>Calculate</a>

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • function – function which will be called
  • params – URL-encoded parameters
  • callback – JavaScript function which will be called when query will be completed
  • params_func – JavaScript function used when you need custom parameters calculated on client side

ajax_form

This Smarty block can be used for submit Web-forms without post-back.

Sample usage:

1
2
3
{ajax_form method="post" id="form_register"}
Any form-element can be placed here
{/ajax_form}

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • params – URL-encoded parameters
  • id – form ID
  • callback – JavaScript function which will be called when query will be completed

Samples

These plugins are quite simple and I think everyone can create even better than mine. I’ve just wanted to show you idea how integration can be done. Working examples can be found here. Also you can download full sources.

The post AJAX-enabled Smarty plugins first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/ajax-enabled-smarty-plugins/feed/ 71