library | 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:40:32 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Sphinx Client API 0.3.1 and 0.4.0 r909 for Sphinx 0.9.8 r909 released https://kpumuk.info/ruby-on-rails/sphinx-client-api-0-3-1-and-0-4-0-r909-for-sphinx-0-9-8-r909-released/ https://kpumuk.info/ruby-on-rails/sphinx-client-api-0-3-1-and-0-4-0-r909-for-sphinx-0-9-8-r909-released/#comments Sun, 09 Dec 2007 19:33:10 +0000 http://kpumuk.info/ror-plugins/sphinx-client-api-0-3-1-and-0-4-0-r909-for-sphinx-0-9-8-r909-released/ I have a good news: Sphinx Client API has been updated and now it supports all brand new features of the unstable Sphinx 0.9.8 development snapshot. What does it mean for you as a developer? What features you will get if you would decide to switch to the new version? I will describe most valuable […]

The post Sphinx Client API 0.3.1 and 0.4.0 r909 for Sphinx 0.9.8 r909 released first appeared on Dmytro Shteflyuk's Home.]]>
Sphinx Search Engine I have a good news: Sphinx Client API has been updated and now it supports all brand new features of the unstable Sphinx 0.9.8 development snapshot. What does it mean for you as a developer? What features you will get if you would decide to switch to the new version? I will describe most valuable improvements of the Sphinx in this article, and will show how to use them with new Sphinx Client API 0.4.0 r909.

Table of contents

Multi-query support

What does it mean? Multi-query support means sending multiple search queries to Sphinx at once. It’s saving network connection overheads and other round-trip costs. But what’s much more important, it unlocks possibilities to optimize “related” queries internally. Here is quote from the Sphinx home page:

One typical Sphinx usage pattern is to return several different “views” on the search results. For instance, one might need to display per-category match counts along with product search results, or maybe a graph of matches over time. Yes, that could be easily done earlier using the grouping features. However, one had to run the same query multiple times, but with different settings.

From now on, if you submit such queries through newly added multi-query interface (as a side note, ye good olde Query() interface is not going anywhere, and compatibility with older clients should also be in place), Sphinx notices that the full-text search query is the same and it is just sorting/grouping settings which are different. In this case it only performs expensive full-text search once, but builds several different (differently sorted and/or grouped) result sets from retrieved matches. I’ve seen speedups of 1.5-2 times on my simple synthetic queries; depending on different factors, the speedup could be even greater in practice.

To perform multi-query you should add several queries using AddQuery method (parameters are exactly the same as in Query call), and then call RunQueries. Please note, that all parameters, filters, query settings are stored between AddQuery calls. It means that if you have specified sort mode using SetSortMode before first AddQuery call, then sort mode will be the same for the second AddQuery call. Currently you can reset only filters (using ResetFilters) and group by (ResetGroupBy) settings. BTW, you can use Query as usually to perform single query, but don’t try to make this call after you have added query into the batch using AddQuery.

Stop speaking, let’s look the example:

1
2
3
4
5
6
7
8
9
10
sphinx = Sphinx::Client.new
sphinx.SetFilter('group_id', [1])
sphinx.AddQuery('wifi')

sphinx.ResetFilters
sphinx.SetFilter('group_id', [2])
sphinx.AddQuery('wifi')

results = sphinx.RunQueries
pp results

As the result we will get array of 2 hashes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[{"total_found"=>2,
  "status"=>0,
  "matches"=>
   [{"attrs"=>{"group_id"=>1, "created_at"=>1175658647}, "weight"=>2, "id"=>3},
    {"attrs"=>{"group_id"=>1, "created_at"=>1175658490}, "weight"=>1, "id"=>1}],
  "error"=>"",
  "words"=>{"wifi"=>{"hits"=>6, "docs"=>3}},
  "time"=>"0.000",
  "attrs"=>{"group_id"=>1, "created_at"=>2},
  "fields"=>["name", "description"],
  "total"=>2,
  "warning"=>""},
 {"total_found"=>1,
  "status"=>0,
  "matches"=>
   [{"attrs"=>{"group_id"=>2, "created_at"=>1175658555}, "weight"=>2, "id"=>2}],
  "error"=>"",
  "words"=>{"wifi"=>{"hits"=>6, "docs"=>3}},
  "time"=>"0.000",
  "attrs"=>{"group_id"=>1, "created_at"=>2},
  "fields"=>["name", "description"],
  "total"=>1,
  "warning"=>""}]

Each hash contains the same data as result of Query method call. Also they have additional fields error and warning which contains error and warning message respectively when not empty.

Note: I have added ResetFilters call before creating second query. Without this call our query will have two filters with conflicting conditions, so there will be no results at all.

Extended engine V2

New querying engine (codenamed “extended engine V2”) is going to gradually replace all the currently existing matching modes. At the moment, it is fully identical to extended mode in functionality, but is much less CPU intensive for some queries. Here are notes from Sphinx author:

I have already seen improvements of up to 3-5 times in extreme cases. The only currently known case when it’s slower is processing complex extended queries with tens to thousands keywords; but forthcoming optimizations will fix that.

V2 engine is currently in alpha state and does not affect any other matching mode yet. Temporary SPH_MATCH_EXTENDED2 mode was added to provide a way to test it easily. We are in the middle of extensive internal testing process (under simulated production load, and then actual production load) right now. Your independent testing results would be appreciated, too!

So, to use new matching mode we should use SPH_MATCH_EXTENDED2 mode. Let’s do it!

1
2
3
sphinx = Sphinx::Client.new
sphinx.SetMatchMode(Sphinx::Client::SPH_MATCH_EXTENDED2)
sphinx.Query('wifi')

Easy enough, right? You should try it by yourself to feel power of new engine. Please note, that this mode is temporary and it will be removed after release.

64-bit document and word IDs support

Before version 0.9.8 the Sphinx was limited to index up to 4 billion documents because of using 32-bit keys. From here on it has ability to use 64-bit IDs, and new feature does not impact on 32-bit keys performance. Let’s look at the example. First we will make query to DB with 32-bit keys:

1
2
3
sphinx = Sphinx::Client.new
result = sphinx.Query('wifi')
pp result['matches'][0]['id'].class

As you can see, class of the id field is Fixnum. Let’s try to make call to index with 64-bit keys. You will get Bignum as the result, and it means that you can have more than 4 billion documents!

Multiple-valued attributes

Plain attributes only allow to attach 1 value per each document. However, there are cases (such as tags or categories) when it is necessary to attach multiple values of the same attribute and be able to apply filtering to value lists. In these cases we can use multiple-valued attributes now.

1
2
3
sphinx = Sphinx::Client.new
sphinx.SetFilter('tag', [1,5])
pp sphinx.Query('wifi')

In case of using miltiple-valued attribute tag you will get result like:

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
{"total_found"=>2,
 "status"=>0,
 "matches"=>
  [{"attrs"=>
     {"tag"=>[4, 5],
      "group_id"=>2,
      "created_at"=>1175658555},
    "weight"=>2,
    "id"=>2},
   {"attrs"=>
     {"tag"=>[1, 2, 3],
      "group_id"=>1,
      "created_at"=>1175658490},
    "weight"=>1,
    "id"=>1}],
 "error"=>"",
 "words"=>{"wifi"=>{"hits"=>6, "docs"=>3}},
 "time"=>"0.000",
 "attrs"=>
  {"price"=>5,
   "tag"=>1073741825,
   "is_active"=>4,
   "group_id"=>1,
   "created_at"=>2},
 "fields"=>["name", "description"],
 "total"=>2,
 "warning"=>""}

As you can see, multiple-valued attributes returned as array of integers.

Geodistance feature

Sphinx now is able to compute geographical distance between two points specified by latitude and longitude pairs (in radians). So you now can specify per-query “anchor point” (and attribute names to fetch per-entry latitude and longitude from), and then use “@geodist” virtual attribute both in the filters and in the sorting clause. In this case distance (in meters) from anchor point to each match will be computed, used for filtering and/or sorting, and returned as a virtual attribute too.

1
2
3
sphinx = Sphinx::Client.new
sphinx.SetGeoAnchor('lat', 'long', 0.87248, 0.63195)
result = sphinx.Query('wifi')

Download

As always, you can download Sphinx Client API from project home page. Take into account that version 0.3.1 of the client API intended to use with Sphinx 0.9.7, and Sphinx Client API 0.4.0 r909 requires Sphinx 0.9.8 r909 development snapshot. You could download Sphinx from the Download section of the Sphinx home page.

The post Sphinx Client API 0.3.1 and 0.4.0 r909 for Sphinx 0.9.8 r909 released first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/sphinx-client-api-0-3-1-and-0-4-0-r909-for-sphinx-0-9-8-r909-released/feed/ 4
Generating permalink from string in Ruby https://kpumuk.info/ruby-on-rails/generating-permalink-from-string-in-ruby/ https://kpumuk.info/ruby-on-rails/generating-permalink-from-string-in-ruby/#comments Mon, 14 May 2007 15:27:39 +0000 http://kpumuk.info/ruby-on-rails/generating-permalink-from-string-in-ruby/ If you are creating Ruby on Rails application like a blog, you most probably want to generate URLs using post titles. It’s good practice, because search engines like keywords in URL, and it looks more human-readable. Just compare: http://example.com/posts/10 and http://example.com/posts/generating-permalinks-from-string (yeah, it’s long, but self-descriptive). Anyways, this is small post about converting a title […]

The post Generating permalink from string in Ruby first appeared on Dmytro Shteflyuk's Home.]]>
If you are creating Ruby on Rails application like a blog, you most probably want to generate URLs using post titles. It’s good practice, because search engines like keywords in URL, and it looks more human-readable. Just compare: http://example.com/posts/10 and http://example.com/posts/generating-permalinks-from-string (yeah, it’s long, but self-descriptive). Anyways, this is small post about converting a title to a permalink.

First thing I love in Ruby is an ability to extend classes with my own methods. I could just add method to_permalink to any string and then everywhere I could write something like @post.title.to_permalink. It’s amazing!

Here is my version of to_permalink method:

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
class String
  def to_permalink
    result = strip_tags
    # Preserve escaped octets.
    result.gsub!(/-+/, '-')
    result.gsub!(/%([a-f0-9]{2})/i, '--\1--')
    # Remove percent signs that are not part of an octet.
    result.gsub!('%', '-')
    # Restore octets.
    result.gsub!(/--([a-f0-9]{2})--/i, '%\1')

    result.gsub!(/&.+?;/, '-') # kill entities
    result.gsub!(/[^%a-z0-9_-]+/i, '-')
    result.gsub!(/-+/, '-')
    result.gsub!(/(^-+|-+$)/, '')
    return result.downcase
  end

  private
 
    def strip_tags
      return clone if blank?
      if index('<')
        text = ''
        tokenizer = HTML::Tokenizer.new(self)

        while token = tokenizer.next
          node = HTML::Node.parse(nil, 0, 0, token, false)
          # result is only the content of any Text nodes
          text << node.to_s if node.class == HTML::Text
        end
        # strip any comments, and if they have a newline at the end (ie. line with
        # only a comment) strip that too
        text.gsub(/<!--(.*?)-->[\n]?/m, '')
      else
        clone # already plain text
      end
    end
end

How it’s working? First thing you would see is a private method strip_tags. Yes, I know about ActionView::Helpers::TextHelper::strip_tags, and this is almost 100% copy of Rails version (the only difference is that my version always returns clone of the original string). I just don’t want to rely on the Rails library.

Then my method replaces all special characters with dashes (only octets like %A0 would be kept), and trims dashed from the beginning and the end of the string. Finally full string will be lowercased.

Of course, in your application you should check collisions (several posts which have the same title should have unique permalinks, for example you could append numbers starting from 1: hello, hello-1, hello-2, etc). This is not my goal to cover all difficulties you could face, it’s small post, do you remember?

Just for your pleasure, here are the RSpec tests for this method:

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
describe 'String.to_permalink from extensions.rb' do
  it 'should replace all punctuation marks and spaces with dashes' do
    "!.@#$\%^&*()Test case\n\t".to_permalink.should == 'test-case'
  end

  it 'should preserve _ symbol' do
    "Test_case".to_permalink.should == 'test_case'
  end
 
  it 'should preserve escaped octets and remove redundant %' do
    'Test%%20case'.to_permalink.should == 'test-%20case'
  end

  it 'should strip HTML tags' do
    '<a href="http://example.com">Test</a> <b>case</b>'.to_permalink.should == 'test-case'
  end

  it 'should strip HTML entities and insert dashes' do
    'Test&nbsp;case'.to_permalink.should == 'test-case'
  end

  it 'should trim beginning and ending dashes' do
    '-. Test case .-'.to_permalink.should == 'test-case'
  end

  it 'should not use ---aa--- as octet' do
    'b---aa---b'.to_permalink.should == 'b-aa-b'
  end
 
  it 'should replace % with -' do
    'Hello%world'.to_permalink.should == 'hello-world'
  end

  it 'should not modify original string' do
    s = 'Hello,&nbsp;<b>world</b>%20'
    s.to_permalink.should == 'hello-world%20'
    s.should == 'Hello,&nbsp;<b>world</b>%20'

    s = 'Hello'
    s.to_permalink.should == 'hello'
    s.should == 'Hello'
  end
end

It’s funny, right?

The post Generating permalink from string in Ruby first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/generating-permalink-from-string-in-ruby/feed/ 5
Sphinx Search Engine 0.9.7, Ruby Client API 0.3.0 https://kpumuk.info/ruby-on-rails/sphinx-search-engine-0-9-7-ruby-client-api-0-3-0/ https://kpumuk.info/ruby-on-rails/sphinx-search-engine-0-9-7-ruby-client-api-0-3-0/#comments Thu, 05 Apr 2007 14:44:36 +0000 http://kpumuk.info/ror-plugins/sphinx-search-engine-0-9-7-ruby-client-api-0-3-0/ [lang_en] It’s happened! We all waited for Sphinx update and finally Andrew Aksyonoff has released version 0.9.7 of his wonderful search engine (who does not know about it, look my previous posts here and here). [/lang_en] [lang_ru] Свершилось! Мы все ждали обновления Sphinx, и вот наконец Andrew Aksyonoff выпустил версию 0.9.7 своего замечательного поискового движка […]

The post Sphinx Search Engine 0.9.7, Ruby Client API 0.3.0 first appeared on Dmytro Shteflyuk's Home.]]>
[lang_en]

Sphinx Search EngineIt’s happened! We all waited for Sphinx update and finally Andrew Aksyonoff has released version 0.9.7 of his wonderful search engine (who does not know about it, look my previous posts here and here).

[/lang_en]

[lang_ru]

Sphinx Search EngineСвершилось! Мы все ждали обновления Sphinx, и вот наконец Andrew Aksyonoff выпустил версию 0.9.7 своего замечательного поискового движка (для тех, кто не понимает, о чем я говорю: посмотрите мои предыдущие заметки здесь и здесь).

[/lang_ru]

[lang_en]

Major Sphinx updates include:

  • separate groups sorting clause in group-by mode
  • support for 1-grams, prefix and infix indexing
  • improved documentation

Now about Sphinx Client API for Ruby. In this version I decided that it is not so good to have different interfaces in different languages (BuildExcerpts in PHP and build_excerpts in Ruby). Therefor applications which using version 0.1.0 or 0.2.0 of API should be reviewed after update. Check documentation for details.

New things in the Sphinx Ruby API:

  • Completely synchronized API with PHP version.
  • Fixed bug with processing attributes in query response (thanks to shawn).
  • Fixed bug query processing time round-up (thanks to michael).
  • 100% covered by RSpec specifications.

You could always download latest version from the Sphinx Client API for Ruby page.

If you are using Sphinx in your Ruby on Rails application, you should try acts_as_sphinx plugin.

[/lang_en]

[lang_ru]

Основные новшества Sphinx включают:

  • separate groups sorting clause in group-by mode
  • support for 1-grams, prefix and infix indexing
  • improved documentation

Теперь о Sphinx Client API для Ruby. В этой версии я решил, что нехорошо иметь разные интерфейсы в разных языка (BuildExcerpts в PHP и build_excerpts в Ruby). Потому код приложений, в которых использовали версии 0.1.0 или 0.2.0 API, необходимо пересмотреть. Детали смотрите в документации.

Изменения в Sphinx Client API для Ruby:

  • Полностью синхронизирован API с версией PHP.
  • Исправлена ошибка с обработкой атрибутов в результатах запроса (спасибо shawn).
  • Исправлена ошибка с округлением временем обработки запроса (спасибо michael).
  • Библиотека покрыта на 100% спецификациями RSpec.

Вы всегда можете загрузить последнюю версию со страницы Sphinx Client API для Ruby.

Если Вы используете Sphinx в приложении на Ruby on Rails, посмотрите плагин acts_as_sphinx.

[/lang_ru]

The post Sphinx Search Engine 0.9.7, Ruby Client API 0.3.0 first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/sphinx-search-engine-0-9-7-ruby-client-api-0-3-0/feed/ 5
Sphinx 0.9.7-RC2 released, Ruby API updated https://kpumuk.info/ruby-on-rails/sphinx-097-rc2-released-ruby-api-updated/ https://kpumuk.info/ruby-on-rails/sphinx-097-rc2-released-ruby-api-updated/#comments Wed, 20 Dec 2006 06:33:29 +0000 http://kpumuk.info/php/sphinx-097-rc2-released-ruby-api-updated/ Today I found that Sphinx search engine has been updated. Major new features include: extended query mode with boolean, field limits, phrases, and proximity support (eg.: @title "hello world"~10 | @body example program); extended sorting mode (eg.: @weight DESC @id ASC); combined phrase+statistical ranking which takes words frequencies into account (currently in extended mode only); […]

The post Sphinx 0.9.7-RC2 released, Ruby API updated first appeared on Dmytro Shteflyuk's Home.]]>
Today I found that Sphinx search engine has been updated. Major new features include:

  • extended query mode with boolean, field limits, phrases, and proximity support (eg.: @title "hello world"~10 | @body example program);
  • extended sorting mode (eg.: @weight DESC @id ASC);
  • combined phrase+statistical ranking which takes words frequencies into account (currently in extended mode only);
  • official Python API;
  • contributed Perl and Ruby APIs.

I have updated Sphinx Client Library along with Sphinx 0.9.7-RC2 Windows build.

The post Sphinx 0.9.7-RC2 released, Ruby API updated first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/sphinx-097-rc2-released-ruby-api-updated/feed/ 4
Using Sphinx search engine in Ruby on Rails https://kpumuk.info/ruby-on-rails/using-sphinx-search-engine-in-ruby-on-rails/ https://kpumuk.info/ruby-on-rails/using-sphinx-search-engine-in-ruby-on-rails/#comments Sun, 26 Nov 2006 08:55:20 +0000 http://kpumuk.info/projects/ror-plugins/using-sphinx-search-engine-in-ruby-on-rails/ Almost all Web-applications needs data search logic and really often this logic should have full-text search capabilities. If you are using MySQL database, you can use its FULLTEXT search, but it’s not efficient when you have a large amout of data. In this case third party search engines used, and one of them (and I […]

The post Using Sphinx search engine in Ruby on Rails first appeared on Dmytro Shteflyuk's Home.]]>
Almost all Web-applications needs data search logic and really often this logic should have full-text search capabilities. If you are using MySQL database, you can use its FULLTEXT search, but it’s not efficient when you have a large amout of data. In this case third party search engines used, and one of them (and I think, the most efficient) is Sphinx. In this article I’ll present my port of Sphinx client library for Ruby and show how to use it.

First of all, what is the Sphinx itself? Sphinx is a full-text search engine, meant to provide fast, size-efficient and relevant fulltext search functions to other applications. Sphinx was specially designed to integrate well with SQL databases and scripting languages. Currently built-in data sources support fetching data either via direct connection to MySQL, or from an XML pipe.

Current Sphinx distribution includes the following software:

  • indexer: an utility to create fulltext indices;
  • search: a simple (test) utility to query fulltext indices from command line;
  • searchd: a daemon to search through fulltext indices from external software (such as Web scripts);
  • sphinxapi: a set of API libraries for popular Web scripting languages (currently, PHP);

I will not describe how to install engine, if you are new with Sphinx, look the official documentation (but if you want to see my vision, you can always ask me in comments, and I will explain installation procedure in one of future posts). Instead I will present port of Sphinx client library to Ruby and show how to use it (to use this library you need Sphinx 0.9.7-RC2).

First you need to download plugin from RubyForge, or from this site.

This is Ruby on Rails plugin, therefor just unpack it in your <app>/vendor/plugins directory (library can be used outside the Rails application). Now you can write something like following in your code:

1
2
3
4
5
6
7
8
9
10
11
sphinx = Sphinx.new
sphinx.set_match_mode(Sphinx::SPH_MATCH_ANY)
result = sphinx.query('term1 term2')

# Fetch corresponding models
ids = result[:matches].map { |id, value| id }.join(',')
posts = Post.find :all, :conditions => "id IN (#{ids})"

# Get excerpts
docs = posts.map { |post| post.body }
excerpts = sphinx.build_excerpts(docs, 'index', 'term1 term2')

It’s pretty simple, isn’t it? There are several options you can use to get more relevant search results:

  • set_limits(offset, limit) – first document to fetch and number of documents.
  • set_match_mode(mode) – matching mode (can be SPH_MATCH_ALL – match all words, SPH_MATCH_ANY – match any of words, SPH_MATCH_PHRASE – match exact phrase, SPH_MATCH_BOOLEAN – match boolean query).
  • set_sort_mode(mode) – sorting mode (can be SPH_SORT_RELEVANCE – sort by document relevance desc, then by date, SPH_SORT_ATTR_DESC – sort by document date desc, then by relevance desc, SPH_SORT_ATTR_ASC – sort by document date asc, then by relevance desc, SPH_SORT_TIME_SEGMENTS – sort by time segments (hour/day/week/etc) desc, then by relevance desc).

Other options you can be found in API documentation.

If you are interested with this library, found bugs or have ideas how to improve it – please leave comments.

Updated: Unfortunately, there are no Windows binaries for latest Sphinx 0.9.7-rc2 version. I’ve built Sphinx for Windows, and added my config file into archive. You can download my build here.

The post Using Sphinx search engine in Ruby on Rails first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/using-sphinx-search-engine-in-ruby-on-rails/feed/ 37
Extending moo.fx with custom effect (fx.Flash) https://kpumuk.info/javascript/extending-moo-fx-with-custom-effect-fx-flash/ https://kpumuk.info/javascript/extending-moo-fx-with-custom-effect-fx-flash/#comments Sat, 29 Apr 2006 08:54:43 +0000 http://kpumuk.info/php/extending-moo-fx-with-custom-effect-fx-flash/ Several days ago my best friend Alexey Kovyrin asked me to help him to create flashing effect on HTML page. I gave him advice to create this effect using moo.fx library. I wanted to show how to extend it, but I couldn’t keep from creating this effect myself. moo.fx is a superlightweight, ultratiny, megasmall javascript […]

The post Extending moo.fx with custom effect (fx.Flash) first appeared on Dmytro Shteflyuk's Home.]]>
Several days ago my best friend Alexey Kovyrin asked me to help him to create flashing effect on HTML page. I gave him advice to create this effect using moo.fx library. I wanted to show how to extend it, but I couldn’t keep from creating this effect myself.

moo.fx is a superlightweight, ultratiny, megasmall javascript effects library, written with prototype.js. It’s easily to extend it with custom effect and in this post I will show you how you can do this. In this article I’ll show how to create flashing effect: element’s background will smoothly change from one color to another and go back to first color (maybe several times).

To extend fx.Base you can use following construction:

1
2
3
fx.Flash = Class.create();
Object.extend(Object.extend(fx.Flash.prototype, fx.Base.prototype), {  
// ...

Now we need to decide in which format initial colors will be passed. I think the most simple to user is to pass color values in #RRGGBB format, the most popular format in web-design. We need to parse this format to get separate color’s parts (reg, green and blue), therefor it’s necessary to create function that makes hexadecimal => decimal conversion. To assign background color to the element while flashing reverse function is required.

1
2
3
4
5
6
7
8
9
10
11
12
hD: "0123456789ABCDEF",

d2h: function(d) {
    var h = this.hD.substr(d & 15, 1);
    while (d > 15) { d >>= 4; h = this.hD.substr(d & 15, 1) + h; }
    if (h.length == 1) h = "0" + h;
    return h;
},
   
h2d: function(h) {
    return parseInt(h, 16);
}

Now we are ready to develop constructor (method initialize()):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
initialize: function(el, options) {
    this.el = $(el);

    var color_from = (options && options.color_from) || "#ffffff";
    var color_to = (options && options.color_to) || "#ff0000";
    var color_f = this.h2d(color_from.substr(1));
    var color_t = this.h2d(color_to.substr(1));
   
    var _options = {
        red: [color_f >> 16, color_t >> 16],
        green: [(color_f >> 8) & 255, (color_t >> 8) & 255],
        blue: [color_f & 255, color_t & 255],
        count: 1
    };
    Object.extend(_options, options || {});
    if (_options.onComplete) _options.flashOnComplete = _options.onComplete;
    this.setOptions(_options);
}

This function can accept following options:

  • duration – duration in milliseconds of changing color from first to second or vice versa. For example, if you pass count = 3, complete effect execution time will be 3 * 2 * duration (default is 500).
  • onComplete – a function that will get called upon effect completion.
  • transition – transition type. (default is fx.sinoidal)
  • color_from – beginning color (default is #ffffff)
  • color_to – ending color (default is #ff0000)
  • count – flashes count (default is 1)

Effect dependents on onComplete function therefor this parameters is saved to another options variable flashOnComplete.

Function increase() is called during effect. In this function we can calculate current color based on internal variable this.now:

1
2
3
4
5
6
increase: function() {
    var r = this.d2h(this.now * (this.options.red[0] - this.options.red[1]) / 255 + this.options.red[1]);
    var g = this.d2h(this.now * (this.options.green[0] - this.options.green[1]) / 255 + this.options.green[1]);
    var b = this.d2h(this.now * (this.options.blue[0] - this.options.blue[1]) / 255 + this.options.blue[1]);
    this.el.style.backgroundColor = "#" + r + g + b;
}

To call effect function toggle() used. OnComplete is used to repeat effect from ending to beginnig color. It also decrements current count value to make it possible to repeat effect count times.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
toggle: function() {
    if (this.flashCount == undefined) this.flashCount = this.options.count;
    this.options.onComplete = this.onComplete.bind(this);
    this.custom(255, 0);
},

onComplete: function() {
    this.flashCount--;
    if (this.flashCount == 0)
    {
        this.flashCount = undefined;
        this.options.onComplete = this.options.flashOnComplete;
    } else
        this.options.onComplete = this.toggle.bind(this);
    this.custom(0, 255);
}

Thats all. You can download source file here. Samples are shown below this.

This is sample text. Click the link below to view fx.Flash effect in action.
1
var sample1 = new fx.Flash("sample-area", {color_from:"#ffffe3", color_to:"#007f00", count:3, transition:fx.circ, duration:300});

Show effect #1

1
var sample2 = new fx.Flash("sample-area", {color_from:"#ffffe3", color_to:"#7f0000", count:1, duration:600});

Show effect #2

The post Extending moo.fx with custom effect (fx.Flash) first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/javascript/extending-moo-fx-with-custom-effect-fx-flash/feed/ 5
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
dBug – Impoved var_dump for PHP https://kpumuk.info/php/dbug/ https://kpumuk.info/php/dbug/#comments Thu, 09 Feb 2006 17:17:31 +0000 http://kpumuk.info/php/dbug/ Today I found very useful tool for PHP – dBug. I think every PHP-programmer uses var_dump or print_r functions for debugging purpose very often. dBug displays structured information about your variables like these functions but in more suitable way (in colored tabular format). Full features list with the examples of work can be found on […]

The post dBug – Impoved var_dump for PHP first appeared on Dmytro Shteflyuk's Home.]]>
Today I found very useful tool for PHP – dBug. I think every PHP-programmer uses var_dump or print_r functions for debugging purpose very often. dBug displays structured information about your variables like these functions but in more suitable way (in colored tabular format).

Full features list with the examples of work can be found on original site.

dBug - Impoved var_dump for PHP

The post dBug – Impoved var_dump for PHP first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/dbug/feed/ 5