Cайт с помощью HTMLMason


Оглавление (нажмите, чтобы открыть):

Cайт с помощью HTML::Mason

Autohandlers and dhandlers are only triggered for the top-level component of a request. In 1.1, you can use an Apache internal redirect or a Mason subrequest ($m->subexec) to solve the problem.

I added a simple autohandler to a directory and now my pages don’t appear.

Where does a dhandler inherit from? Can I change it to inherit based on the URL path?

Consider a site with the following components:

and suppose a request comes in for /products/index.html. /dhandler will handle the request but will still inherit from /autohandler.

This is not always the desired behavior, but there is no easy way to change it. If you want /products/* requests to use /products/autohandler, you’ll need to create /products/dhandler as well.

Can I change the value of an attribute dynamically, based on the request?

Then replace every other

Now you can leave the attribute definitions alone, but define a method if and when you need a dynamically computed value.

When using multiple component roots and autohandlers, does every autohandler in every root get called, and in what or

For each path, it will search all of the component roots, and only run the *first* autohandler found. Some of the autohandlers might come from one root and some from another. However, there is no way that multiple autohandlers would be run for the same path (/foo/autohandler, for example.) There is also no way for /foo/autohandler in root 1 to explicitly call /foo/autohandler in root 2.

People sometimes ask for this behavior to be changed. We feel it’s a bad idea because multiple component roots, right now, are very clean in both behavior and implementation. Trying to run multiple autohandlers for the same path would require a complex set of precedence rules that would almost certainly lead to unpredictable behavior. (Think about multiple versions of multiple autohandlers at different directory levels, and trying to predict which order they’d run in.)

CACHING

When I change a component I don’t always see the results in the output. How do I invalidate Mason code caches?

Before executing a memory-cached component, Mason compares the stored timestamp with the timestamp of the source file. If the source file has a later timestamp, Mason will load the component from the filesystem.

Similarly, before using an object file, Mason compares the modified timestamp of the source and object files. If the source file has a later timestamp, then it is reparsed and the object file is overwritten.

The system is designed so that you will immediately see the effects of source file changes. There are several ways for this system to breakdown; most are easy to avoid once you know about them.

* If you copy or move in a component source file from elsewhere, it will retain the original file’s timestamp, which may be earlier than the object file.

* If you use tar, rsync, rdist or similar programs to transfer components, the timestamps of the created files may not be updated to the current time. Check the program’s documentation for timestamp-related options.

* If you use a shared file system like NFS, the timestamps of locally created files may not jibe with timestamps of NFS files due to differences in machine clocks.

* If you ftp files onto a running server, Mason may read the file while it is incomplete. If the ftp then completes within the same second, Mason will not notice the change, and won’t ever read the complete file.

When in doubt, touching the source files (with the Unix touch command, or by re-saving in an editor) should force Mason to reload the component. If that does not work, try removing the object files and/or restarting the server to clear the memory cache. However, these remedies should be necessary only to diagnose the caching problem, not for normal Mason operation. On a normal Mason system cache expiration should just work «as expected».

Mason code caching breaks down often in my situation. Couldn’t you do something smarter than just comparing the timestamps?

Some alternatives that have been suggested:

* Compare the sizes of the files as well as timestamps, or use the more liberal «source timestamp != object timestamp». This would indeed increase the chance of catching a change. But it would still fail occasionally (e.g. when changing a single character, or when copying an old-timestamp file that just happens to match the current timestamp), resulting in intermittent, head-scratching errors. In our opinion, it is better to fail miserably up front and be forced to fix your system than to have a mostly-working system that fails once a week. This is especially true when you are relying on Mason’s cache invalidation on a production system.

* Comparing MD5 or other signatures of the content. This would be very accurate, but would require reading and processing the source file instead of just performing a stat. This extra expense reduces the effectiveness of the cache.

The bottom line: If you are relying on Mason’s cache invalidation on a production system, you should take the time and build in the appropriate infrastructure to ensure that source file timestamps are always up-to-date after they are copied/untarred into place.

When I change code in a library file I don’t see the results. How can I get Mason to reread the library files?

Once I’ve made an error in a component, the error keeps appearing in the logs, no matter how many times I fix it and reload!

Do data cache files expire automatically when a component or its dependencies change?

With Mason 1.1x and beyond, you can use the following idiom to say «expire when my component source file changes»:

With Mason HTML ), perl code and HTML::Mason directives.

Some components are accessed directly by web browsers. These are called top-level components. A top-level component might consist purely of static HTML.

Other components are support components, which are called by top-level components or other support components. These components are analogous to perl subroutines — they allow you to create small packages of code that you can reuse throughout your project.

How do components communicate with each other?

Some components may have very simple return values. As an example, consider a component called isNetscape which returns a true value when the client’s browser is Netscape and undef when it is not. The isNetscape component could then be used easily in an if() or other control statement.

Of course, components can also return strings of text, arrays, hashes or other arbitrarily complex perl data structures.

How do I use modules in components?

* the module will be used separately by every httpd child process, costing both time and memory.

* it is difficult to keep track of all the modules being used on a site.

A more efficient method is to put the use line in the handler.pl or use the PerlModule directive. If you want components to be able to refer to symbols exported by the module, you need to use the module inside the HTML::Mason::Commands package. See the «External modules» section of the Administrator’s Guide:

Can I define subroutines in components?

You can technically define named subroutines inside the section of any component, but we highly discourage this, because all components are executed in the same namespace. This makes it easy to create two subroutines with the same name in two different components.

Consider the following options:

* If the routine is going to display HTML, use a separate component or a subcomponent.

* If the subroutine is only of use in your component, use an anonymous subroutine defined in . Even though you could define the anonymous subroutine in any section, a is recommended, both for performance and to avo >

* If the subroutine is of interest to more than just your component, have you considered putting it in a module?

Note that calling a component, while reasonably fast, is about an order of magnitude slower than calling an equivalent subroutine. So if you’re going to call the routine many times in a loop, you may wish to use the anonymous subroutine for performance reasons. Benchmark for yourself.

Does Mason set the current working directory (.) for me?

In an Apache environment, the working directory will be set in a more-or-less random way, depending on such seemingly irrelevant factors as whether you started the server in single-process mode or not. In a non-Apache environment the working directory will be whatever it was before Mason started executing.

Often people expect the working directory to be the directory of the current component. You can, instead, get that directory manually with

How do I exit from all components including the ones that called me?

Why does my output have extra newlines/whitespace and how can I get rid of it?

In components that do display content, there are various strategies. To eliminate selected newlines, use the backslash. For example,

outputs «foobarbaz» with no newlines.

To prevent a component from outputting any newlines, use a filter:

To emit binary data without the risk of inserting extra whitespace, surround your code with $m->clear_buffer and $m->abort, to suppress any preceding and following content:

At some point Mason will probably offer a «reasonable» whitespace removal feature, controlled by parameter.

I’m trying to generate an image or other binary file, but it seems to be getting corrup

In Apache 1.0 a real working example looks like this:

In Apache 2.0 use:

How do I put comments in components?

* In the and sections, and in a block, use standard Perl comments (‘#’).

* In Mason 1.3 and beyond, use for single or multi-line comments anywhere outside of Perl sections. Before 1.3, this syntax isn’t guaranteed to work; one alternative is to begin a line with %#.

* If you are producing HTML, you can use standard HTML comments delimited by . The difference is that these comments will appear in the final output.

What’s a good way to temporarily comment out code in a component?

The ad will still be fetched and counted, but not displayed!

A better way to block out a section is if (0):

Code blocked out in this way will neither be executed nor displayed, and multiple if (0) blocks can be nested ins >HTML comments).

Another way to block out code is with a tag or a comment, although these not cannot be nested.

How can I capture the output of a component (and modify it, etc.) instead of having it automatically output?

Can I use globals in components?

If you have a handler.pl file, you can also declare global variables in the handler() subroutine as long as you explicitly put them in the HTML::Mason::Commands package.

or use the Parser allow_globals parameter.

Alternatively you can turn off strict entirely by passing:

when you create the Parser object. Then you can use all the globals you want. Doing this is terribly silly, however, and is bound to get you in trouble down the road.

How do I share variables between components?

Second, you can use globals. All components run in the same package (HTML::Mason::Commands as of this writing), so globals in this package are visible to all components. See the previous question.

There is no way to share a variable between just a few components; this is a limitation of Perl’s scoping rules. You can make a variable /visible/ to only certain components using ‘our’ declarations:

See the Perl documentation on ‘our’ to make sure you understand what this is doing.

The section is /not/ for sharing variables among different file components. It is for sharing variables among the subcomponents and methods of a single file component.

Why does the order of output get mixed up when I use print or $r->print?

Since your server is most likely in batch mode, all Mason output gets buffered til the end of the request. print and $r->print circumvent the buffer and thus come out before other Mason output.

Solution: don’t use print or $r->print. Use $m->out if you must output inside a Perl section. See the section on output mode in the Administrator’s Guide.

and the section on $m->out in the Request manual.

Why doesn’t my code run every time the component runs?

If you need code that is guaranteed to run when the component or request exits, cons >DESTROY method.

Is exactly like %ARGS, and do I need to worry about it?

If you want to pass arguments that are not > will pass arguments clickable.x and clickable.y to the action url automatically. If you want to access these, you’d have to use $ARGS and $ARGS rather than trying to declare them in .

Why does Mason display the wrong line numbers in errors?

In 1.1 and on, error line numbers correctly reflect the component source.

How can I get a list of components matching a path pattern?

This will work even with multiple component roots; you’ll get a combined list of all matching component paths in all component roots.

Can I access $m (the request object) from outside a component, e.g. inside a subroutine?

How can I make the |h escape flag work with my Russian/Japanese/other-non-western encoding?

To make |h escape just , &, and «, which is often what people want, put the following in your Apache configuration:

Or, in a top-level autohandler:

When using multiple component roots, is there a way to explicitly call a component in a specific root?

People sometimes ask for the ability to do this. We feel it’s a bad idea because it would endanger the cleanliness of multiple component roots in both behavior and implementation. As it stands now, the rules are very easy to understand and the implementation is very clean and isolated; only the resolver really needs know about multiple component roots.

If you want to be able to explicitly refer to components in a given root, put an extra subdirectory between the root and the components. e.g. put your components in

then add the root as

Now you can prefix a path with /global to refer to any component in that root.

Alternatively, [http://search.cpan.org/dist/MasonX-Request-ExtendedCompRoot MasonX::Request::ExtendedCompRoot] is a subclass of Mason that does allow you to call components in a specific component root.

Is there a syntax checker like perl -c for components?

The best you can do is write a standalone script that mimics your web environment as much as possible — in particular, declaring the same globals and loading the same modules. Instead of actually executing components, your script need only load them with $interp->load(). This method will throw a fatal error if a component fails to load.

HTTP AND HTML

How do I access GET or POST arguments?

How can I access the raw content of a POST in a Mason component?

Apache/mod_perl has an easier way of doing it than CGI/FCGi, which uses FakeApache. As you can see from the comment, since FakeApache implements read, I couldn’t get it to be completely dynamic:

Probably $r->params does not work. there is no such method in ‘man Apache’

— Rajesh Kumar Mallah.

What happens if I include query args in a POST ?

Should I use CGI .pm to read GET/POST arguments?

Can I use CGI .pm to output HTML constructs?

You have to give the empty string argument or CGI will try to read GET/POST arguments.

To print HTML constructs returned by CGI functions, just enclose them in , e.g.

How do I modify the outgoing HTTP headers?

How do I do an external redirect?

In Mason 1.1x, use the [=$m->redirect] method.

See the next question if your redirect isn’t producing the right status code.

When trying to use $m->redirect I get ‘Can’t locate object method redirect via package HTML::Mason. ApacheHandler’.

Why isn’t my status code reaching users’ browsers?

If you are using $m->abort or $m->redirect and there is an eval() wrapped directly or indirectly around the call, you must take care to propagate abort exceptions after the eval(). This looks like:

How can I handle file uploads under Mason?

The way you handle the submission depends on which args method you chose for the !ApacheHandler class.

Under the ‘ CGI ‘ method (default for 1.0x), you can use the [=$m->cgi_object] method to retrieve a CGI .pm object which can be used to retrieve the uploaded file. Here is an example using the ‘ CGI ‘ method:

Under the ‘mod_perl’ method (default for 1.1x), the request object available as [=$r] in your components will be an object in the Apache::Request class (as opposed to the Apache class). This object is capable of returning Apache::Upload objects for parameters which were file uploads. Please see the [Apache::Request http://search.cpan.org/

joesuf/libapreq-1.3/Request/Request.pm#Apache%3A%3AUpload_METHODS documentation] for more details. Here is an example using the ‘mod_perl’ method:

For more information on how to manually set the args method, see the !ApacheHandler documentation.

If you are using CGI .pm, there are some configuration issues to be aware of. CGI .pm needs a tmp directory, and you probably want to be able to specify what that directory is.

Try doing this in your httpd.conf or handler.pl:

You must do this _before_ you load either the HTML::Mason or HTML::Mason. ApacheHandler modules.

That may change which directories CGI tries to use.

You could also try

during startup, either in your httpd.conf or handler.pl

The root of the problem is probably that the temp directory is being chosen when the module loads uring server startup while its still root. It sees it can write to /usr/tmp and is happy. Then when actually running as nobody it dies.

I bet Lincoln would welcome a patch (hint, hint). One solution would be to check if you’re running under mod_perl and you’re root. If so, then check Apache->server->uid and see if that id can write to the temp directory too.

How can I redirect the current request to be a file download?

How can I manipulate cookies?

One thing to avo >POST requests has caused people problems. It seems that Apache::Cookie and Apache::Request make a better pair.

How can I populate form values automatically?

This will work for any component that contains a complete form in its output.

If you are using Apache::Request to process incoming arguments under mod_perl (the default as of 1.10), then you can also do this:

These two examples are slightly different from each other, in that each makes a different set of parameters available to HTML:: !FillInForm. In the first example, the arguments used are those that were explicitly passed to the component. In the second example, the arguments are those that were passed in the initial HTTP request. Of course, variations on this are possible by mixing and matching %ARGS, $m->request_args, $m->caller_args, and so on.

INSTALLATION

What else do I need to use Mason?

What platforms does Mason run on?

Can I run Mason outside a web server?

Can I run Mason via CGI ?

The examples in the docs requires that you have Mason 1.10+ installed.

Note that running Mason under CGI (or other non-persistent environments) will entail a substantial performance hit, since the perl interpreter will have to load, load up Mason and its supporting modules for every CGI execution. Using mod_perl or similar persistent environments (SpeedyCGI, FastCGI, etc.) avoids this performance bottleneck.

Can I use Mason with Apache/mod_perl 2.0?

Where can I find a web host supporting Mason?

What does the error Can’t locate object method ‘ TIEHASH ‘ via package ‘Apache::Table’ mean?


To fix the problem, you’ll have to recompile your server, adding the PERL_TABLE_API=1 flag (or EVERYTHING=1).

If you can’t recompile your server, you can edit the Mason source code. Find a line in ApacheHandler.pm that looks like this (it’s line 365 in Mason 1.04):

and change it to:

Recent versions of Mason use that, or a variant of it.

What does the error Can’t locate Apache/Request.pm in @INC m

You can either install libapreq, or change args_method to ‘ CGI ‘. The latter is a bit slower and uses more memory.

Why am I getting segmentation faults (or silently failing on startup)?

* Are you using a dynamically-linked mod_perl? DSO mod_perl builds were unstable for a long time, although they might finally be getting better. Rebuild Apache with mod_perl linked statically and see if the problem goes away. Also see http://perl.apache.org/docs/1.0/guide/install.html#When_DSO_can_be_Used.

* Earlier versions of XML::Parser and Apache could conflict, because both would statically compile in expat for XML parsing. This was fixed as of Apache version 1.3.20 and XML::Parser 2.30, both of which can be compiled against the same shared libexpat. You can also build Apache with ‘—disable-rule=EXPAT’. Matthew Kennedy points out that ‘If «strings `which httpd` | grep -i xml» returns anything, you have this problem.’

Мастер Йода рекомендует:  Задача о нахождении средней зарплаты трех работников при ограничении на передаваемую между ними

* Are you using Perl 5.6.0? Though not widespread, Perl 5.6.0 can generate sporadic segmentation faults at runtime for some Perl code. Specifically, evals of moderate complexity appear problematic. And, since Mason uses lots of evals of moderate complexity, you can’t avoid them. If the two suggestions above don’t solve your segfault problem and you are running Perl 5.6.0, try upgrading to Perl 5.6.1.

Where did the name come from?

Is Mason fast?

Although benchmarks on [http://chamas.com/bench/ Apache Hello World! benchmarks] site shows that Mason code is five (simple Hello World page, [=hello.mas]) to ten (heavyweight template, [=h2000.mas]) times slower than mod_perl solution.

Beware of «Hello World!» and other simple benchmarks. While these benchmarks do a good job of measuring the setup and initialization time for a package, they are typically not good measures of how a package will perform in a complex, real-world application. As with any program, the only way to know if it meets your requirements is to test it yourself.

In general, however, if your application is fast enough in pure mod_perl, it will most likely be fast enough under HTML::Mason as well.

How can I make my Mason application run faster?

If your application still needs to run faster, consider using Mason’s caching methods ($m->cache and $m->cache_self) to avoid regenerating dynamic content unnecessarily.

Does Mason leak memory?

If you do find other memory leaks that are traceable to Mason, please check the known bugs list to make sure it hasn’t already been reported. If it hasn’t, simplify your handler.pl (if you have one) and the offending component as much as possible, and post your findings to the mason-users mailing list.

Of course it is always possible for your own component code to leak, e.g. by creating and not cleaning up global variables. And mod_perl processes do tend to grow as they run because of «copy-on-write» shared-memory management. The mod_perl documentation and performance faq make good bedtime reading.

If you are using RedHat’s mod_perl RPM, or another DSO mod_perl installation, you will leak memory and should switch to a statically compiled mod_perl.

Why are my config file changes not taking effect?

For more details see «Server Stopping and Restarting» in the mod_perl guide.

2. Note that you cannot use Mason httpd parameters (MasonCompRoot, MasonErrorMode, etc.) and a handler.pl script that creates an ApacheHandler object at the same time. Depending on how you declare your PerlHandler, one or the other will always take precedence and the other will be ignored. For more details see «Site Configuration Methods» in the Admin manual.

What filename extensions should I use for Mason components?

The Mason team now recommends a filenaming scheme with extensions like .html, .txt, .pl for top-level components, and .mhtml, .mtxt, .mpl for internal (non-top-level) components.

Whatever naming scheme you choose should ideally accomplish three things:

* Distinguish top-level from internal components. This is obviously crucial for security.

* Distinguish output components from those that compute and return values. This improves clarity, and forces the component writer to decide between outputting and returning, as it is bad style to do both.

* Indicate the type of output of a component: text, html, xml, etc. This improves clarity, and helps browsers that ignore content-type headers (such as IE ) process non-HTML pages correctly.

Can I serve images through a HTML::Mason server?

How can I prevent a particular subdirectory from being handled by HTML::Mason?

Or suppose you have a «/cgi-bin» that you want to process via CGI:

When you have multiple Location directives, the latest ones in the configuration have the highest precedence. So to combine the previous directive with a typical Mason directive:

More generally, you can use various Apache configuration methods to control which handlers are called for a given request. Ken Williams uses a FilesMatch directive to invoke Mason only on requests for «.html» files:

Or you could reverse this logic, and write FilesMatch directives just for gifs and jpegs, or whatever.

If you are using a handler.pl, you can put the abort decision in your handler() routine. For example, a line like the following will produce the same end result as the directive, above.

However, performance will not be as good as the all-Apache configuration.

Why am I getting 404 errors for pages that clearly exist?

If you believe the file is in fact inside the component root and HTML::Mason is in error, it may be because you’re referring to the Apache document root or the HTML::Mason component root through a symbolic link. The symbolic link may confuse HTML::Mason into thinking that two directories are different when they are in fact the same. This is a known «bug», but there is no obvious fix at this time. For now, you must refrain from using symbolic links in either of these configuration items.

The same thing could also happen in any context with more than one way to specify a canonical filename. For example, on Windows, if your document root starts with «C:» and your component root starts with «c:», you might have this problem even though both paths should resolve to the same file.

With Mason 0.895 and above, if you set Apache’s LogLevel to warn, you will get appropriate warnings for these Mason-related 404s.

Some of my pages are being served with a content type other than text/html. How do I get HTML::Mason to properly set the content type?

This indicates that files with no extension and files with an unknown extension should be treated as text/html. By default, Apache would treat them as text/plain.

Microsoft Internet Explorer displays my page just fine, but Netscape or other browsers just display the raw HTML code.

The solution is to set your default content-type to text/html. See previous question.

My configuration prevents HTML::Mason from processing anything but html and text extensions, but I want to generate a dynamic image using HTML::Mason. How can I get HTML::Mason to set the correct MIME type?

How do I bring in external modules?

How do I adjust Perl’s INC path so it can find my modules?

How do I use Mason in conjunction with UserDir to support Mason in user’s home directories?

Outside your handler subroutine:

Inside your handler subroutine:

How do I connect to a database from Mason?

The long answer is, of course, longer. A good deal of thought should be put into how a web application talks to databases that it depends on, as these interconnections can easily be both performance bottlenecks and very un-robust.

Most people use some sort of connection pooling — opening and then re-using a limited number of database connections. The Apache::DBI module prov >DBI- >connect() will transparently reuse an already open connections, if it can.

The «right» place to ask Apache::DBI for database handles is often in a top level autohandler.

Alternately, $dbh could be a global variable which you set via MasonAllowGlobals.

You can use Apache::DBI in your httpd.conf file quite easily simply by adding:

If you want to do more with Apache::DBI, like call connect_on_init, you can use a

Others may simply use a handler.pl file. Georgiou Kiriakos writes:

Regardless of whether you set up global $dbh variables in handler.pl, the static sections of handler.pl should set up Apache::DBI stuff:

How come a certain piece of Perl code runs fine under regular perl, but fails under Mason?

If something suddenly stops working when you place it in a Mason environment, the problem is far more likely to rest with the following environmental changes than with Mason itself:

* With mod_perl, the server is running under a different user/group and thus has different permissions for the resource you’re trying to access

* With mod_perl, code can stay resident in the perl interpreter for a long time.

* Your headers may be sent differently under mod_perl than under your previous CGI situation (or whatever it was)

Mason does not have anything to do with sending mail, or accessing a database, or maintaining user accounts, or server authentication, so if your problems are in areas like these, your time will be better spent looking at other environmental changes like the ones mentioned above.

I’m using HTML::Mason. ApacheHandler and I have decline_dirs disabled and am using a dhandler to handle directory requests. But when a request comes in without the final slash after the directory name, relative links are broken. What gives?

UPGRADING TO 1 .1x

After upgrading, I see this error whenever I load a page: The following parameter was passed in the call to HTML::Mason::Component::FileBased->new() but was not listed in the validation options: create_time

When I try to start my server I see an error like: The resolver class your Interp object uses does not implement the apache_request_to_comp_path’ method.

Are you using a handler.pl file created before version 1.10? Please see the handler.pl sample that comes with the latest version of Mason.

You are explicitly creating an Interp object in your handler.pl and then passing that to ApacheHandler->new.

Instead, simply pass all of your Interp parameters to ApacheHandler->new directly. The parameters will end up going where they belong.

HTML::Mason::Admin

HTML::Mason::Admin — Mason Administrator’s Guide

This guide is intended for the sys admin/web master in charge of installing, configuring, or tuning a Mason system.

The Config.pm file contains global settings for your system, such as the presence or absence of certain optional modules.

Makefile.PL initially creates Config.pm based on your environment, placing it in the lib/HTML/Mason subdirectory of the distribution. After that, you can edit it by hand, following the comments inside. In most cases, you will not need to edit it.

«make install» copies Config.pm to your Perl library directory (e.g. /usr/lib/perl5/site_perl/HTML/Mason ) along with the other module files. This allows Mason internally to grab the configuration data with « use HTML::Mason::Config ».

When upgrading from a previous version, «make install» will maintain the previous Config.pm values.

There are three ways to configure a Mason site:


Minimal configuration, relying on default Mason behavior. Simplest and least flexible.

Configuration via httpd.conf directives. Medium complexity and flexibility.

Configuration via a handler script (handler.pl). Most complex but most flexible.

The next three sections discuss these methods in detail. We recommend that you start with the simplest method and work your way forward as the need for flexibility arises.

It is important to note that you cannot mix httpd.conf configuration directives with a handler script. Depending on how you declare your PerlHandler , one or the other will always take precedence and the other will be ignored.

A simple configuration looks like:

MasonCompRoot specifies the component root , the top of your component source tree. In simple configurations the component root is the same as the server’s DocumentRoot . (See CONFIGURING VIRTUAL SITES to understand why the component root and DocumentRoot might differ.)

When Mason handles a request, the requested filename must be underneath your component root — that gives Mason a legitimate component to start with. If the filename is not underneath the component root, Mason will place a warning in the error logs and return 404.

MasonDataDir specifies the data directory , a writable directory that Mason uses for various features and optimizations. Mason will create the directory on startup, if necessary, and set its permissions according to the web server User/Group.

Mason’s configuration parameters are set via mod_perl’s PerlSetVar and PerlAddVar directives. The latter directive is only available in mod_perl version 1.24 and greater. Though these parameters are all strings, Mason treats them in different ways. The different parameter types are:


    string

The variable’s value is simply taken literally and used. Quotes are necessary if the string contains whitespace.
boolean

The variable’s value is used as a boolean, and is subject to Perl’s rules on truth/falseness. It is recommended that you use 0 (false) or 1 (true) for these arguments.
code

The string is treated as a piece of code and eval ‘ed. This is used for parameters that expect subroutine references. For example, an anonymous subroutine might look like:

A named subroutine call would look like this:

To set a list parameter, use PerlAddVar for the values, like this:

As noted above, PerlAddVar is only available in mod_perl 1.24 and up. This means that it is only possible to assign a single value (using PerlSetVar ) to list parameters if you are using a mod_perl older than 1.24.

Almost all of Mason’s configuration parameters correspond to new() parameters for the HTML::Mason::Parser , HTML::Mason::Interp , and HTML::Mason::ApacheHandler objects. Configuration parameters are named predictably by taking the mixed-caps form of the new() parameter and prefixing «Mason». For example, comp_root becomes MasonCompRoot and data_dir becomes MasonDataDir.

Corresponds to the allow_globals parameter.
MasonDefaultEscapeFlags — string

Corresponds to the default_escape_flags parameter.
MasonIgnoreWarningsExpr — string

Corresponds to the ignore_warnings_expr parameter.
MasonInPackage — string

Corresponds to the in_package parameter.
MasonPostamble — string

Corresponds to the preamble parameter.
MasonTaintCheck — boolean

Corresponds to the taint_check parameter.
MasonUseStrict — boolean

Corresponds to the use_strict parameter.
MasonPreprocess — code

Corresponds to the preprocess parameter.
MasonPostprocess — code

Corresponds to the postprocess parameter.

Correponds to the comp_root parameter. This parameter can either be a single value, such as ‘/foo/comp/root’, or a list of keys and values such as:

See the Multiple component roots section for more details on multiple component roots.
MasonDataDir — string (required)

Corresponds to the allow_recursive_autohandlers parameter.
MasonAutohandlerName — string

Corresponds to the autohandler_name parameter.
MasonCodeCacheMaxSize — string

Corresponds to the code_cache_max_size parameter.
MasonCurrentTime — string

Corresponds to the current_time parameter.
MasonDataCacheDir — string

Corresponds to the data_cache_dir parameter.
MasonDieHandler — code or 0

Corresponds to the die_handler parameter.
MasonMaxRecurse — string

Corresponds to the max_recurse parameter.
MasonOutMethod — code

Corresponds to the out_method parameter.
MasonOutMode — string

Corresponds to the out_mode parameter.
MasonPreloads — list

Corresponds to the preloads parameter.
MasonStaticFileRoot — string

Corresponds to the static_file_root parameter.
MasonSystemLogEvents — string

Corresponds to the system_log_events parameter.
MasonSystemLogFile — string

Corresponds to the system_log_file parameter.
MasonSystemLogSeparator — string

Corresponds to the system_log_separator parameter.


MasonUseAutohandlers — boolean

Corresponds to the use_autohandlers parameter.
MasonUseDataCache — boolean

Corresponds to the use_data_cache parameter.
MasonUseDhandlers — boolean

Corresponds to the use_dhandlers parameter.
MasonUseObjectFiles — boolean

Corresponds to the use_object_files parameter.
MasonUseReloadFile — boolean

Corresponds to the use_reload_file parameter.

Correponds to the apache_status_title parameter.
MasonAutoSendHeaders — boolean

Correponds to the auto_send_headers parameter.
MasonDebugHandlerProc — string

Correponds to the error_mode parameter.
MasonTopLevelPredicate — code

Correponds to the top_level_predicate parameter.

These are the only parameters that do not correspond to new() parameters.


    MasonArgsMethod — string

Valid values for this parameter are CGI or mod_perl . This determines whether to use the CGI or Apache::Request module for argument handling. Please see HTML::Mason::ApacheHandler/PARAMETERS TO THE use() DECLARATION for more details.

This can only be set once, regardless of how you set MasonMultipleConfig.

If this parameter is true, Mason assumes that you may have multiple sets of configuration directives defined, perhaps for multiple locations or virtual hosts. This means that Mason will create a new set of parser/interp/handler objects for every request. If this parameter is false, Mason simply creates a single set at server startup to maximize shared memory. Defaults to false.

If you set this option, the Apache child processes will need the proper permissions to create the data directories.

To maximize shared memory, you should put your Mason configuration directives in the configuration file before you load the HTML::Mason::ApacheHandler module via a PerlModule directive.

Because certain features were not available in mod_perl before 1.21_01, Mason will be less memory efficient when using those older versions.

For maximum flexibility, you may choose to write a custom script to create your Mason objects and handle requests. In our documentation and examples we call this script handler.pl , though you may name it whatever you like.

The handler.pl file is responsible for creating the three Mason objects and supplying the many parameters that control how your components are parsed and executed. It also provides the opportunity to execute arbitrary code at three important junctures: the server initialization, the beginning of a request, and the end of a request. A wide set of behaviors can be implemented with a mere few lines of well-placed Perl in your handler.pl . In this section we present the basics of setting up handler.pl as well as some ideas for more advanced applications.

This method requires only a bit of Apache configuration. First, use a PerlRequire directive to declare your handler.pl location (this can be anywhere, though the Apache conf/ subdirectory is a good place as any). Second, set your PerlHandler simply to HTML::Mason rather than HTML::Mason::ApacheHandler.

handler.pl creates three Mason objects: the Parser, Interpreter, and ApacheHandler. The Parser compiles components into Perl subroutines; the Interpreter executes those compiled components; and the Apache handler routes mod_perl requests to Mason. These objects are created once in the parent httpd and then copied to each child process.

These objects have a fair number of possible parameters. Only two of them are required, comp_root and data_dir ; these are discussed in the next two subsections. The various parameters are documented in the individual reference manuals for each object: HTML::Mason::Parser , HTML::Mason::Interp , and HTML::Mason::ApacheHandler .

The advantage of embedding these parameters in objects is that advanced configurations can create more than one set of objects, choosing which set to use at request time. For example, suppose you have a staging site and a production site running on the same web server, distinguishing between them with a configuration variable called version:

You may specify multiple component roots to be searched in the spirit of Perl’s @INC. To do so you must specify a list of lists:

Each pair consists of a key and root. The key is a string that identifies the root mnemonically to a component developer. Keys are case-insensitive and must be distinct.

This specifies two component roots, a main component tree and a private tree which overrides certain components. The order is respected ala @INC, so private is searched first and main second. (I chose the => notation here because it looks cleaner, but note that this is a list of lists, not a hash.)

The key has several purposes. Object and data cache filenames use the (uppercased) key to make sure different components sharing the same path have different cache and object files. For example, if a component /foo/bar is found in ‘private’, then the object file will be

and the cache file

The key is also included whenever Mason prints the component title, as in an error message:

This lets you know which version of the component was running.

Components will often need access to external Perl modules. Any such modules that export symbols should be listed in handler.pl , rather than the standard practice of using a PerlModule configuration directive. This is because components are executed inside the HTML::Mason::Commands package, and can only access symbols exported to that package. Here’s sample module list:

In any case, for optimal memory utilization, make sure all Perl modules are used in the parent process, and not in components. Otherwise, each child allocates its own copy and you lose the benefit of shared memory between parent processes and their children. See Vivek Khera’s mod_perl tuning FAQ (perl.apache.org/tuning) for details.

Unix web servers that run on privileged ports like 80 start with a root parent process, then spawn children running as the ‘User’ and ‘Group’ specified in httpd.conf. This difference leads to permission errors when child processes try to write files or directories created by the parent process.

To work around this conflict, Mason remembers all directories and files created at startup, returning them in response to interp->files_written . This list can be fed to a chown() at the end of the startup code in handler.pl :

With just a few lines in handler.pl you can make a global hash (e.g. %session ) available to all components containing persistent user session data. If you set a value in the hash, you will see the change in future visits by the same user. The key piece is Jeffrey Baker’s Apache::Session module, available from CPAN.

The file eg/session_handler.pl in the distribution contains the lines to activate cookie-based sessions using Apache::Session and CGI::Cookie. You can use eg/session_handler.pl as your new handler.pl base, or just copy out the appropriate pieces to your existing handler.pl .

The session code is customizable; you can change the user ID location (e.g. URL instead of cookie), the user data storage mechanism (e.g. DBI database), and the name of the global hash.

Global variables generally make programs harder to read, maintain, and debug, and this is no less true for Mason. Due to the persistent mod_perl environment, globals require extra initialization and cleanup care. And the highly modular nature of Mason pages does not mix well with globals: it is no fun trying to track down which of twenty components is stepping on your variable. With the ability to pass parameters and declare lexical ( my ) variables in components, there is very little need for globals at all.

That said, there are times when it is very useful to make a value available to all Mason components: a DBI database handler, a hash of user session information, the server root for forming absolute URLs. Usually you initialize the global in your handler.pl , either outside the handler() subroutine (if you only need to set it once) or inside (if you need to set it every request).

Mason by default parses components in strict mode, so you can’t simply start referring to a new global or you’ll get a fatal warning. The solution is to invoke use vars inside the package that components execute in, by default HTML::Mason::Commands :

Alternatively you can use the Parser/allow_globals parameter or method:

The only advantage to allow_globals is that it will do the right thing if you’ve chosen a different package for components to run in (via the Parser/in_package Parser parameter.)

Similarly, to initialize the variable in handler.pl , you need to set it in the component package:

Alternatively you can use the Interp/set_global Interp method:

Again, set_global will do the right thing if you’ve chosen a different package for components.

Now when referring to these globals inside components, you can use the plain variable name:

Mason should be prevented from serving images, tarballs, and other binary files as regular components. Such a file may inadvertently contain a Mason character sequence such as « handler(), e.g.:

This line allows text/html and text/plain to pass through but not much else. It is included (commented out) in the default handler.pl .

Another way is specifying a filename pattern in the Apache configuration, e.g.:

This directs Mason to handle only files with .html, .txt, or no extension.

Users may exploit a server-side scripting environment by invoking scripts with malicious or unintended arguments. Mason administrators need to be particularly wary of this because of the tendency to break out «subroutines» into individually accessible file components.

For example, a Mason developer might create a helpful shared component for performing sql queries:

This is a perfectly reasonable component to create and call internally, but clearly presents a security risk if accessible via URL:

Of course a web user would have to obtain the name of this component through guesswork or other means, but obscurity alone does not properly secure a system. Rather, you should choose a site-wide policy for distinguishing top-level components from private components, and make sure your developers stick to this policy. You can then prevent private components from being served.

One solution is to place all private components inside a directory, say /private, that lies under the component root but outside the document root.

Another solution is to decide on a naming convention, for example, that all private components begin with «_», or that all top-level components must end in «.html». Then turn all private requests away with a 404 NOT_FOUND (rather than, say, a 403 FORBIDDEN which would provide more information than necessary). Use either an Apache directive

or a handler.pl directive:

Even after you’ve safely protected internal components, top-level components that process arguments (such as form handlers) still present a risk. Users can invoke such a component with arbitrary argument values via a handcrafted query string. Always check incoming arguments for validity and never place argument values directly into SQL, shell commands, etc. Unfortunately, Mason does not yet work with with Perl’s taint checking which would help ensure these principles.

By default Mason will decline requests for directories, leaving Apache to serve up a directory index or a FORBIDDEN as appropriate. Unfortunately this rule applies even if there is a dhandler in the directory: /foo/bar/dhandler does not get a chance to handle a request for /foo/bar.

If you would like Mason to handle directory requests, do the following:

1. Set the ApacheHandler/decline_dirs ApacheHandler parameter to 0.

2. If your handler.pl contains the standard «return -1» line to decline non-text requests (as given in the previous section), add a clause allowing directory types:

The dhandler that catches a directory request is responsible for setting a reasonable content type.

This section explains how standard Mason features work and how to administer them.

Cache files are implemented using MLDBM , an interface for storing persistent multi-level data structures. MLDBM , in turn, uses one of several DBM packages ( DB_File , GDBM ) and one of several serialization mechanisms ( Data::Dumper , FreezeThaw or Storable ). Mason’s Config.pm controls which packages are used.

The most important task is selecting a good DBM package. Most standard DBM packages ( SDBM , ODBM , NDBM ) are unsuitable for data caching due to significant limitations on the size of keys and values. Perl only comes with SDBM , so you’ll need to obtain a good-quality package if you haven’t already. At this time the best options are Berkeley DB ( DB_File ) version 2.x, available at www.sleepycat.com, and GNU’s gdbm ( GDBM ), available at GNU mirror sites everywhere. Stay away from Berkeley DB version 1.x on Linux which has a serious memory leak (and is unfortunately pre-installed on many distributions).

As far as the serialization methods, all of them should work fine. Data::Dumper is probably simplest: it comes with the latest versions of Perl, is required by Mason anyway, and produces readable output (possibly useful for debugging cache files). On the other hand Storable is significantly faster than the other options according to the MLDBM documentation.

Data caching will not work on systems lacking flock(), such as Windows 95 and 98. Administration

Once set up, data caching requires little administration. When a component calls $m->cache or $m->cache_self for the first time, Mason automatically creates a new cache file under data_dir/cache . The name of the file is determined by encoding the path as follows:

like URL encoding with a ‘+’ escape character. For example, the cache file for component /foo/bar is data_dir/cache/foo+2fbar .

Currently Mason never deletes cache files, not even when the associated component file is modified. (This may change in the near future.) Thus cache files hang around and grow indefinitely. You may want to use a cron job or similar mechanism to delete cache files that get too large or too old. For example:

In general you can feel free to delete cache files periodically and without warning, because the data cache mechanism is explicitly not guaranteed — developers are warned that cached data may disappear anytime and components must still function.

If some reason you want to disable data caching, specify use_data_cache =>0 to the Interp object. This will cause all $m->cache calls to return undef without doing anything.

A debug file is a Perl script that creates a fake Apache request object ( $r ) and calls the same PerlHandler that Apache called. Debug files are created under data_dir/debug/ for authenticated users, and in data_dir/debug/anon for anonymous users.

Debug files can only be used with the handler.pl configuration method.

Several ApacheHandler parameters are required to activate and configure debug files:

The debug_mode parameter indicates which requests should produce a debug file: «all», «none», or «error» (only if a error occurs). debug_perl_binary

The full path to your Perl binary — e.g. /usr/bin/perl . This is used in the Unix «shebang» line at the top of each debug file. debug_handler_script

The full path to your handler.pl script. Debug files invoke handler.pl just as Apache does as startup, to load needed modules and create Mason objects. debug_handler_proc

The name of the request handler defined in handler.pl . This routine is called with the saved Apache request object.

Here’s a sample ApacheHandler constructor with all debug options:

When replaying a request through a debug file, the global variable $HTML::Mason::IN_DEBUG_FILE will be set to 1. This is useful if you want to omit certain flags (like preloading) in handler.pl when running under debug. For example:

The previewer is a web based utility that allows site developers to:


    .

View a site under a variety of simulated client conditions: browser, operating system, date, time of day, referer, etc.
.

View a debug trace of a page, showing the component call tree and indicating which parts of the page are generated by which components.

The web-based previewer interface (a single component, actually) allows the developer to select a variety of options such as time, browser, and display mode. The set of these options together is called a previewer configuration. Configurations can be saved under one of several preview ports. For more information on how the previewer is used, see HTML::Mason::Devel .

Follow these steps to activate the Previewer:


    .

Choose a set of preview ports, for example, 3001 to 3005.
.

In httpd.conf, put a Listen in for each port. E.g.

You’ll also probably want to restrict access to these ports in your access.conf. If you have multiple site developers, it is helpful to use username/password access control, since the previewer will use the username to keep configurations separate.
.

In your handler.pl , add the line

somewhere underneath «use HTML::Mason». Then add code to your handler routine to intercept Previewer requests on the ports defined above. Your handler should end up looking like this:

The three «new» lines inside the if block should look exactly the same as the lines at the top of handler.pl . Note that these separate Mason objects are created for a single request and discarded. The reason is that the previewer may alter the objects’ settings, so it is safer to create new ones every time.
.

Copy the Previewer component («samples/preview») to your component root (you may want to place it at the top level so that http://www.yoursite.com/preview calls up the previewer interface). Edit the «CONFIGURATION» block at the top to conform to your own Mason setup.

To test whether the previewer is working: restart your server, go to the previewer interface, and click «View». You should see your site’s home page.

Mason will log various events to a system log file if you so desire. This can be useful for performance monitoring and debugging.

The format of the system log was designed to be easy to parse by programs, although it is not unduly hard to read for humans. Every event is logged on one line. Each line consists of multiple fields delimited by a common separator, by default ctrl-A. The first three fields are always the same: time, the name of the event, and the current pid ($$). These are followed by one or more fields specific to the event.

The request number is an incremental value that uniquely identifies each request for a given child process. Use it to match up REQ_START/REQ_END pairs.

To turn on logging, specify a string value to system_log_events containing one or more event names separated by ‘|’. In additional to individual event names, the following names can be used to specify multiple events:

For example, to log REQ_START, REQ_END, and COMP_LOAD events, you could use system_log_events => «REQUEST|COMP_LOAD» Note that this is a string, not a set of constants or’d together.

By default, the system log will be placed in data_dir/etc/system.log. You can change this with system_log_file .

The default line separator is ctrl-A. The advantage of this separator is that it is very unlikely to appear in any of the fields, making it easy to split() the line. The disadvantage is that it will not always display, e.g. from a Unix shell, making the log harder to read casually. You can change the separator to any sequence of characters with system_log_separator .

The time on each log line will be of the form «seconds.microseconds» if you are using Time::HiRes, and simply «seconds» otherwise. See Config.pm section.

Sample Log Parser

Here is a code skeleton for parsing the various events in a log. You can also find this in eg/parselog.pl in the Mason distribution.

Performance: REQUEST events are useful for analyzing the performance of all Mason requests occurring on your site, and identifying the slowest requests. eg/perflog.pl in the Mason distribution is a log parser that outputs the average compute time of each unique URL, in order from slowest to quickest.

Server activity: REQUEST events are useful for determining what your web server children are working on, especially when you have a runaway. For a given process, simply tail the log and find the last REQ_START event with that process id. (You can also use the Apache status page for this.)

Cache efficiency: CACHE events are useful for monitoring cache «hit rates» (number of successful reads over total number of reads) over all components that use a data cache. Because stores to a cache are more expensive than reads, a high hit rate is essential for the cache to have a beneficial effect. If a particular cache hit rate is too low, you may want to consider changing how frequently it is expired or whether to use it at all.

Load frequency: COMP_LOAD events are useful for monitoring your code cache. Too many loads may indicate that your code cache is too small. Also, if you can turn off the code cache for a short time, COMP_LOAD events will tell you which components are loaded most often and thus good candidates for preloading.

This section explains Mason’s various performance enhancements and how to administer them.

When Mason loads a component, it places it in a memory cache.

The maximum size of the cache is specified with the Interp/code_cache_max_size Interp parameter; default is 10MB. When the cache fills up, Mason frees up space by discarding a number of components. The discard algorithm is least frequently used (LFU), with a periodic decay to gradually eliminate old frequency information. In a nutshell, the components called most often in recent history should remain in the cache. Very large components (over 20% of the maximum cache size) never get cached, on the theory that they would force out too many other components.

Note that the «size» of a component in memory cannot literally be measured. It is estimated by the length of the source text plus some overhead. Your process growth will not match the code cache size exactly.

You can monitor the performance of the memory cache by turning on system logs and counting the COMP_LOAD events. If these are occurring frequently even for a long-running process, you may want to increase the size of your code cache.

You can prepopulate the cache with components that you know will be accessed often; see Preloading. Note that preloaded components possess no special status in the cache and can be discarded like any others.

Naturally, a cache entry is invalidated if the corresponding component source file changes.

To turn off code caching completely, set Interp/code_cache_max_size to 0.

The in-memory code cache is only useful on a per-process basis. Each process must build and maintain its own cache. Shared memory caches are conceivable in the future, but even those will not survive between web server restarts.

As a secondary, longer-term cache mechanism, Mason stores a compiled form of each component in an object file under data_dir/obj/ component-path . Any server process can eval the object file and save time on parsing the component source file. The object file is recreated whenever the source file changes.

Besides improving performance, object files are essential for debugging and interpretation of errors. Line numbers in error messages are given in terms of the object file. The curious-minded can peek inside an object file to see exactly how Mason converted a given component to a Perl object.

If you change any Parser options, you must remove object files previously created under that parser for the changes to take effect.

If for some reason you don’t want Mason to create object files, set the Interp/use_object_files Interp parameter to 0.

You can tell Mason to preload a set of components in the parent process, rather than loading them on demand, using the Interp/preloads Interp parameter. Each child server will start with those components loaded in the memory cache. The trade-offs are:

a small one-time startup cost, but children save time by not having to load the components memory

a fatter initial server, but the memory for preloaded components are shared by all children. This is similar to the advantage of using modules only in the parent process.

Try to preload components that are used frequently and do not change often. (If a preloaded component changes, all the children will have to reload it from scratch.)

Normally, every time Mason executes a component, it checks the last modified time of its source file to see if it needs to be reloaded. These file checks are convenient for development, but for a production site they degrade performance unnecessarily.

To remedy this, Mason has an accelerated mode that changes its behavior in two ways:

1. Does not check component source files at all, relying solely on object files. This means the developer or an automated system is responsible for recompiling any components that change and recreating object files, using the Parser/make_component Parser method.

2. Rather than continuously checking whether object files have changed, Mason monitors a «reload file» containing an ever-growing list of components that have changed. Whenever a component changes, the developer or an automated system is responsible for appending the component path to the reload file. The reload file is kept in data_dir/etc/reload.lst .

You can activate this mode with the Interp/use_reload_file Interp method.

The advantage of using this mode is that Mason stats one file per request instead of ten or twenty. The disadvantage is a increase in maintenance costs as the object and reload files have to be kept up-to-date. Automated editorial tools, and cron jobs that periodically scan the component hierarchy for changes, are two possible solutions. The Mason content management system automatically handles this task.

Site builders often maintain two versions of their sites: the production (published) version visible to the world, and the development (staging) version visible internally. Developers try out changes on the staging site and push the pages to production once they are satisfied.


The priorities for the staging site are rapid development and easy debugging, while the main priority for the production site is performance. This section describes various ways to adapt Mason for each case.

Mason can spew data in two modes. In «batch» mode Mason computes the entire page in a memory buffer and then transmits it all at once. In «stream» mode Mason outputs data as soon as it is computed. (This does not take into account buffering done by Apache or the O/S.) The default mode is «batch».

Batch mode has the advantage of better error handling. Suppose an error occurs in the middle of a page. In stream mode, the error message interrupts existing output, often appearing in an awkward HTML context such as the middle of a table which never gets closed. In batch mode, the error message is output neatly and alone.

Batch mode also offers more flexibility in controlling HTTP headers (see Devel/sending_http_headers) and in handling mid-request error conditions (see Request/clear_buffer).

Stream mode may help get data to the browser more quickly, allowing server and browser to work in parallel. It also prevents memory buildup for very large responses.

Since Apache does its own buffering, stream mode does not entail immediate delivery of output to the client. You must set $|=1 to turn off Apache buffering completely (generally not a good idea) or call $m->flush_buffer to flush the buffer selectively.

In terms of making your server seem responsive, the initial bytes are most important. You can send these early by calling $m->flush_buffer in key locations such as the common page header. However, this dilutes the advantages of batch mode mentioned above. Tradeoffs.

You control output mode by setting interp->out_mode to «batch» or «stream».

When an error occurs, Mason can respond by:


showing a detailed error message in the browser

die’ing, which sends a 501 to the browser and lets the error message go to the error logs.

The first option is ideal for development, where you want immediate feedback on the error. The second option is usually desired for production so that users are not exposed to messy error messages. You control this option by setting ah->error_mode to «html» or «fatal» respectively.

As discussed in the debugging section, you can control when Mason creates a debug file. While creating a debug file is not incredibly expensive, it does involves a bit of work and the creation of a new file, so you probably want to avoid doing it on every request to a frequently visited site. I recommend setting debug_mode to ‘all’ in development, and ‘error’ or ‘none’ in production.

Consider reload files only for frequently visited production sites.

These examples extend the single site configurations given so far.

If you want to share some components between your sites, arrange your httpd.conf so that all DocumentRoots live under a single component space:

The directory structure for this scenario might look like:

Incoming URLs for each site can only request components in their respective DocumentRoots, while components internally can call other components anywhere in the component space. The shared/ directory is a private directory for use by components, inaccessible from the Web.

Sometimes your sites need to have completely distinct component hierarchies, e.g. if you are providing Mason ISP services for multiple users. In this case the component root must change depending on the site requested. Since you can’t change an interpreter’s component root dynamically, you need to maintain separate Mason objects for each site in your handler.pl :

We assume each virtual server configuration section has a

Above we pre-create all Mason objects in the parent. Another scheme is to create objects on demand in the child:

Получить URL запроса в HTML :: Mason

December 2020

1.1k раз

Как мы можем найти URL запроса GET на сайте PERL с помощью HTML :: Mason. Я попытался с помощью $ м объекта от Мейсона.

1 ответы

In addition to the $m Mason request object you also have $r the Apache request object. The uri method will return the path component of the requested URL:

If you want the requested URL including the query string, you can use the unparsed_uri method:

SYNOPSIS

In httpd.conf or .htaccess:

A script at /cgi-bin/mason_handler.pl :

A .html component somewhere in the web server’s document root:

DESCRIPTION

This module lets you execute Mason components in a CGI environment. It lets you keep your top-level components in the web server’s document root, using regular component syntax and without worrying about the particular details of invoking Mason on each request.

If you want to use Mason components from within a regular CGI script (or any other Perl program, for that matter), then you don’t need this module. You can simply follow the directions in the Using Mason from a standalone script section of the administrator’s manual.

This module also provides an $r request object for use inside components, similar to the Apache request object under HTML::Mason::ApacheHandler , but limited in functionality. Please note that we aim to replicate the mod_perl functionality as closely as possible — if you find differences, do not depend on them to stay different. We may fix them in a future release. Also, if you need some missing functionality in $r , let us know, we might be able to provide it.

Finally, this module alters the HTML::Mason::Request object $m to provide direct access to the CGI query, should such access be necessary.

HTML::Mason::CGIHandler Methods

  • new()
    Creates a new handler. Accepts any parameter that the Interpreter accepts.

If no comp_root parameter is passed to new() , the component root will be $ENV .

handle_request()
Handles the current request, reading input from $ENV or STDIN and sending headers and component output to STDOUT . This method doesn’t accept any parameters. The initial component will be the one specified in $ENV .

handle_comp()
Like handle_request() , but the first (only) parameter is a component path or component object. This is useful within a traditional CGI environment, in which you’re essentially using Mason as a templating language but not an application server.

handle_component() will create a CGI query object, parse the query parameters, and send the HTTP header and component output to STDOUT. If you want to handle those parts yourself, see the Using Mason from a standalone script section of the administrator’s manual.

handle_cgi_object()
Also like handle_request() , but this method takes only a CGI object as its parameter. This can be quite useful if you want to use this module with CGI::Fast.

The component path will be the value of the CGI object’s path_info() method.

request_args()
Given an HTML::Mason::FakeApache object, this method is expected to return a hash containing the arguments to be passed to the component. It is a separate method in order to make it easily overrideable in a subclass.

interp()
Returns the Mason Interpreter associated with this handler. The Interpreter lasts for the entire lifetime of the handler.

$r Methods

  • headers_in()
    This works much like the Apache method of the same name. In an array context, it will return a %hash of response headers. In a scalar context, it will return a reference to the case-insensitive hash blessed into the HTML::Mason::FakeTable class. The values initially populated in this hash are extracted from the CGI environment variables as best as possible. The pattern is to merely reverse the conversion from HTTP headers to CGI variables as documented here: http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html#6.1.

header_in()
This works much like the Apache method of the same name. When passed the name of a header, returns the value of the given incoming header. When passed a name and a value, sets the value of the header. Setting the header to undef will actually unset the header (instead of setting its value to undef ), removing it from the table of headers returned from future calls to headers_in() or header_in() .

headers_out()
This works much like the Apache method of the same name. In an array context, it will return a %hash of response headers. In a scalar context, it will return a reference to the case-insensitive hash blessed into the HTML::Mason::FakeTable class. Changes made to this hash will be made to the headers that will eventually be passed to the CGI module’s header() method.

header_out()
This works much like the Apache method of the same name. When passed the name of a header, returns the value of the given outgoing header. When passed a name and a value, sets the value of the header. Setting the header to undef will actually unset the header (instead of setting its value to undef ), removing it from the table of headers that will be sent to the client.

The headers are eventually passed to the CGI module’s header() method.

err_headers_out()
This works much like the Apache method of the same name. In an array context, it will return a %hash of error response headers. In a scalar context, it will return a reference to the case-insensitive hash blessed into the HTML::Mason::FakeTable class. Changes made to this hash will be made to the error headers that will eventually be passed to the CGI module’s header() method.

err_header_out()
This works much like the Apache method of the same name. When passed the name of a header, returns the value of the given outgoing error header. When passed a name and a value, sets the value of the error header. Setting the header to undef will actually unset the header (instead of setting its value to undef ), removing it from the table of headers that will be sent to the client.

The headers are eventually passed to the CGI module’s header() method.

One header currently gets special treatment — if you set a Location header, you’ll cause the CGI module’s redirect() method to be used instead of the header() method. This means that in order to do a redirect, all you need to do is:

You may be happier using the $m->redirect method, though, because it hides most of the complexities of sending headers and getting the status code right.

content_type()
When passed an argument, sets the content type of the current request to the value of the argument. Use this method instead of setting a Content-Type header directly with header_out() . Like header_out() , setting the content type to undef will remove any content type set previously.

When called without arguments, returns the value set by a previous call to content_type() . The behavior when content_type() hasn’t already been set is undefined — currently it returns undef .

If no content type is set during the request, the default MIME type text/html will be used.

method()
Returns the request method used for the current request, e.g., «GET», «POST», etc.

http_header()
This method returns the outgoing headers as a string, suitable for sending to the client.

send_http_header()
Sends the outgoing headers to the client.

notes()
This works much like the Apache method of the same name. When passed a $key argument, it returns the value of the note for that key. When passed a $value argument, it stores that value under the key. Keys are case-insensitive, and both the key and the value must be strings. When called in a scalar context with no $key argument, it returns a hash reference blessed into the HTML::Mason::FakeTable class.

pnotes()
Like notes() , but takes any scalar as an value, and stores the values in a case-sensitive hash.

subprocess_env()
Works like the Apache method of the same name, but is simply populated with the current values of the environment. Still, it’s useful, because values can be changed and then seen by later components, but the environment itself remains unchanged. Like the Apache method, it will reset all of its values to the current environment again if it’s called without a $key argument.

params()
This method returns a hash containing the parameters sent by the client. Multiple parameters of the same name are represented by array references. If both POST and query string arguments were submitted, these will be merged together.

Added $m methods

The $m object provided in components has all the functionality of the regular HTML::Mason::Request object $m , and the following:

    cgi_object()
    Returns the current CGI request object. This is handy for processing cookies or perhaps even doing HTML generation (but is that really what you want to do?). If you pass an argument to this method, you can set the request object to the argument passed. Use this with care, as it may affect components called after the current one (they may check the content length of the request, for example).

Note that the ApacheHandler class (for using Mason under mod_perl) also provides a cgi_object() method that does the same thing as this one. This makes it easier to write components that function equally well under CGIHandler and ApacheHandler.

cgi_request()
Returns the object that is used to emulate Apache’s request object. In other words, this is the object that $r is set to when you use this class.

HTML::Mason::FakeTable Methods

This class emulates the behavior of the Apache::Table class, and is used to store manage the tables of values for the following attributes of :

headers_in
headers_out
err_headers_out
notes
subprocess_env

HTML::Mason::FakeTable is designed to behave exactly like Apache::Table , and differs in only one respect. When a given key has multiple values in an Apache::Table object, one can fetch each of the values for that key using Perl’s each operator:

If anyone knows how Apache::Table does this, let us know! In the meantime, use get() or do() to get at all of the values for a given key ( get() is much more efficient, anyway).

Since the methods named for these attributes return an HTML::Mason::FakeTable object hash in a scalar reference, it seemed only fair to document its interface.

    new()
    Returns a new HTML::Mason::FakeTable object. Any parameters passed to new() will be added to the table as initial values.

add()
Adds a new value to the table. If the value did not previously exist under the given key, it will be created. Otherwise, it will be added as a new value to the key.

clear()
Clears the table of all values.

do()
Pass a code reference to this method to have it iterate over all of the key/value pairs in the table. Keys will multiple values will trigger the execution of the code reference multiple times for each value. The code reference should expect two arguments: a key and a value. Iteration terminates when the code reference returns false, to be sure to have it return a true value if you wan it to iterate over every value in the table.

get()
Gets the value stored for a given key in the table. If a key has multiple values, all will be returned when get() is called in an array context, and only the first value when it is called in a scalar context.

merge()
Merges a new value with an existing value by concatenating the new value onto the existing. The result is a comma-separated list of all of the values merged for a given key.

set()
Takes key and value arguments and sets the value for that key. Previous values for that key will be discarded. The value must be a string, or set() will turn it into one. A value of undef will have the same behavior as unset() .

unset()
Takes a single key argument and deletes that key from the table, so that none of its values will be in the table any longer.

Masonry — вывод html блоков в виде кирпичной кладки

Встречали сайты, где блоки разных размеров выводятся в контейнер, максимально рационально заполняя пространство?

Сделать такой вывод позволяет скрипт David’a DeSandro, который называется Masonry (с англ. кирпичная кладка). Также, наглядный пример можете посмотреть на официальном сайте скрипта. На офф. сайте вы найдете полную документацию на английском.

Masonry — это Javascript библиотека, позволяющая выводить HTML блоки в компактно-сложенном виде. Скрипт анализирует высоту каждого блока и максимально экономя пространство располагает его.

Возможно кто-то уже давно слышал о нем и даже использовал его в своих проектах, но я впервые столкнулся с ним недавно. Не могу сказать, что каждый сможет легко сделать любой вывод. Но с базовым использованием думаю справится каждый. Разобраться что и как там работает не так просто, но сказать что очень сложно я тоже не могу. Если вы неплохо разбираетесь в JS, то любой вывод должен получиться. Цель этого поста познакомить вас с Masonry и оставить заметку о нем для себя.

Masonry работает самостоятельно без использования библиотек, но также может использоваться как jQuery плагин.

В этом посте я сделаю перевод главной страницы офф-сайта, которая объясняет как начать работать со скриптом.

Masonry на Javascript

Эти пакеты установки, содержат все что нужно, для использования Masonry:

Скачивайте js файл и подключайте его к вашему сайту:

Для WordPress подключать лучше используя функцию wp_enqueue_script():

Masonry работает с элементами контейнера, для которых указан один и тот же класс item:

Класс можно указать любой, главное при вызове определить опцию itemSelector : ‘.item’ .

Для блоков контейнера нужно указать ширину. Ширину нужно подбирать соответствующую контейнеру и параметру columnWidth (ширина колонки):

Включение Masonry (Инициализация)

Чтобы скрипт начал работать его нужно применить к нашему контейнеру. Запуск скрипта в виде экземпляра на чистом javascript делает так:

В этом случае конструктор экземпляра содержит 2 аргумента: columnWidth (ширина колонки) и itemSelector (класс блоков в контейнере с которыми будет работать Masonry). Это не все опции, остальные смотрите в документации или ниже на этой странице.

Инициализация через HTML

Masonry можно запустить не используя Javascript, прямо из HTML, указав class js_masonry контейнеру и указав параметры в атрибуте data-masonry-options :

Опции установленные в HTML должны быть в формате JSON. Аргументы должны быть в кавычках «itemSelector»: . Имейте ввиду, что значение аттрибута HTML должно быть в одинарных кавычках ‘ , потому что свойства JSON используют двойные кавычки » .

Инициализация через jQuery

Для использования Masonry не нужно jQuery, но если вам удобнее работать с jQuery, masonry работает с ним как плагин.

Чтобы получить экземпляр используйте метод .data(‘masonry’) :

Инициализация для блоков с изображениями

Так как картинки подгружаются отдельно от HTML кода, применение «Масонри» для блоков с картинкой обычно вызывает ошибку — наложение одного блока на другой. Так происходит потому что Масонри срабатывает до того, как картинка в блоке подгружается, блоку устанавливается высота, а затем картинка «рушит» эту высоту. Решить эту проблему можно несколькими способами:

Способ 1

Установить для всех изображений размеры жестко: ширину и высоту в пикселях.

Способ 2

Повесить обработку Масонри на событие load . Код для jQuery:

Минус этого способа в том, что тут скорее всего придется ждать загрузки всего «окна»: jQuery(window).load . Использовать load отдельно для элемента редко допустимо, потому что jQuery будет интерпретировать его как AJAX функцию load. Чтобы этого избежать используйте 3-й пример.

Способ 3

Инициализировать работу Масонри, после того, как все картинки будут загружены. А для проверки загрузки использовать дополнительный JS скрипт imagesLoaded. Код:

Заметка: также ошибка может быть при использовании дополнительных шрифтов, поэтому загрузку шрифтов нужно проверять.

Обязательные свойства это: columnWidth and itemSelector . Все остальные можно использовать по желанию:

itemSelector(строка) (обязательный) Определяет какой дочерний элемент контейнера будет использован при построении кладки. Элемент нужно указывать, чтобы исключить другие элементы контейнера, которые используются для установки размеров см. «columnWidth»: «.grid-sizer» .
По умолчанию: нет columnWidth(число/элемент/селектор в виде строки) (обязательный) Ширина колонки в пикселях: «columnWidth»: 60 . Если установить селектор или элемент, masonry будет использовать ширину установленного элемента: «columnWidth»: «.gutter-sizer» .Masonry рассчитывает внешнюю ширину блоков, с учетом css свойств border, padding, margin.
По умолчанию: нет containerStyle(объект) CSS стили которые применяются к контейнеру. Чтобы отменить применение masonry стилей к контейнеру укажите containerStyle: null
По умолчанию: gutter(число/элемент/селектор в виде строки) Расстояние между элементами, подобное margin-right . Пример: «gutter»: 10
По умолчанию: 0 hiddenStyle(объект) Стили применяемые к спрятанным элементам.
По умолчанию: isFitWidth(логический) Устанавливает ширину контейнера равную доступному числу колонок, рассчитанную из ширины элементов контейнера. Когда установлен параметр, вы можете отцентровать контейнер через CSS. Заметка: это свойство не работает, если элементам контейнера установлена ширина в %, нужно в пикселях: width: 120px . Также, опция columnWidth должна быть установлена в фиксированное значение, например: columnWidth: 120 .
По умолчанию: false isInitLayout(логический) Включает подстройку блоков во время инициализации. Установите в false, чтобы скрипт не строил кирпичную кладку при инициализации, так вы сможете использовать методы и добавлять события перед обработкой элементов контейнера.
По умолчанию: true isOriginLeft(логический) Контролирует горизонтальное расположение блоков. По умолчанию блоки расставляются с лева на права. Установите в false, чтобы расположить блоки с права на лева.
По умолчанию: true isOriginTop(логический) Контролирует вертикальное расположение блоков. По умолчанию блоки располагаются сверху вниз. Установите в false, чтобы блоки располагались снизу вверх.
По умолчанию: true isResizeBound(логический) Связывает расположение блоков с изменениями размеров окна.
По умолчанию: true stamp(элемент/массив элементов/строка селектор/NodeList) Определяет какие блоки нужно зафиксировать при выводе. Это специальные элементы к которым не будет применен эффект masonry. «stamp»: «.stamp»
По умолчанию: нет transitionDuration(строка) Продолжительность перехода (скорость анимации), когда блоки меняют позицию или появляются. Нужно устанавливать в формате времени для CSS. Чтобы отменить всю анимацию установите в 0: transitionDuration: 0
По умолчанию: ‘0.4s’ visibleStyle(объект) Стили, которые будут применены при показе скрытых элементов.
По умолчанию: меню


Масонри на чистом CSS

C недавних пор, практически все браузеры понимают свойство CSS column-count , смотрите сами.

А раз так, то больше нет необходимости подключать javascript и можно сделать блоки Masonry на чистом css. Конечно такой вариант менее гибкий в настройках, но он в разы проще и быстрее устанавливается и разобраться в нем проще.

У нас есть такой HTML код:

И мы подключаем для него такие css стили:

Минусов у этого варианта хватает

Пробежимся по минусам этого метода и чем он уступает масонри.

Поддержка браузеров, на сегодня (2020 г.) отличная, но все же не полная.

Любую анимацию, нужно будет дописывать вручную.

Главный минус column-count и, собственно, причина, по которой нельзя использовать этот способ вместо masonry в большинстве случаев — это направление блоков.

Если у masonry читается по горизонтали:
1 2 3
4 5 6

То в column-count по вертикали:
1 3 5
2 4 6

С таким подходом использовать с хронологической точки зрения не вариант.

Динамическое добавление элементов в блок, например при AJAX погрузке, сбивает с толку. Т.е. Масонри, добавляет новые элементы после текущих и не трогает текущие, так нет путаницы что добавилось, а что нет. А вот этот вариант, путает элементы.

Например, у нас есть 3 колонки и 30 элементов — условно по 10 в каждой колонке. Добавляем еще 10 и они добавятся не равномерно во все 3 колонки, не затрагивая предыдущее расположение элементов, а добавятся в HTML, а затем браузер перестроит расположение. При этом в первую колонку может попасть 1 элемент, во вторую 2, а в третью 8. В результате, после динамического добавления элементов почти всегда получается путаница: что было и что добавилось.

Поэтому, если планируете подгружать элементы аяксом — этот вариант рассматривать не стоит!

CSS masonry с помощью flexbox, :nth-child() и order

Дата публикации: 2020-05-03

От автора: на первый взгляд создать макет masonry с помощью flexbox довольно просто; все, что вам нужно сделать, это установить для flex-flow — column wrap, и вуаля, у вас есть макет masonry. Что-то вроде того. Проблема этого подхода заключается в том, что он создает сетку с визуально перетасованным и непонятным порядком. Элементы будут (без ведома пользователя) отображаться сверху вниз, и кто-то, анализирующий сетку слева направо, будет читать поля в произвольном порядке, например, 1, 3, 6, 2, 4, 7, 8, 5 и так далее, и тому подобное.

Во Flexbox нет простого способа вывести элементы с макетом column при использовании порядка row, но мы можем построить макет masonry CSS (JavaScript не требуется) — с помощью свойств :nth-child() и order. В сущности, вот прием для создания порядка row при использовании flex-direction: column, учитывая, что вы отображаете три столбца:

Это создаст макет masonry с элементами, представленными в виде столбцов, но упорядоченными в виде рядов (серые вертикальные линии представляют псевдо-элементы, которые создают разрывы строк):

Как создать сайт самому?

Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

Давайте разберем эту проблему (или вы можете посмотреть набор кодов).

Выберите меньшее из двух зол: перетасованный порядок или странные отступы

Flexbox на самом деле не рассчитан на создание masonry; если установить фиксированную высоту для flex-контейнера (так, чтобы элементы могли переноситься) и column wrap для flex-flow, вы получите что-то вроде этого:

Элементы отображаются в столбцах сверху вниз, создавая произвольный порядок при чтении слева направо. Это, конечно, ожидаемый результат, и он желателен во многих сценариях, но не тогда, когда мы пытаемся создать макет masonry, и он становится все более дезориентирующим по мере роста страницы.

Если мы вместо того, чтобы изменить значение flex-direction на row и получить элементы различной высоты, мы достигнем правильного порядка, то получим странные и неожиданные отступы:

Таким образом, кажется невозможным взять лучшее из обоих миров: элементы, представленные в виде столбцов, но упорядоченные в виде строк. Вы можете решить использовать flex-direction: column и просто перемещаться по элементам в HTML для достижения правильного визуального порядка, но это может быть громоздким, излишне сложным, и исказит порядок табуляции элементов.

Изменение порядка элементов с помощью order и nth-child()

Свойство order влияет на порядок элементов, содержащихся во flexbox или grid, и мы можем использовать его, чтобы переупорядочить элементы для нашего будущего макета masonry. Свойство order довольно просто в использовании: если у вас есть два элемента и один имеет order: 1, а другой order: 2, элемент с order: 1 отображается перед другим элементом, независимо от их порядка в исходном коде HTML.

Решение для CSS masonry зависит от деталей спецификации order: что произойдет, если два или более элементов имеют одинаковое значение order? Кто отображается первым? Flexbox использует порядок исходного кода: элемент, который указан первым в исходном коде, будет отображаться раньше других элементов с таким же значением order. Этот факт дает нам возможность легко перегруппировать элементы в сетке, так что мы можем изменить порядок со столбцов на строки, и при этом отображая строки, как столбцы, используя nth-child().

Посмотрите на таблицу ниже. Чтобы добиться нужного порядка с помощью flex-direction: row, нам просто нужно отобразить элементы в порядке по умолчанию: 1, 2, 3, 4, 5, 6 и т. д.

Если мы хотим добиться того же порядка при использовании, flex-direction: column, нам нужно изменить порядок элементов, чтобы он соответствовал порядку каждого столбца в таблице (а не каждой строки):

Т.е. первые элементы в нашем макете flexbox должны быть 1, 4, 7, 10. Эти элементы будут заполнять первый столбец, далее следуют 2, 5, 8, 11 — 2-й столбец, и 3, 6, 9, 12 — 3-й и последний столбец. Вот где в игру вступает селектор nth-child(). Мы можем использовать его для выбора каждого третьего элемента (3n), начиная с первого элемента (3n+1), и установить для всех этих элементов одинаковое значение order:

Mason Portfolio HTML Theme

Screenshots

Overview

Mason is a Modern, Professional, Creative, and Responsive HTML template for showcasing your portfolio and personal information. It suits best for web designers, Graphic designers, UX designers, Web developers, Media Agency, Small businesses and creatives.

All components used in this theme are well commented, W3C validated and are well documented

Features

  • Powered by Bootstrap
  • Well documented codes
  • Fully Responsive
  • Free Google Fonts
  • Owl Carousel 2
  • Font Awesome Icons
  • Magnific Popup
  • Working Contact Form with PHP with validation
  • Home Particles Effect
  • W3C validated HTML and CSS code
  • Cross Browser Compatible
  • Free Updates

Instructions

Images are only for demo purposes and not included with the download bundle

Reviews

Category Themes / HTML / Portfolio
First release 12 May 2020
Last update 12 May 2020
Files included .php, .css, .html, Javascript .js
Tags template , responsive , clean , bootstrap , creative , css3 , html5 , jquery , minimal , modern , one page , portfolio , cv , nice , freelancer , agency , personal , designer

Earn 10% of all purchases made by new customers you refer to Codester.
Join our Affiliate program

License details

Regular License

A regular license allows an item to be used in one project for either personal or commercial use by you or on behalf of a client. The item cannot be offered for resale either on its own or as part of a project. Distribution of source files is not permitted.

Extended License

An extended license allows an item to be used in unlimited projects for either personal or commercial use. The item cannot be offered for resale «as-is». It is allowed to distribute/sublicense the source files as part of a larger project.

HTML::Mason

есть тут кто-нибудь, кто работал с этим тулкитом (кроме меня :))?

хочу задать пару вопросов (ответов в официальной доке нет :))

Re: HTML::Mason

Re: HTML::Mason

я конечно идиот, но не до такой же степени.

все вышенаписанное я знаю, и дальше сверх того.

меня интересует одна вещь — объявление глобальных переменных в autohandler’е.

т.е. переменные как shared декларируешь, а в подчиненные компоненты они не передаются.

Re: HTML::Mason

>я конечно идиот, но не до такой же степени.

Получить URL запроса в HTML :: Mason

December 2020

1.1k раз

Как мы можем найти URL запроса GET на сайте PERL с помощью HTML :: Mason. Я попытался с помощью $ м объекта от Мейсона.

1 ответы

In addition to the $m Mason request object you also have $r the Apache request object. The uri method will return the path component of the requested URL:

If you want the requested URL including the query string, you can use the unparsed_uri method:

Masonry Layout — кирпичный эффект элементов на сайте

Доброго времени суток всем! Это моя вторая статья в этом году. Первую про иконочный шрифт я опубликовал совсем недавно и меня радует, что я нашел время для написания второй статьи с таким небольшим отрывом. Пока для меня это небольшой отрыв, т.к. чаще писать нет возможности, но я стараюсь. �� А теперь давайте разберемся о чем пойдет речь в этой статье.

Быть может многие из вас видели на сайтах расположение элементов (картинок, статей, различных блоков) кирпичным эффектом. Вы скажите — это же можно и через CSS сделать? Может и можно, но только такой гибкости не будет. Скрипт сам расставляет элементы на странице, используя вертикальное пространство. Также при позиционировании блоков скрипт добавляет анимацию. Пронаблюдать это можно в адаптивном дизайне, уменьшая окно браузера. Так вот, достигается это все с помощью небольшой javaScript-библиотеки — Masonry. Данный скрипт очень широко используется в современных трендовых дизайнах. Не знаю как в русско-язычном, но в зарубежном интернете Masonry получил большую популярность.

Автором Masonry является David DeSandro из США. Хотелось бы сказать ему большое спасибо за такой хороший скрипт. Распространяется данная библиотека абсолютно бесплатно, так что смело можете использовать ее на своем сайте.

Я думаю многим понравилось. На самом деле все очень красиво смотрится. Давайте разберемся как работать с Masonry, как вывести на нашем сайте наши блоки кирпичным эффектом?

Для начала нам необходимо перейти на страничку скрипта — http://masonry.desandro.com и скачать последнюю версию. На момент написания данной статьи это версия — 4.0. Также на данном сайте вы найдете подробную документацию на английском языке. Я ниже разберу основные моменты из документации — как подключать, какие имеются опции и т.д. Все затрагивать не буду, т.к. я сам в некоторых моментах еще не разобрался. Для внедрения на свой сайт требуется сделать минимум действий. Вы сейчас в этом убедитесь.

На сайте для скачивания имеются две версии скрипта — сжатая (минимизированная) и несжатая. Лучше использовать именно сжатую — masonry.pkgd.min.js. Также библиотеку можно подгрузить и из CDN:

Советую подключить минимизированную версию Masonry из CDN. Так мы уменьшим количество ненужных http-запросов. Вообще, какой бы вы скрипт не подключали, если есть возможность подключить минизированную версию с CDN, то подключайте именно ее.

Для работы Masonry нам необходимо создать родительский блок и положить в него сами элементы.

Для наглядности я создал демо-страничку с картинками разных размеров. В качестве примера элементов я взял именно картинки, т.к. они имеют разную высоту, но вместо картинок может быть любой блок: текст, видео и др. Попробуйте уменьшить окно браузера и вы увидите, как картинки плавно меняют свою позицию.

Давайте посмотрим как будет выглядеть html-код:

Как видим, css используется здесь по минимуму.

Инициализируем плагин Masonry

Сделать это можно несколькими способами.

Инициализация Masonry через javaScript

Вы можете использовать Masonry как jQuery-плагин:

Но имейте ввиду, что для этого метода у вас должна быть подключена библиотека jQuery:

На демо-страничке я инициализировал Masonry, как jQuery-плагин, т.е. код инициализации у меня следующий:

Если вы обратили внимание методу «masonry()» мы передали две опции: ItemSelector и columnWidth. Это обязательные две опции. По словам разработчика они необходимы для нормальной работы скрипта. Впрочем, об опциях мы поговорим чуть ниже. Все, после этих действий должно все работать.

Инициализация с помощью Vanilla JavaScript

Вы можете использовать Masonry также и с Vanilla JS:

Конструктор Masonry() принимает два аргумента: дочерний элемент контейнера и опции объекта. Код инициализации будет следующий.

Честно говоря, не работал с Vanilla JS поэтому конкретно не могу сказать чем он хорош, чем jQuery. Просто знайте, что есть такой метод.

Инициализация через HTML

Вы можете инициализировать Masonry через HTML, не написав ни единой строчки javaScript кода. Для этого понадобится добавить всем дочерним элементам контейнера атрибут — «data-masonry». Опции можно передать, в качестве значения.

Передаваемые параметры должны соответствовать формату JSON. Хочу обратить ваше внимание на использование кавычек в коде. Кавычки для атрибута data-masonry пишутся одинарными, а для передаваемых опций — двойные. Т.е. именно так, как показано на примере.

Данный вариант можно использовать, если вы не хотите использовать на сайте лишний javaScript. Например, я бы не стал лишний раз грузить jQuery, если на сайте он у меня нигде не используется.

Вот такая вот библиотека. Ничего сложного нет. А что дальше?

Если обратиться к документации, то дальше идет разбор: размеры элементов контейнера, опции, события, методы.

Размеры элементов

Размеры дочерних элементов могут быть как фиксированными, так и резиновыми. При фиксированном размере (ширина и высота) элементов ширина блоков и их оформление задается в пользовательском css-файле стилей. По высоте хочу сказать, если вы используете не пустые блоки, то высота блока будет высчитываться браузером, исходя из его содержимого. В моем случае я высоту не задаю, т.к. картинки итак имеют свою высоту.

Резиновая сетка

При резиновой сетке ширина элементов задается в процентах. Резиновую сетку в основном используют в адаптивном дизайне. Подробнее об опциях поговорим ниже.

ImagesLoaded

Иногда при загрузке страницы может случиться так, что элементы будут перекрывать друг друга. При этом они собираются все в один комок и смотрится все ужасно. Так вот решить эту проблему можно с помощью небольшой библиотеки — imagesLoaded. Наиболее хорошо это проявилось у меня при адаптивном дизайне. Именно, когда я сайт открывал с мобильного телефона сетка изображений у меня собиралась в одну кучу.

Подключаем imagesLoaded с CDN:

С помощью imagesLoaded элемент позиционируется на странице только после полной его загрузки.

Или инициализация Masonry происходит только после полной загрузки всех изображений.

Опции (Options)

Теперь давайте разберем какие мы можем передать опции методу masonry().

Все опции сгруппированы. Ну, это сделано, чтобы легче было в них ориентироваться.

Теперь давайте посмотрим какие опции входят в определенную группу.

Рекомендованные (Recommended)

itemSelector

Данная опция указывает к каким элементам будет применяться эффект Masonry. Полезно указывать данную опцию, потому что тем самым мы можем отсечь элементы которые не являются частью макета. Этот параметр нам уже знаком, когда мы разбирали инициализацию Masonry.

columnWidth

Задает ширину элементов макета. Если данный параметр опустить Masonry возьмет внешнюю ширину первого элемента. Разработчик всегда советует указывать ширину колонок, будь то элементы фиксированные или резиновые.

Размеры элементов (Element sizing)

Если мы хотим сделать наш макет с элементами резиновым, например, при адаптивном дизайне, то для этих целей предусмотрен параметр, который делает нашу сетку резиновой.

percentPosition

Код резиновой сетки мы разбирали выше, но в подробности опций не вдавались.

Как видим, чтобы активировать резиновую сетку мы добавили параметр percentPosition в код инициализации с булево значением «true«. А в качестве ширины указали класс элемента, которому в css присвоена ширина в процентах.демо

gutter

Между элементами можно задать отступ по горизонтали с помощью опции gutter, передав число. Число будет соответствовать отступам в пикселях.

Отступы по вертикали между элементами задаются в css.

Отступы можно задать и в процентах, т.е. они будут меняться в зависимости от размера окна браузера.

Мы создали пустой DIV-блок перед списком элементов.

В CSS для данного блока указали ширину в процентах. А в коде инициализации опции gutter мы указали класс данного пустого элемента. Скрипт сам создаст отступы в процентах, исходя из ширины данного блока.Демо

stamp

Данной опцией можно назначить элементы, которые будут штампованы в сетке Masonry. Остальные элементы будут находиться ниже и будут обтекать штампованные. Иногда это может быть полезным. Опции stamp передаем класс штампованного элемента.

Детальнее пример вы можете посмотреть на Codepen, а также отредактировать при необходимости.

fitWidth

Суть данной опции состоит в том, что когда мы ее активируем родительскому блоку элементов добавляется фиксированная ширина в пикселях. Причем ширина родительского блока равна сумме ширин всех дочерних элементов. Таким образом, указав в css родительскому блоку правило «margin: 0 auto» мы можем расположить блок с элементами Masonry по центру.

Внимание! Данная опция не работает с элементами, ширина которых указана в процентах. Значение опции «columnWidth» должно быть указано в пикселях, например, «columnWidth: 120». Иначе, элементы могут налезть друг на друга.

originLeft

По умолчанию все элементы сетки выравниваются слева на право. С опцией originLeft можно изменить горизонтальный поток элементов и задать выравнивание справа налево. Достаточно передать булево значение «false».

originTop

Также как и по горизонтали по умолчанию элементы сетки выравниваются по верхнему краю. С опцией originTop можно изменить поток элементов по вертикали и задать выравнивание снизу вверх, примерно как в тетрисе �� .

Настройки (Setup)

Переходим к опциям настроек.

containerStyle

Данная опция отменяет стили родительского контейнера элементов. По умолчанию родителю задается правило «position: relative». Данное правило можно отменить.

Конечно, можно было и переопределить через файл CSS с помощью «!important», но я не люблю так делать. Вообще я считаю это правило дурного тона в верстке. Лучше все же очистить стили, тем более разработчик дает нам такую возможность.

transitionDuration

Продолжительность перехода, когда элементы меняют свое местоположение. По умолчанию задано время — 0.4 сек. Формат времени задается, как формат времени CSS.

Вот некоторые примеры установки времени.

resize

C помощью данной опции можно отменить изменение размеров родительского блока. Т.е. по умолчанию, если не задать фиксированный размер родителю при уменьшении экрана браузера наши дочерние элементы сетки будут менять свое месторасположение, будут перемещаться вниз, занимая свободное пространство. Так вот с помощью опции «resize» можно отменить переходы.

Честно говоря, такого же эффекта можно добиться, если задать родителю просто фиксированный размер. Здесь я не понимаю разработчика — либо я что-то недопонял, либо данная опция имеет место быть в определенных случаях. Подробнее можете посмотреть на примере в Codepen. Попробуйте изменить размер экрана браузера. Потом поменяйте «resize: false» на «resize: true» и поймете о чем идет речь.Посмотреть на CodePen

initLayout

Данная опция активирует нашу кирпичную сетку при инициализации скрипта. По умолчанию она включена — «initLayout: true». Но можно и отменить.

Вы можете использовать методы и события перед активацией сетки. Например, вы можете сделать так, что ваша сетка будет активироваться по клику определенной кнопки. Ну и далее что-то в этом роде.

В данной статье я не буду разбирать события и методы, т.к. статья итак получилась объемной. Вы можете их самостоятельно изучить на сайте разработчика. Там же найдете и примеры реализации. Все довольно понятно изложено. Не всегда авторами скриптов пишутся такие инструкции. За инструкцию Masonry разработчику я бы поставил твердую — 5. ��

Masonry на чистом CSS

Есть также вариант реализовать кирпичную кладку на чистом css. Не буду приводить здесь весь код. Можете глянуть на CodePen, ничего сложного нет. В данном случае удобно тем, что не нужно подключать лишние js-библиотеки и разбираться в опциях плагина.

В принципе все то, что я изложил выше хватает, чтобы задействовать кирпичный эффект на своем сайте.

А на этом все. Всем спасибо за внимание. Задавайте вопросы в комментариях, всегда буду рад помочь. Встретимся в следующих статьях. Пока!

Заур Магомедов

Верстальщик с большим опытом работы. Занимаюсь созданием сайтов с 2009 года. Постоянно обучаюсь и совершенствую свои навыки. Веду свои проекты, в том числе и данный блог.

Добавить комментарий