Menu
Is free
registration
home  /  Internet/ Change the top menu. PdoMenu - creating a menu in MODX Modx vertical menu

Changing the top menu. PdoMenu - creating a menu in MODX Modx vertical menu

Menu generation snippet. It can replace Wayfinder, and allows more flexibility in specifying parameters.

For example, it can build a menu from several parents at once, displaying them both together and as separate branches.

A significant increase in speed is provided only at the first start, further Wayfinder is not particularly inferior, thanks to competent caching.

Options

By default, pdoMenu accepts general pdoTools parameters and some of its own:

Name Default Description
& parents Current resource List of parents for search results, separated by commas. If you put & parents = `0`- the sample is not limited. If the parent's id begins with a hyphen, it and its children are excluded from the selection.
& level 0 (unlimited) Generated menu level.
& resources List of resources to display in the results, separated by commas. If a resource id begins with a hyphen, that resource is excluded from the selection.
& templates List of templates for filtering results, separated by commas. If a template id begins with a hyphen, resources with it are excluded from the selection.
& where JSON-encoded array of additional fetch parameters.
& displayStart 0 Enable display of menu start nodes. Useful when specifying more than one parents.
& context Restricting the selection by resource context.
& showHidden 0 Show resources hidden in the menu.
& showUnpublished 0 Show unpublished resources.
& previewUnpublished 0 Enable showing unpublished resources if the user has permission to do so.
& hideSubMenus 0 Hide inactive menu branches.
& select List of fields to select, separated by commas. You can specify a JSON string with an array, for example & select = `(" modResource ":" id, pagetitle, content ")`
& sortby menuindex Any resource field to sort, including the TV parameter, if specified in the parameter & includeTVs, for example & sortby = `(" tvname ":" ASC "," pagetitle ":" DESC ")`... You can specify a JSON string with an array of several fields. For random sorting, specify & sortby = `RAND ()`
& sortdir ASC Sorting direction: descending or ascending. If you leave the & sortby and & sortdir parameters empty, then the sorting will go in the order of the resources in & resources.
& limit 0 Limiting the number of sample results.
& offset 0 Skipping results from the beginning. Must be used in conjunction with the explicitly specified & limit
& checkPermissions Specify what permissions you want to check for the user when displaying resources, for example & checkPermissions = `list`.
& countChildren 0 Exact counting of the number of child resources of each category and displaying them in the [[+ children]] placeholder. Makes additional queries to the database, so it is disabled by default.
& toPlaceholder If not empty, the snippet will save all data to a placeholder with this name instead of being displayed on the screen.
& plPrefix wf. Prefix for placed placeholders.
& showLog 0 Show additional information about the work of the snippet. Only for those authorized in the "mgr" context.
& fastMode 0 Fast chunk processing mode. All raw tags (conditions, snippets, etc.) will be cut.
& cache 0 Snippet results caching.
& cacheTime 3600 Time of cache validity, in seconds.
& scheme -1 The url formation scheme is passed to modX :: makeUrl (), so the possible options are needed. The special uri type substitutes the resource uri value without running the function.
& useWeblinkUrl 1 Generate a link based on the resource class.
& rowIdPrefix The id = "" prefix for setting the identifier in the chunk.
& hereId id of the current resource for the generated menu. You need to specify it only if the script itself incorrectly defines it, for example, when displaying a menu from a chunk of another snippet.
& includeTVs List of TV parameters for selection, separated by commas. For example & includeTVs = `action, time` will give placeholders [[+ action]] and [[+ time]].
& prepareTVs List of TV parameters, with files from media sources, for which full paths need to be generated. If you install & prepareTVs = `1`, all TVs specified in & includeTVs.
& processTVs List of TV parameters to be processed and displayed according to their settings in the system manager. If you install & processTVs = `1`, all TVs specified in & includeTVs... Slows down work.
& tvPrefix Prefix for TV parameters.

Template parameters

These parameters set chunks that contain templates for generating menus.

Name Description
& tplOuter Chunk of the design of the entire menu block. Default: @INLINE
    [[+ wrapper]]
& tpl Chunk of the menu item design. If not specified, then the content of the resource fields will be printed to the screen. Default: @INLINE
  • [[+ menutitle]] [[+ wrapper]]
  • & tplHere Chunk of the design of the current menu item.
    & tplStart Chunk of registration of the root item, provided that it is included & displayStart... Default: @INLINE

    [[+ menutitle]]

    [[+ wrapper]]
    & tplParentRow Chunk of the design of a parent with children that does not match the & tplCategoryFolder conditions. For example: @INLINE
    & tplParentRowHere The chunk of the layout of the current document, if it contains children.
    & tplParentRowActive Chunk of registration of parents with descendants in the active menu branch.
    & tplCategoryFolder A special chunk of the category design. The category is considered a parent with children, which has an empty template or rel = "category" in the link_attributes field.
    & tplInner Chunk of the design of the entire block of menu sub-items. If empty, it will use & tplOuter... For example: @INLINE
    & tplInnerRow Chunk of registration of a sub-item of the menu. For example: @INLINE
    & tplInnerHere Chunk for the design of the active sub-item of the menu.

    CSS class parameters

    These parameters set the value of the placeholders [[+ classnames]] and [[+ classes]] for various menu items. Placeholder [[+ classnames]] displays only class name without attribute class = "", unlike the placeholder [[+ classes]].

    Examples of

    The usual menu output from the site root to one level:

    []

    Output excluding specific parents and checking user permissions:

    []

    Displaying a menu from two parents at once, showing the root points:

    []

    Displaying two levels of resources, counting the number of nested resources:

    [] `& tplParentRow =` @ INLINE

  • [[+ menutitle]] ([[+ children]])
  • [[+ wrapper]] `& countChildren =` 1`]]



    Wayfinder serves to organize lists of links for MODX. Thanks to the support of templates, it allows you to display lists in any necessary form:
    • Menu in the form of a list, table, images, icons, etc.
    • Static menus
    • Menus with different effects (dropdown, dropdown, etc.)
    • map of site
    Call example:


    & rowTpl = `rowTpl`
    & outerTpl = `outerTpl`
    & hereClass = `active`
    & rowClass = `eNav_li`]]

    Snippet parameters:

    & startId- id of the parent page, if you specify 0, it will be from the site root. The default is the id of the active page

    & displayStart - show document with startId in menu title, default false

    & level- nesting depth, by default 0 - all levels

    & limit- limit the number of pages in the output (default 0 - no limit)

    & ignoreHidden- ignore the checkbox of the "Show in menu" page, ie if you specify 1, it will display all pages. The default is 0. Only those pages are displayed that have the "Show in menu" checkbox selected

    & ph - the name of the substitute for the directly displayed results. The default is 0.

    & debug- debug mode (default 0)

    & hideSubMenus - expand only active submenu (default 0)

    & removeNewLines- removes the line feed character on output (default 0)

    & textOfLinks- for the name of the menu link. Possible options:menutitle, id, pagetitle, description, parent, alias, longtitle, introtext. Default menutitle

    & titleOfLinks- for the title of the menu link.menutitle, id, pagetitle, description, parent, alias, longtitle, introtext. Default pagetitle

    & rowIdPrefix- sets id (rowIdPrefix + docId) for each element. Default 0

    & includeDocs- id of documents separated by commas, which will be included in the menu (not specified by default)

    & excludeDocs - id of documents separated by commas, which will be excluded from the menu (default 0)

    & contexts- context for generating the menu. The default is current.

    & startIdContext - The identifier of the context from which the documents are taken to form the result.

    & config - External PHP file for storing Wayfinder configuration (example: core / components / wayfinder / configs).

    & scheme - Format for generating URL. Possible values ​​(based on the makeURL API call):

    1: (default) URL relative to site_url;

    0: see http;

    1: see https;

    full: an absolute URL starting with site_url;

    abs: an absolute URL starting with base_url;

    http: an absolute URL, coerced into the http scheme;


    https: an absolute URL, coerced into the https scheme.

    & sortBy - The field to sort by. (default menuindex)

    The options are:

    id, menutitle, pagetitle, introtext, menuindex, published, hidemenu, parent, isfolder, description, alias, longtitle, type, template

    & sortOrder- Sorting order."ASC" or "DESC". Default ASC

    & where - JSON-style filter parameters (Matches where in MySQL)... For example, when you want to hide a blog or news from the Articles addon: & where = `[(" class_key:! = ":" Article ")]`
    Examples:
    output only folders: & where = `isfolder = 1

    & hereId - Determine the current ID to use in the snippet. Use the value [[* id]] if the template is specified using the hereTpl parameter and activeRowParentTpl is not being applied correctly in the menu item. By default, the current ID.
    You need to specify it only if the script itself incorrectly defines it, for example, when displaying a menu from a chunk of another snippet.

    & hereTpl - The hereTpl template is used when the current item is displayed in the menu.
    Possible placeholders:
    [[+ wf.classes]] - a place to specify the used CSS class (includes class = "")
    [[+ wf.classnames]] - contains only the name of the CSS class (does not include class = "")
    [[+ wf.link]] - address (href) for the link
    [[+ wf.title]] - text for the title of the link
    [[+ wf.linktext]] - link title text
    [[+ wf.wrapper]] - place to display submenu
    [[+ wf.id]] - display a unique identifier (id)
    [[+ wf.attributes]] - display additional link attributes
    [[+ wf.docid]] - document identifier for the current element
    [[+ wf.subitemcount]] -number of items in the folder
    [[+ wf.description]] - displays the values ​​of the description field
    [[+ wf.introtext]] - displays the values ​​of the introtext field

    Example template: [[+ wf.linktext]] [[+ wf.wrapper]]

    Template parameters

    These parameters specify the chunks that contain templates that will generate Wayfinder's output.

    In the current version of Wayfinder for MODX Revolution, you can access your custom TV using the wf prefix placeholders. eg [[+ my_TV]]

    At the time of this writing, only the original TV values ​​will be returned - they will not be formatted. For example, if your TV is an image - the usual use of such a TV inside your template will return the full full image tag, but inside a Wayfinder template - only the path to the image will be returned.

    If you want to handle TV, you can do so by calling a snippet within the Wayfinder row template (& rowTpl. For example, your TV image is named icon and usually the following code is used for output in the template:

    ... ...

    But since this won't let you handle TV, you need to replace it with:

    ... ...

    And now we put the following PHP code inside the processTV snippet:

    getObject ("modResource", $ myId); return $ doc-> getTVValue ($ myTV);

    As a result, a fully processed TV image is returned.

    & outerTpl

    The name of the chunk containing the template for the outer container.

    Available placeholders:

    • wf.classes - displays classes taken from a set of Wayfinder parameters (including the class = "" attribute)
    • wf.classnames - display class names (without class = "")
    • wf.wrapper - displays the internal content (row).
      [[+ wf.wrapper]]

    The & innerTpl parameter contains the same set of placeholders as & outerTpl.

    & rowTpl

    Chunk name containing template for menu row items.

    Available placeholders:

    • wf.classes - class output (including the class = "" attribute)
    • wf.classnames - display the corresponding classes (without class = "")
    • wf.link - the value of the href = "" attribute for the menu link
    • wf.title - the name of the title text for the link from the field specified in the & titleOfLinks parameter
    • wf.linktext - the text for the active link specified in the field passed in the & textOfLinks parameter
    • wf.wrapper - displays internal content, such as a submenu
    • wf.id - displays the unique ID of the attribute. You need to specify the & rowIdPrefix parameter in order for this placeholder to receive a value. The value is the docId prefix.
    • wf.attributes - Prints the attribute link for the current element
    • wf.docid - document ID of the current element
    • wf.description - description for the current element
    • wf.level - current nesting level

    Usage example:

    [[+ wf.linktext]] [[+ wf.wrapper]]

    Another option:

  • [[+ wf.linktext]] - [[+ wf.description]] [[+ wf.wrapper]]

  • Examples of

    First level


    [[! Wayfinder? & startId = `0` & level =` 1`
    & rowTpl = `rowTpl`
    & outerTpl = `outerTpl`
    & hereClass = `active`
    & rowClass = `eNav_li`]]

    Chunk code outerTpl



      [[+ wf.wrapper]]

    RowTpl chunk code



      [[+ wf.wrapper]]

    Second level (in this example, the menu and submenu items were visually at the same level

    [[! Wayfinder? & startId = `0` & level =` 2`
    & rowTpl = `rowTplFooterMenu`
    & outerTpl = `outerTplFooterMenu`
    & innerTpl = `innerTplFooterMenu`
    & innerRowTpl = `innerRowTplFooterMenu`
    & hereClass = `active`]]

    Chunk code outerTplFooterMenu



    [[+ wf.wrapper]]

    chunk code rowTplFooterMenu




    • [[+ wf.title]]


    • [[+ wf.wrapper]]

    chunk code innerTplFooterMenu

    [[+ wf.wrapper]]

    chunk code innerRowTplFooterMenu



  • [[+ wf.title]]


  • But this is not for us;).

    We will do everything from scratch. Why did we (I) need this, because there are already ready-made options? Because I like it that way. Because I think this approach is the most correct. Because, being able to develop our own, we can easily understand someone else's code, change, fix errors or supplement it with the functionality necessary in a particular case. And, in the end, making your own is often so pleasant!

    Further narration will assume that the reader has minimal knowledge of PHP programming. In theory, those people who do not understand the code at all will be able to copy the code and reproduce all the steps that will be discussed below. However, it may be better for them to use ready-made snippets a la Ditto, since they provide a bunch of opportunities for external configuration without getting into the main code.

    I do not want to debate what is better for the user - to take ready-made or to develop their own ... Both in that, and in another case, there are pros and cons. For me personally, there are more advantages in the second option. Also, each of the readers will decide for himself.

    So, let's take a look at ours again. Since there are quite a lot of different software parts in our site, and you need to start with something, so we will program ...

    Top Menu

    By the term "top menu" I mean a set of links to pages at the top of the site (see image below):

    I will describe the first example of creating a snippet in great detail, in the future I will dwell mainly on the most essential details.

    Let's compare to our site tree in the management system, which we built in the previous article:

    As you can see from the figure, four documents are highlighted in the site tree (namely "Blog", "About authors", "Photos" and "Feedback"), which will subsequently create links in the top menu.

    Also, let me remind you that we hid documents in advance that we do not want to show in the menu. For example, in the settings of the document with the name "Site Search", the checkbox "Show in the menu" was removed, and the remaining two documents "Links" and "Categories" were hidden on the site, by removing the checkbox in the document settings "Publish" (the "Page settings" tab in document settings).

    Thus, in the previous article, we prepared the top menu in the control system.

    Now let's move on to the issue of displaying our actions directly on the site.

    Most of the programs on the site are performed by the so-called. "", i.e. separate pieces of code (they can also be understood as separate functions or subroutines) in PHP. Therefore, in order to implement the top menu display in MODx, we also need to create a new snippet, program it and add a call to this snippet in the template in the right place.

    Let's go to the management system, open the "Resources" tab -> "Resource management" -> the "Snippets" tab and click on the "New snippet" link. In the "Snippet name" field, enter "TopMenu" without quotes and for now just save an empty snippet without code. After saving, we will see the name of our snippet on the "Snippets" tab.

    Let me remind you that in our template we moved the top menu to the "TOPMENU" chunk. Switch to the "Chunks" tab and open the "" chunk. In the contents of this chunk, we will see the following code:


    • Blog

    • Authors

    • Photo

    • Feedback

    This code is what creates our menu. Let's comment it out and add a call to the "TopMenu" snippet in the chunk:


    []

    Here again we will have to digress a little to clarify the meaning of this construction []. The fact is that it is with the help of constructions like [] or [! SnippetName!] That we can make calls to snippets anywhere in our templates, chunks, and even just on any separate page of the site.

    In this case, the [] construction denotes a call cached snippet, i.e. a call to a dynamic subroutine, the result of which will be calculated and executed once, and later on loading the page where this snippet is called, the result will be unchanged, since the repeated call of the snippet no longer occurs. Thus, we save the resources of our web server (and this is always very important with high traffic to the resource).

    However, there are situations when you need to re-execute the snippet code all the time and you cannot cache the results. In such cases, the construction [! SnippetName!] Is used, which will always force the snippet to be executed without caching. By analogy, this construction is called a call uncacheable snippet.

    So, let's save the "TOPMENU" chunk and refresh the site page. Hmm, oddly enough, the top menu is gone. But is it really so amazing? By commenting out the HTML code of the menu in the chunk, we hid its display in the browser (check this by looking at the HTML source of the page). And our "TopMenu" snippet does nothing, since nothing has been added to it yet. Let's fix this shortcoming :).

    Let's go back to the "Snippets" tab, open the created "TopMenu" snippet and try to test its capabilities ... Patience, my advanced readers, not everyone is familiar with these details.

    First, let's write the simplest code (regular PHP code):

    echo "Testing ...";
    ?>

    Select "Continue editing" before saving. we will have to change the content of our snippet more than once, and after that we will save the snippet. Refresh the site page and see in place of the top menu ... well, to tell the truth, at first glance we will not see almost any changes, except for the slightly expanded blue background of the menu. Press "CRTL + A" to select all the text on the site page, and we will see that after all, our snippet displayed the text "Testing ..." in place of the menu, just the text color matches the background color.

    Let's change the snippet code to the following:

    echo " Testing ...";
    ?>

    Now we can clearly see that our snippet works and even (!) Displays some text. Well, this is fine, but not enough for our task, since we must ensure that our snippet displays links from the control system, and in exactly the same HTML code that we commented out in the "TOPMENU" chunk.

    And again, a little distraction ...

    The entire system of document relationships in MODx is built on the principle: each "parent document" contains from zero to many "child documents" ("parent" -> "childs").

    Each document in the MODx database has its own unique identifier "ID" - this is the number that we see in brackets in the site tree next to each of the documents.

    By the way, this unique identifier carries only one single meaning - it uniquely identifies a specific document in the control system. and nothing more! I specifically focus on this fact, since I have met repeated attempts to change these identifiers for a variety of purposes ... You need to remember right away that this is simply pointless, so do not try to change these numbers. You shouldn't pay much attention to them at all, usually these numbers are used simply to generate links to certain documents.

    In the MODx database, a special "parent" field has also been created for each document. The value of this field is a number indicating either the unique identifier of the parent document, or, if the document is at the root of the tree, zero. Thus, you can always unambiguously determine which document is the parent for a given one.

    To see what we just talked about, open phpMyAdmin, select your database and find the (PREFIX) site_content table, where (PREFIX) is your prefix that you entered during installation. You will see many fields that store certain document data, including "ID" - a unique identifier, "parent" - the number of the parent document, "pagetitle" - the title of the page, and others.

    So, using this information about the principle of storing and linking documents in MODx, we can understand how to get the necessary data to display links in the top menu: we need to find in the database all documents that are in the root of the site tree, i.e. have a value of zero in the "parent" field.

    Using the SQL language, such a query is described something like this (you can try to enter this query in the SQL input field in phpMyAdmin, after replacing "modx_" with your prefix):

    SELECT *
    FROM `modx_site_content`
    WHERE `parent` = 0;

    However, such a request will return us absolutely all documents from the site root, which is not entirely correct, based on the main task - to display links only to those documents that have:

    • published status (in the database the field "published" is responsible for this item, where value = 1 means that the document has been published, and value = 0 means unpublished).
    • not deleted (the "deleted" field, where 1 is deleted and 0 is not deleted),
    • and which have the "Show in menu" option set (the "hidemenu" field, where 1 - to hide, and 0 - to show in the menu).

    In addition, running a little ahead, we will immediately sort the documents by the "Position in the menu" parameter, which will determine the position of each link in our menu.

    Well, from the point of view of SQL, this is not a difficult task at all and it is solved like this:

    SELECT *
    FROM `modx_site_content`
    WHERE `published` = 1
    AND `parent` = 0
    AND `deleted` = 0
    AND `hidemenu` = 0
    ORDER BY `menuindex` ASC;

    Theoretically, all SQL queries can be executed in snippets directly using PHP scripts, connecting the database every time and doing many other routine operations, repeating them over and over ... But, you must agree, this would neutralize the meaning of using the framework, which is certainly our control system since MODx, among its other advantages, provides a ready-made set of program interface tools (API, Application Programming Interface). APIs are software functions that unify and facilitate many data processing processes.

    Let's use one of the mentioned API functions "getDocumentChildren" in our snippet. The "getDocumentChildren" function receives the following data as parameters:

    • $ id - number of the parent document,
    • $ active - select only published or unpublished documents (1 or 0, respectively),
    • $ deleted - select only deleted or not deleted documents (1 | 0),
    • $ fields - fields that are selected from the database,
    • $ where - special conditions, i.e. WHERE clause in SQL query,
    • $ sort - the field by which to sort the results
    • $ direction - sorting direction, can be ASC or DESC, i.e. sorting from lowest to highest value or vice versa
    • $ limit is the limit of the request, i.e. LIMIT clause in SQL query

    $ results = $ modx-> getDocumentChildren (
    $ id = 0,
    $ active = 1,
    $ deleted = 0,
    $ where = "hidemenu = 0",
    $ sort = "menuindex",
    $ dir = "ASC",
    $ limit
    );

    Print ("

    Foreach ($ results as $ key => $ value) (
    print_r ($ value);
    }

    Print ("");
    ?>

    Save the snippet and refresh the page. As a result of executing the updated "TopMenu" snippet, you will see a list of arrays and their values ​​sorted by the values ​​of the "menuindex" field from the lowest value to the highest. Try changing the $ dir = "ASC" parameter to $ dir = "DESC" - as a result, the arrays will be rebuilt and the first document will display the document with the highest value of the "menuindex" field.

    It is probably clear to experienced programmers that the result obtained already gives everything that is needed to build a ready-made menu with links. Well, almost everything. In any case, I will continue: we will rewrite the PHP code to get as close as possible to the desired result.

    $ results = $ modx-> getDocumentChildren (
    $ id = 0,
    $ active = 1,
    $ deleted = 0,
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle",
    $ where = "hidemenu = 0",
    $ sort = "menuindex",
    $ dir = "ASC",
    $ limit
    );

    $ items = "";
    $ output = "";

    Foreach ($ results as $ key => $ value) (
    $ items. = "


  • ". $ value [" pagetitle "]."
  • \ n ";
    }

    If ($ items! = "") (
    $ output = "

      \ n ";
      $ output. = $ items;
      $ output. = "
    \ n ";
    }

    Return $ output;

    We will not analyze the code in detail, since this is the most common PHP code, nothing more. If someone does not understand the meaning of any constructions, I ask in the comments, or better - to the corresponding support forums.

    Let's save the new snippet code and refresh the page. As a result of executing the code, we will see practically what we wanted to get:

    Those. these are already automatically generated links, the structure of which completely repeats the structure of documents in the MODx tree. To test this, try creating some test document at the root of the site and refresh the page.

    However, this is not all. Many have probably already noticed that there are links, but there are no links ... Paradox :). I mean, the names of the documents in the menu are displayed, but the links to them do not work. This is logical, since while in the code of links "#" is displayed instead of real paths.

    To solve this problem, you need to learn about another extremely useful feature of MODx: the address of any internal page of the site can be obtained using the following construction [~ id ~], where id is the unique number of the required document, i.e. the same number indicated in brackets next to the name of each document in the site tree. Thus, by adding such a construction [~ 1 ~] in the template / chunk / page content,

      • index - the alias for the "Blog" document, if we entered "index" as the alias for the document, or
      • 1.html, if we did not enter anything in the "Alias" field for the "Blog" document
    • if friendly links are disabled, then we will see the text index.php? id = 1

    Let's rewrite the snippet using this information:

    $ results = $ modx-> getDocumentChildren (
    $ id = 0,
    $ active = 1,
    $ deleted = 0,
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle",
    $ where = "hidemenu = 0",
    $ sort = "menuindex",
    $ dir = "ASC",
    $ limit
    );

    $ items = "";
    $ output = "";

    Foreach ($ results as $ key => $ value) (
    $ items. = "


  • ". $ value [" pagetitle "]."
  • \ n ";
    }

    If ($ items! = "") (
    $ output = "

      \ n ";
      $ output. = $ items;
      $ output. = "
    \ n ";
    }

    Return $ output;

    So we changed # to [~ ". $ Value [" id "]." ~], Ie in fact, for each document from the array, its unique ID is substituted inside the [~ id ~] construction. As a result, we get a menu with working links.

    We have almost reached the ideal ... However, even now there is still one detail that must be taken into account: the designer determined that the active link should be highlighted with a white background and the color of the link should accordingly be changed to orange.

    To achieve this, we will once again reveal the secrets of MODx CMS :). Hidden in the API is the $ modx-> documentIdentifier function, which returns the value of the unique identifier of the current page. We will need it to determine the active page and select it in the menu:

    $ results = $ modx-> getDocumentChildren (
    $ id = 0,
    $ active = 1,
    $ deleted = 0,
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle",
    $ where = "hidemenu = 0",
    $ sort = "menuindex",
    $ dir = "ASC",
    $ limit
    );

    $ cid = $ modx-> documentIdentifier;

    $ items = "";
    $ output = "";

    Foreach ($ results as $ key => $ value) (
    if ($ value ["id"] == $ cid) (
    $ active = "id = \" active \ "";
    }
    else (
    $ active = "";
    }
    $ items. = "
    ". $ value [" pagetitle "]."
    \ n ";
    }

    If ($ items! = "") (
    $ output = "

      \ n ";
      $ output. = $ items;
      $ output. = "
    \ n ";
    }

    Return $ output;

    Well, how did it work? Happened!

    But you didn't think that this would be the end? And rightly so. We set ourselves the highest bar, we want to use the maximum capabilities of MODx. Therefore, there is one more small detail that we missed.

    Let's take a closer look at the names of the fields that we request using the getDocumentChildren function: "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle". Among them there is such a field as "menutitle". As the name suggests, this field can store menu title... The control system also has a "Menu item" input field. This field is optional. However, the logic is that if this field is filled, then we must replace the link text in the menu with the one entered by the user. Well, let's do it like this:

    /********************************
    Title: TopMenu
    Purpose: Display the top menu
    Project: Demosite MODx
    ********************************/

    $ results = $ modx-> getDocumentChildren (
    $ id = 0, // parent document ID
    $ active = 1, // Select only published documents
    $ deleted = 0, // Select only non-deleted documents
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle", // Select fields from the database
    $ where = "hidemenu = 0", // Select only those documents that need to be published in the menu
    $ sort = "menuindex", // Sort documents by the menuindex field
    $ dir = "ASC", // Sort documents in ascending order
    $ limit = "" // We do not set any restrictions (the LIMIT parameter in the SQL query)
    );

    $ cid = $ modx-> documentIdentifier; // get the ID of the current page

    $ items = "";
    $ output = "";

    Foreach ($ results as $ key => $ value) (
    if ($ value ["id"] == $ cid) (
    $ active = "id = \" active \ "";
    }
    else (
    $ active = "";
    }
    if ($ value ["menutitle"]! = "") (
    $ title = $ value ["menutitle"];
    }
    else (
    $ title = $ value ["pagetitle"];
    }
    $ items. = "
    ". $ title."
    \ n "; // collect menu items
    }

    // If at least one menu item was found,
    // create the HTML code for the menu
    if ($ items! = "") (
    $ output = "

      \ n ";
      $ output. = $ items;
      $ output. = "
    \ n ";
    }

    // Return the result of the snippet
    return $ output;

    Now try to enter some text in the input field "Menu item" of any document ... Does everything work? Wonderful!

    P.S. absolutely all pages currently use the same template. In this template, in fact, we have made only the top menu dynamic so far, all other details remain unchanged. We will definitely deal with this later, but for now - don't panic;).

    Conclusion:

    So, one more article has come to its logical conclusion.

    Learning Outcomes:

    • We tried to understand the purpose of some of the MODx document input fields and examined the storage of this information in the database;
    • Found out about new special MODx constructs: [], [! SnippetName!], [~ Id ~];
    • Learned about the availability of a special API and used some of the API functions;
    • And based on this knowledge, we created our new snippet in MODx!

    When submitting a ready-made website, the webmaster's business cards try to automate all processes as much as possible so that the client, after the delivery of the project, does not tug at them over trifles. One of the most common problems is precisely with the creation and editing of new menu items.

    Therefore, one of the main tasks of a webmaster is to create a dynamic menu so that all actions to edit the menu structure could be performed from the administrative panel.

    This can be done using special MODx tools - snippets.

    Snippet Is php code that runs in the MODx template and allows you to display information from the CMS database.

    Snippets are divided into two types:

    • cached;
    • not cached.

    Their difference is in the design of the call. So, for example, if we have a snippet with the name "SNIPNAME", then with a non-cached call, the construction will look like this:

    [! SNIPNAME!]

    With a cached version, it will look like this:

    []

    Here the question may arise, why make the snippet cacheable? The fact is that when using the cache, the structure is saved and there is no constant access to the database, which in turn increases the speed of page loading and reduces the load on the server. But often, you can face the fact that after entering into the cache, the webmaster performs some actions, but they are not displayed on the site; to display them, you must first clear the outdated cache. I'll talk about this a little later. We will use the non-cached menu option.

    The second important characteristic of snippets are - Extra options, which can be set directly when calling this construct. The diagram looks like this:

    [! SnippetName? & parameter1 = `parameter value` & parameter2 =` parameter value`!]

    Sign "?" - gives the system a signal that it is followed by parameters that need to be applied to the snippet. And the snippets themselves are separated by "&", and the values ​​are enclosed in back quotes. If you put the wrong quotes, then nothing will work.

    How do you customize the dynamic display of the menu structure?

    To display the menu in MODx, we will use a snippet:

    [! Wayfinder!]

    We will not be able to use it in its "pure form", because this requires the presence of embedded materials, and it will be displayed only on the main page. It will be correct to indicate the id of the article from which it is worth counting. With this method, we can create many different menus using id for this. In practice, it will be more clear.

    Since now the Parent point is "Main" with the value id = 1. Then the structure should look like this:

    With this design, you can bring the menu out of the child items. Let's put this into practice.

    We go to the section "Elements" - "Manage elements" - Tab "Chunks". We select the "HEADER" chunk and find in it the code that is responsible for displaying the menu.

    HOME

    • home
    • about us
    • services
    • projects
    • solutions
    • jobs
    • blog
    • contacts

    Let's insert the above snippet construction instead of this code:

    [! Wayfinder? & startId = `1`!]

    As you can see, the menu is connected, the url is changing in the address bar, although the template remains the same, we will fix it in the next lessons.

    But there are two problems:

    1.) The active menu item is not highlighted.

    2.) There is no menu item "Home".

    Let's fix these shortcomings.

    We connect the active menu item

    By default, the Wayfinder snippet forms the active menu item with the "active" class. So we don't have to add an additional script, but just change the class in the css file. To do this, go to the folder with our template - /assets/templates/retina/css/style.css. Please note that the folder name of the template folder may differ for you, it all depends on what name you entered in the first lessons. Open this file and look for a line with styles for the active menu item. I have this line - 190, and here is the code itself:

    #navigation a.nav-btn (margin-bottom: 15px; text-decoration: none; padding: 0 36px 0 10px; line-height: 30px; display: block; background: url (images / navigation.png) repeat-x 0 0; height: 30px; position: relative;)

    Replace the class ".nav-btn" with "active".

    We connect "Home"

    And so, as you understand, we have removed the daughter items from the "Main" menu item. To pull up this item itself, we need our entire menu to be at the same nesting level.

    First, we check if access to the root folder is open. To do this, go to the "Tools" - "Configuration" - "Users" tab. In it we find the parameter - " Allow access to root folder"And set the value to" Yes ".

    After that, select the item, let's say "Services", go to the page for editing it and click on the icon below, as shown in the screenshot.

    After clicking, you need to select the parent menu item in the left column of materials, we select the horse folder. See screenshot below.

    Click on it and save our article. The material itself should move one level with the "Main" one.

    This action must be done with all the subparagraphs. You should have the following structure.

    If you refresh the page of your site now, then your menu will disappear. This is because the parent category id has changed. Let's tweak it. To do this, go to the section "Elements" - "Manage elements" - Tab "Chunks". Select the "HEADER" chunk and find the code in it:

    [! Wayfinder? & startId = `1`!]

    And change to:

    That's it, the menu is completely ready and matches the template.

    If you noticed, you can see from the template that in the footer we have a menu that exactly repeats the items of the option we just created. Therefore, I propose to immediately correct this block as well. To do this, go to the section "Elements" - "Manage elements" - Tab "Chunks" select the chunk "FOOTER". In it we find the code responsible for displaying the bottom menu, and instead of it we insert the already familiar construction.

    [! Wayfinder? & startId = `0`!]

    Here's what you should get.

    That's all for today. If you have any questions, write them in the comments, I will try to answer them. Until next lessons.

    Greetings, dear readers. In the last lesson, we filled the site a little with content (), now it's time to bring everything to the menu so that users can navigate to them.

    Create dynamic menu in MODX we will be using a snippet PdoMenu from the package pdoTools... Check out the basic documentation before you start.

    PdoMenu Documentation

    Options

    Template parameters

    CSS class parameters

    Official examples


    you can read the official documentation here. Now let's take a look at the most typical menu calls.

    Calling PdoMenu

    Option 1... In place of this static menu call the pdoMenu snippet, for this in the resource tree, on the tab “ The elements”In the snippets section expand the branch pdoTools, then click on pdoMenu left-click (do not release the button) and drag this snippet to the place where you want to call the menu, then in the window that opens, fill in the necessary parameters and click " Save«.

    Option 2... We just manually write the call.

    Typical examples

    Normal single-level menu

    For example, we have the most common menu, with the following html markup.

    The result is the following code with a menu call:

    • & parents = `0` - a list of parents (in my case, I do not limit the selection, since I will only display certain pages anyway);
    • & level = `1` - nesting level (in this case there is none);
    • & resources = `2,3,4,5` - a list of resources to be displayed in the menu;
    • & firstClass = `0` - class for the first menu item (not which one);
    • & lastClass = `0` - the class of the last menu item (not any);
    • & outerClass = `top-menu` - class of the menu wrapper (substituted in ul);
    • & hereClass = `current-menu-item` - class for the active menu item (substituted in li);
    • & rowClass = `menu-item` - class of one menu row (substituted in li).

    Two-level custom bootstrap menu

    The static html code looks like this:

    Its output code will be like this:

    Also, in the next lesson I will give a couple more conclusions of drop-down menus, based on bootstrap (and, this is for those who did not get the point. Well, then we will do it.

    At first glance, everything looks complicated, but that is not so, read the documentation in more detail, ask questions in the comments, I will definitely help.