Jump to content

Community

Rikki

Invision Community Team
  • Posts

    24,342
  • Joined

  • Days Won

    79

Reputation Activity

  1. Like
    Rikki got a reaction from The Old Man for a guide, Best practices for your themes   
    While the theme system allows almost limitless customization possibilities, there are a few best practices that we recommend you follow. They will make things easier for both you and site admins who choose to use your theme.
     
    Don't edit default CSS files
    Whenever a default theme file is edited, it makes upgrading a site a little more difficult because the customizations have to be handled. This is an easy problem to solve for CSS because by its nature it cascades - that means you can create your own CSS files that overwrite styles defined in our default CSS files, without impacting the ability for the suite to update the default CSS file later upon upgrade.
    By way of encouragement, we ship an empty CSS file called custom.css which you can use as a starting point for your changes. For simpler themes, keeping your changes in this one file might be sufficient. However, you can create more custom CSS files in the custom group if you wish, and they'll be automatically included (no need to use @import statements).

     
    The IPS Community Suite always includes your custom CSS files last in the loading order, so you can use the same selectors you see in the default CSS files and your new styles should overwrite the default.
     
    Keep template changes to a minimum
    Similar to the above, editing templates can lead to difficulty with upgrades, because customized templates may be missing new HTML necessary for a new feature, or worse, break the templates by calling a variable that has since been removed.
    However, unlike CSS files, templates can't cascade, and sometimes editing a template is the only choice. Therefore, we recommend you try to keep these edits to a minimum. There's a few strategies for doing so:
    Use CSS where possible
    It may be tempting to adjust the HTML in templates to help achieve some particular visual style. We recommend exploring using CSS to do this instead wherever possible because it will make maintaining your theme much easier in the long run. Use template includes and custom templates where appropriate
    If you're adding a larger block of HTML to a template (more than a couple of lines), consider putting that code in a custom template bit instead, and then calling that template from the default template. That way, the customization to the default template is a simple include tag that can easily be reverted and added back later without much effort. To call a custom template, you can do: {template="myCustomTemplate" group="<group>" app="<app>"} where <group> and <app> are the keys for the location you chose when you created your custom template bit.
    Consider creating a hook instead
    Application hooks have the ability to adjust templates by 'hooking' into the code inside them. In some situations, using a hook to adjust the template may be more appropriate that editing the template contents directly.
     
    Remember mobile support
    The IPS Community Suite has been designed from the ground up to be responsive; that is, the same theme works on devices regardless of screen size, whether it's a desktop monitor or a phone. When you make changes to your theme, remember to consider mobile support and ensure you include responsive styles too. You can use a tool like Google Chrome's web inspector to mimic different screen sizes, or use a tool like BrowserStack to test your theme on real devices
     
    Remember right-to-left support
    The IPS Community Suite is designed to work fully with both left-to-right (LTR) and right-to-left (RTL) languages. If you are creating a theme that you plan to share with others (rather than one just for your own use), keep RTL support in mind. The next step of this guide covers some steps you can follow to support it.
  2. Like
    Rikki got a reaction from The Old Man for a guide, Adding custom editor buttons   
    If an existing CKEditor plugin isn't available that meets your needs, another alternative that may be suitable is to create a custom button.
     
    What can custom buttons do?
    Custom buttons allow you to create blocks of HTML that are inserted by clicking a button on the editor toolbar. The blocks you create can accept content that users can enter.
    Custom buttons don't have the capabilities of a full CKEditor plugin - they can't be dynamic or use Javascript, for example. But for formatting text the user enters, a custom button may be the best choice.
    Note: although custom buttons tend to be simple, we recommend you have knowledge of HTML, or seek assistance from our peer-to-peer forums.
     
    Creating a custom button
    To create a custom button, navigate to Customization -> Editor -> Toolbars. Click the Add Button button in the header, and then the Custom tab. The form you see has the following fields:
    Button title
    The title seen by users when they hover over the button in the editor Icon
    A small image file that will act at the button icon on the editor. For retina support, upload an icon twice as big as you'd like it to display; it will be resized down by the browser and therefore show high-res. Type
    Three types of content are supported, and they roughly mimic the three types of element display in HTML: Inline - used when the inserted HTML exists somewhere in a line of text. Does not create a new line for the content. Single line block - designed for single lines (e.g. headers), and puts the block on a new line Block - used for multiple lines, and puts the block on a new line Use option
    A custom button can optionally accept a value from the user (aside from what they can type as normal inside the block itself). This option will appear as a popup dialog when the user clicks the button in the editor, and the value they enter is passed into the block when it is rendered. With this field enabled, you'll see an additional setting: Option label
    The text shown to the user requesting a value for the option. HTML
    The actual HTML the button will render in the editor when used. Generally, any HTML is supported but it must be valid. Within this HTML, a couple of special tags can be used: {option}
    If the option is used, this tag is replaced with the value the user entered, as-is. {content}
    If your button will allow the user to type within the generated HTML, insert this tag where the user should be able to type. Click the Save button to create the button. Your icon will be shown on the Buttons Not On Editor toolbar, and from here you can drag it to your live toolbars and configure it as normal.
     
    Using custom styles
    We don't recommend using inline styles in your HTML, because it will be almost impossible for you to update later (posts are built at save-time, not display-time, so if you update a custom button, old posts won't reflect those changes).
    Instead, we suggest using classnames, and adding styles for those classnames in your custom.css theme file. This way, you can update the styles later, and old posts will also reflect the changes.
     
    An example
    Within this documentation we have tip boxes like this:
    Tip This is a tip
    This is a custom editor button we've created that is available to staff. Here's the configuration we used to create this button:
    Button title
    Tip Icon
    Type
    Block Use option
    No HTML <div class='docsBox docsBox_tip'> <div class='docsBox_header'>Tip</div> <div class='docsBox_body'> <div class='ipsType_richText ipsType_break ipsContained'> {content} </div> </div> </div>  
    We then add these styles to our custom.css CSS file:
    .docsBox_header { padding: 5px 10px; color: #fff; font-weight: 500; font-size: 15px; } .docsBox_body { padding: 10px; font-size: 13px; line-height: 1.4; } .docsBox_tip .docsBox_header { background: #2E7D32; } .docsBox_tip .docsBox_body { background: #E8F5E9; } .docsBox_tip .docsBox_body .ipsType_richText { color: #1B5E20; }  
  3. Like
    Rikki got a reaction from The Old Man for a guide, Targeting elements on specific pages with CSS   
    Occasionally, you'll want to be able to change the style of a particular element on a particular page, without affecting similar elements on other pages. For example, lets say you wanted to change how the .ipsPageHeader element looks in topic view, to make the title bigger, but without changing it for all other pages that also use .ipsPageHeader.
     
    Adding a classname - the wrong way
    One method would be to edit the template for topic view, add a classname to the element, and then create a style using that new classname as the selector. This works, but it has a drawback - because you've edited the template, IPS4 won't be able to automatically update it for you when you upgrade to newer versions of the IPS Community Suite. We always suggest you try and avoid editing templates directly, for this reason.
     
    Using page-specific selectors - the right way
    There's a better way - every page in IPS4 includes some special attributes on the body tag that identify the app, module and controller being viewed. You can use these to write a CSS selector to only target pages that match the ones you want. Going back to our example, we could target .ipsPageHeader in topic view like so:
    body[data-pageapp="forums"][data-pagemodule="forums"][data-pagecontroller="topic"] .ipsPageHeader { ...your styles } This works because topic view is generated by the topic controller, in the forums module, in the forums app. All pages in the IPS Community Suite follow this controller/module/application structure.
    You can mix and match these. If you want to style all page headers in the forums app only, you could simplify the above to:
    body[data-pageapp="forums"] .ipsPageHeader { ...your styles } You can find out the right values to use by going to the page you want to target, viewing the source in a tool like Web Inspector, and finding the body tag - look for the special data-page* attributes that are used for that page.
    By including these styles in your custom.css file in your theme, you can target specific elements on specific pages, without making it difficult to upgrade your community later.
  4. Like
    Rikki got a reaction from 60kell for a guide, Buttons   
    Basics
    The button classes described here can be applied to any element, although typically would be applied to an element like a, input[type="submit"] or button so that the user can interact with it.
    As a minimum, a button should receive the basic ipsButton class, plus a size class and a style class (explained below).
     
    Button styles
    ipsButton_normal
    Normal button ipsButton_primary
    Primary button ipsButton_alternate
    Alternate button ipsButton_important
    Important button ipsButton_light
    Light button ipsButton_veryLight
    Very light button ipsButton_overlaid
    Overlaid button ipsButton_link
    Link button  
    Button sizes
    ipsButton_medium
    Medium button ipsButton_verySmall
    Very small button ipsButton_small
    Small button ipsButton_large
    Large button ipsButton_veryLarge
    Very large button ipsButton_fullWidth
    Can be combined with another size, above.
    Full width button  
    Disabled buttons
    Buttons can be visually disabled either by adding the class ipsButton_disabled, or, on relevant input elements, adding the disabled property. For example:
    <a href='#' class='ipsButton ipsButton_normal ipsButton_medium ipsButton_disabled'>Disabled button (link)</a> <input type='submit' class='ipsButton ipsButton_normal ipsButton_medium' disabled value='Disabled button (input)'> These would render like so:
    Disabled button (link)  
    Split buttons
    Split buttons allow you to create toolbars easily by specifying a list of buttons that display joined to each other.
    They are created by specifying the class ipsButton_split on a wrapper element containing two or more buttons. The wrapper element can be a <ul> tag, or any other that makes sense for your use.
    All of the buttons in a split button group should be the same size, otherwise results are unpredictable. Different styles can be used on each button, though.
    <ul class='ipsButton_split'> <li><a href='#' class='ipsButton ipsButton_small ipsButton_primary'>Button 1</a></li> <li><a href='#' class='ipsButton ipsButton_small ipsButton_light'>Button 2</a></li> <li><a href='#' class='ipsButton ipsButton_small ipsButton_light'>Button 3</a></li> </ul> Button 1 Button 2 Button 3  
  5. Like
    Rikki got a reaction from BomAle for a guide, ips.utils.position   
    Description
    Dealing with element positioning - getting current positions, working out new positions, and so on - is a common task in a web application such as IPS4. This utility aims to make that easier by providing some methods to do the calculations for you.
     
    Methods
    object getElemPosition( mixed elem )
    Returns various positioning information for the provided element.
    elem
    DOM element or jQuery object containing the element to work with Returned object:
    absPos left
    Absolute left position right
    Absolute right position (i.e. left + width) top
    Absolute top position bottom
    Absolute bottom position (i.e. top + height) viewportOffset left
    Viewport left offset (i.e. left offset - left scroll postion) top
    Viewport top offset (i.e. top offset - top scroll position) offsetParent
    Reference to the element's offsetParent. That is, the closest element that has a non-static position. fixed
    true if the element has any ancestors which have fixed positioning or have one of the table display values.  
    object positionElem( object options )
    Returns positioning values, allowing the calling method to appropriate position the element with a best-fit on the screen. This method does not apply the positioning values to the element itself.
    options trigger
    The trigger element for this popup; that is, the element that the popup should be 'attached' to target
    The element to be positioned targetContainer
    The element that contains the element to be positioned. Assumed to be body if not provided. center (boolean)
    Specifies whether the method should attempt to position the target centered relative to the trigger. above (boolean)
    Specifies whether the method should attempt to position the target above the trigger. By default, a best fit is attempted. Returned object:
    top
    Ideal top position, in pixels left
    Ideal left position, in pixels fixed
    Whether the element should have fixed positioning applied (because an ancestor does) location horizontal
    Best horizontal location for the element; either center, left or right vertical
    Best vertical location for the element; either bottom or top  
    boolean hasFixedParents( mixed elem )
    Returns true if any of the element's descendants have fixed positioning or have one of the table display classes (e.g. table-row).
    elem
    The element whose ancestors are being checked for fixed positioning. Either a DOM node or a jQuery object.  
    object getElemDims( mixed elem )
    Returns current dimension information for the element.
    elem
    The element whose dimensions are being returned. Either a DOM node or a jQuery object. Returned object:
    width
    Current width in pixels height
    Current height in pixels outerWidth
    Current outer width of the element; that is, the width plus border and padding outerHeight
    Current outer height of the element; that is, the width plus border and padding  
    number nautralWidth( mixed elem )
    Returns the natural width of the provided element (which should be an img element). The natural width is the original width of the image not accounting for any resizing done by CSS or HTML attributes.
    elem
    The element whose natural width is being returned. Either a DOM node or a jQuery object.  
    number nautralHeight( mixed elem )
    Returns the natural height of the provided element (which should be an img element). The natural height is the original height of the image not accounting for any resizing done by CSS or HTML attributes.
    elem
    The element whose natural height is being returned. Either a DOM node or a jQuery object.  
    number lineHeight( mixed elem )
    Attempts to return the computed line-height, in pixels, of the provided element. There are edge cases where this result won't be reliable, such as CSS styling <span> tags inside the element differently to the element itself. Test your use case.
    elem
    The element whose line-height is being returned. Either a DOM node or a jQuery object.
  6. Like
    Rikki got a reaction from citrixws for a guide, Common logic checks using HTML Logic   
    HTML Logic is a very powerful way of conditionally showing different elements in your theme, depending on the values of certain properties. Since the entire IPS4 framework is available within a logic expression, there's a lot of scope for using different kinds of data to determine what should show.
    In this guide we'll provide a range of examples of common logic checks you might want to do. Even if the exact expression you need isn't listed here, it should provide a good starting point to help you write your own expressions.
     
    Logic Recap
    Let's quickly recap how HTML Logic works. For a more complete tutorial, be sure to read through the Template Syntax guide.
    In IPS4, logic checks are done using the special {{if}}, {{else}} and {{elseif}} tags. As with standard programming logic, if the expression results in true, the block of code within is executed. If it is false, it isn't (and if there's an else or elseif block, that is tested for a true result instead). So, a block of logic in a template might look like this:
    {{if member.member_id == 3}} <!-- If the member has ID 3, this will be shown --> {{elseif member.member_id == 9}} <!-- But if the member has ID 9, this will be shown instead --> {{else}} <!-- If the member isn't ID 3 or 9, then this will show --> {{endif}} If you need help constructing a logic check, feel free to check out the Customization Resources forum.
     
    Examples. I want to...
    Check if the user is logged in
    {{if member.member_id}} <!-- this will show if the member is logged in --> {{endif}}  
    Check if the user isn't logged in
    {{if !member.member_id}} <!-- this will show if the user is a guest --> {{endif}}  
    Check if the user's ID is one of x, y or z
    You can check as many values as you like; just add more numbers to the array.
    {{if in_array( member.member_id, array( 5, 28, 472 ) )}} <!-- Shows if the member's ID is 5, 28 or 472 --> {{endif}}  
    Check if the user is in group x
    Where x is the group ID number. Note that this also checks secondary member groups.
    {{if member.inGroup('x')}} <!-- Shows if member is in group 'x' --> {{endif}}  
    Check if the user has more than x posts
    In IPS4, all content in all apps counts as a 'post'.
    {{if member.member_posts > 3}} <!-- Shows if the member has more than 3 posts --> {{endif}}  
    Check if the user has fewer than x posts
    In IPS4, all content in all apps counts as a 'post'.
    {{if member.member_posts < 3}} <!-- Shows if the member has fewer than 3 posts --> {{endif}}  
    Check if the user is an administrator
    Note that this also checks if any of the user's secondary member groups has admin permissions.
    {{if member.isAdmin()}} <!-- Shows if the user is an administrator --> {{endif}}  
    Check if the user is banned
    {{if member.isBanned()}} <!-- Shows if the user is banned --> {{endif}}  
    Check if the current page is part of app x
    You need to check the application key. Most are obvious (e.g. forums is the forums app), but there are some others to be aware of. For custom/third-party apps, ask the author which app key they use.
    core = Any system page that isn't part of another app, e.g. search, login/registration, profiles etc. cms = Pages nexus = Commerce {{if request.app == 'forums'}} <!-- Shows if the user is viewing any page in the 'forums' app --> {{endif}}  
    Check if a system setting has value x
    You can check whether system settings have a given value, although you will need to know the setting key used by the backend. Values may not be simple to check, depending on their type - consult our Customization Resources forum if you aren't sure how to check a particular setting.
    {{if settings.auto_polling_enabled}} <!-- Shows if the 'auto_polling_enabled' setting is true (i.e. enabled) --> {{endif}}  
    Check a variable in a template has value x
    Template bits in IPS4 may receive one or more variables from the backend code. You can check the values of these within the template to do something based on the value. This only works within the template into which the variable you are checking is passed - they are not inherited.
    {{if $myVariable == 'some_value'}} <!-- Shows if $myVariable is equal to 'some_value' --> {{endif}}  
    Check if the current forum is forum ID x
    Within the forums app, you can check whether the current page is showing the forum with ID x
    {{if request.app == 'forums' && request.module == 'forums' && request.id == 3}} <!-- Shows if the user is in the forums app, viewing a forum with the ID 3 --> {{endif}} .
  7. Like
    Rikki got a reaction from Night Wolf for a guide, Common logic checks using HTML Logic   
    HTML Logic is a very powerful way of conditionally showing different elements in your theme, depending on the values of certain properties. Since the entire IPS4 framework is available within a logic expression, there's a lot of scope for using different kinds of data to determine what should show.
    In this guide we'll provide a range of examples of common logic checks you might want to do. Even if the exact expression you need isn't listed here, it should provide a good starting point to help you write your own expressions.
     
    Logic Recap
    Let's quickly recap how HTML Logic works. For a more complete tutorial, be sure to read through the Template Syntax guide.
    In IPS4, logic checks are done using the special {{if}}, {{else}} and {{elseif}} tags. As with standard programming logic, if the expression results in true, the block of code within is executed. If it is false, it isn't (and if there's an else or elseif block, that is tested for a true result instead). So, a block of logic in a template might look like this:
    {{if member.member_id == 3}} <!-- If the member has ID 3, this will be shown --> {{elseif member.member_id == 9}} <!-- But if the member has ID 9, this will be shown instead --> {{else}} <!-- If the member isn't ID 3 or 9, then this will show --> {{endif}} If you need help constructing a logic check, feel free to check out the Customization Resources forum.
     
    Examples. I want to...
    Check if the user is logged in
    {{if member.member_id}} <!-- this will show if the member is logged in --> {{endif}}  
    Check if the user isn't logged in
    {{if !member.member_id}} <!-- this will show if the user is a guest --> {{endif}}  
    Check if the user's ID is one of x, y or z
    You can check as many values as you like; just add more numbers to the array.
    {{if in_array( member.member_id, array( 5, 28, 472 ) )}} <!-- Shows if the member's ID is 5, 28 or 472 --> {{endif}}  
    Check if the user is in group x
    Where x is the group ID number. Note that this also checks secondary member groups.
    {{if member.inGroup('x')}} <!-- Shows if member is in group 'x' --> {{endif}}  
    Check if the user has more than x posts
    In IPS4, all content in all apps counts as a 'post'.
    {{if member.member_posts > 3}} <!-- Shows if the member has more than 3 posts --> {{endif}}  
    Check if the user has fewer than x posts
    In IPS4, all content in all apps counts as a 'post'.
    {{if member.member_posts < 3}} <!-- Shows if the member has fewer than 3 posts --> {{endif}}  
    Check if the user is an administrator
    Note that this also checks if any of the user's secondary member groups has admin permissions.
    {{if member.isAdmin()}} <!-- Shows if the user is an administrator --> {{endif}}  
    Check if the user is banned
    {{if member.isBanned()}} <!-- Shows if the user is banned --> {{endif}}  
    Check if the current page is part of app x
    You need to check the application key. Most are obvious (e.g. forums is the forums app), but there are some others to be aware of. For custom/third-party apps, ask the author which app key they use.
    core = Any system page that isn't part of another app, e.g. search, login/registration, profiles etc. cms = Pages nexus = Commerce {{if request.app == 'forums'}} <!-- Shows if the user is viewing any page in the 'forums' app --> {{endif}}  
    Check if a system setting has value x
    You can check whether system settings have a given value, although you will need to know the setting key used by the backend. Values may not be simple to check, depending on their type - consult our Customization Resources forum if you aren't sure how to check a particular setting.
    {{if settings.auto_polling_enabled}} <!-- Shows if the 'auto_polling_enabled' setting is true (i.e. enabled) --> {{endif}}  
    Check a variable in a template has value x
    Template bits in IPS4 may receive one or more variables from the backend code. You can check the values of these within the template to do something based on the value. This only works within the template into which the variable you are checking is passed - they are not inherited.
    {{if $myVariable == 'some_value'}} <!-- Shows if $myVariable is equal to 'some_value' --> {{endif}}  
    Check if the current forum is forum ID x
    Within the forums app, you can check whether the current page is showing the forum with ID x
    {{if request.app == 'forums' && request.module == 'forums' && request.id == 3}} <!-- Shows if the user is in the forums app, viewing a forum with the ID 3 --> {{endif}} .
  8. Like
    Rikki got a reaction from Eupolemos for a guide, Responsiveness   
    Introduction to responsive classes
    IPS4's CSS framework is responsive, meaning elements adapt according to the size of the display the users chooses to use. In most cases, the existing classes already outlined in this guide take care of it for you; for example, menus automatically adjust, and tab bars collapse into a dropdown menu on mobile phones.
    There may be times when you need to control on which devices sizes elements show or hide themselves. For example, if you add a custom footer element, you may want to only show it on desktop, and hide it from tablets or phones.
    The responsive classes that IPS4 provides allow you to control this kind of behavior.
     
    Responsive sizes used by IPS4
    For the purposes of the media queries we use to control responsiveness, the following sizes represent each device:
    Phones - up to 767 pixels wide Tablets - between 768 pixels and 979 pixels wide Desktops - 980 pixels and wider  
    Basic show/hide functionality
    The CSS framework includes two groups of three classes that show or hide elements on desktop, tablet and phone-sized devices, respectively. The classes act in an exclusive way; that is, if you use the show classes, any devices that don't match will not show the element. The opposite is also true; if you use the hide classes, then the element will not show on those devices but will show on the others not specified.
    The classes are:
    ipsResponsive_hidePhone ipsResponsive_hideTablet ipsResponsive_hideDesktop ipsResponsive_showPhone ipsResponsive_showTablet ipsResponsive_showDesktop You can combine these as needed. For example:
    <div class='ipsResponsive_hidePhone ipsResponsive_hideTablet'> This element *will not* display on phones or tablets, but *will* display on desktops </div>  
    Additional classes to control element display
    When using the show classes outlined above, you typically need to include an additional class that controls how the element is rendered. This can be one of the following:
    ipsResponsive_block ipsResponsive_inlineBlock ipsResponsive_inline <div class='ipsResponsive_showDesktop ipsResponsive_block'> This element will *only* show on desktop sizes, and will render as a block-level element. </div> These additional classes aren't usually necessary when using the hide classes.
  9. Like
    Rikki got a reaction from DeanW for a guide, Pages   
    The foundation of Pages (the application) is the page (the thing).
    Tip To alleviate confusion in these tutorials, the application "Pages" will always be referred to with a capital letter; pages within the application or community will be lowercase.
    What is a page?
    A page is a container for content. Depending on your needs, a page can simply contain simple content (whether that's plain text, or rich content with images, embeds, and the other things you're used from our other applications), or more complex content like blocks and databases (see later steps to find out more about those).
    If you are comfortable with code, you can also use all of our standard template logic in a page, allowing for some highly custom results. For those who aren't comfortable with coding, there's an easy page builder, allowing you to drag and drop components into your page.
    A page has a URL, and can be automatically added to your menu navigation when you create it, if you wish.
    A page can also have custom permissions, allowing you to restrict who can or cannot access the page. This is great if you want to build special sections of your site, perhaps for staff or premium members only.
    Prior to Invision Community 4.3, Pages were not searchable (although external search engines such as Google will index them). However, if you have a database on a page, the content of the database will be searchable.
    Creating Pages
    Pages are created via the AdminCP, by navigating to Pages -> Pages. A directory listing of your current pages will be shown. Folders are supported here as you'd expect; the URL of the page will reflect this structure. For example, a page called index in a folder called guides will have the URL <your community URL>/guides/index. 
    When you click the Add Page button, you are asked whether you want to use the Page Builder or Manual HTML.

    Page Builder
    After creating the page in the AdminCP, you'll be able to go to the front-end to add content to your page, using drag and drop from the sidebar manager. This option is best for those not familiar with HTML. Manual HTML
    When you choose this option, you'll be provided with a code editor to create your page. Within this code editor you're free to use HTML, as well as the full range of template logic supported by IPS4. With this method, you insert other items (blocks, databases etc.) into the page by using special tags. A sidebar on the editor show you the available tags.  
    Managing content in pages with the drag and drop editor
    If you've created a page using the Page Builder options, after saving the configuration in the AdminCP, you can head over to the page on the front-end to manage its content (click the View Page option from the menu on the page listing screen to easily navigate to it). 
    By default, the page will be empty. Click the sidebar toggle to open the sidebar and see the available widgets. All of the usual widgets are available to you from across the suite, but under the Pages category are a handful of special reusable widgets:

    Of these, WYSIWYG Editor is the one you'd be most likely to use when setting up your pages. It gives you a standard IPS4 rich text editor to add content to the page. Simply drag it into a location on your page, then click the Edit button to access the editor. We won't cover the other blocks here since they are specific to other kinds of functionality within Pages.
    Managing content in pages using Manual HTML
    When you create a page using manual HTML, you can choose how much of the standard IPS4 wrapper you start with. By default, the suite wrapper is included in the output. This encompasses the header, menu navigation etc., meaning the content of your page is inserted inside this wrapper. With this option disabled, the suite wrapper isn't used - you'll be responsible for providing this (you can however choose a custom page wrapper you've created).
    If you use the suite wrapper, you can also choose whether the standard sidebar is included in the output. The content you enter into the code editor forms the main page content, and the sidebar will be managed as usual with drag and drop on the front-end.
    Adding to Navigation
    When you create a page, you can easily add it to your site's main navigation menu under the Menu tab on the page edit screen. Alternatively, you can add it to the menu manually via the normal menu management process.
     
    Setting as Default
    Often you will wish to set the pages application as your default application, so that you can show a page you created as your default homepage. For this, along with how to create a basic homepage, please refer to the following guide.
     
  10. Like
    Rikki got a reaction from kyriazhs1975 for a guide, Pages   
    The foundation of Pages (the application) is the page (the thing).
    Tip To alleviate confusion in these tutorials, the application "Pages" will always be referred to with a capital letter; pages within the application or community will be lowercase.
    What is a page?
    A page is a container for content. Depending on your needs, a page can simply contain simple content (whether that's plain text, or rich content with images, embeds, and the other things you're used from our other applications), or more complex content like blocks and databases (see later steps to find out more about those).
    If you are comfortable with code, you can also use all of our standard template logic in a page, allowing for some highly custom results. For those who aren't comfortable with coding, there's an easy page builder, allowing you to drag and drop components into your page.
    A page has a URL, and can be automatically added to your menu navigation when you create it, if you wish.
    A page can also have custom permissions, allowing you to restrict who can or cannot access the page. This is great if you want to build special sections of your site, perhaps for staff or premium members only.
    Prior to Invision Community 4.3, Pages were not searchable (although external search engines such as Google will index them). However, if you have a database on a page, the content of the database will be searchable.
    Creating Pages
    Pages are created via the AdminCP, by navigating to Pages -> Pages. A directory listing of your current pages will be shown. Folders are supported here as you'd expect; the URL of the page will reflect this structure. For example, a page called index in a folder called guides will have the URL <your community URL>/guides/index. 
    When you click the Add Page button, you are asked whether you want to use the Page Builder or Manual HTML.

    Page Builder
    After creating the page in the AdminCP, you'll be able to go to the front-end to add content to your page, using drag and drop from the sidebar manager. This option is best for those not familiar with HTML. Manual HTML
    When you choose this option, you'll be provided with a code editor to create your page. Within this code editor you're free to use HTML, as well as the full range of template logic supported by IPS4. With this method, you insert other items (blocks, databases etc.) into the page by using special tags. A sidebar on the editor show you the available tags.  
    Managing content in pages with the drag and drop editor
    If you've created a page using the Page Builder options, after saving the configuration in the AdminCP, you can head over to the page on the front-end to manage its content (click the View Page option from the menu on the page listing screen to easily navigate to it). 
    By default, the page will be empty. Click the sidebar toggle to open the sidebar and see the available widgets. All of the usual widgets are available to you from across the suite, but under the Pages category are a handful of special reusable widgets:

    Of these, WYSIWYG Editor is the one you'd be most likely to use when setting up your pages. It gives you a standard IPS4 rich text editor to add content to the page. Simply drag it into a location on your page, then click the Edit button to access the editor. We won't cover the other blocks here since they are specific to other kinds of functionality within Pages.
    Managing content in pages using Manual HTML
    When you create a page using manual HTML, you can choose how much of the standard IPS4 wrapper you start with. By default, the suite wrapper is included in the output. This encompasses the header, menu navigation etc., meaning the content of your page is inserted inside this wrapper. With this option disabled, the suite wrapper isn't used - you'll be responsible for providing this (you can however choose a custom page wrapper you've created).
    If you use the suite wrapper, you can also choose whether the standard sidebar is included in the output. The content you enter into the code editor forms the main page content, and the sidebar will be managed as usual with drag and drop on the front-end.
    Adding to Navigation
    When you create a page, you can easily add it to your site's main navigation menu under the Menu tab on the page edit screen. Alternatively, you can add it to the menu manually via the normal menu management process.
     
    Setting as Default
    Often you will wish to set the pages application as your default application, so that you can show a page you created as your default homepage. For this, along with how to create a basic homepage, please refer to the following guide.
     
  11. Like
    Rikki got a reaction from BomAle for a guide, Mixins   
    Mixins are a special type of controller that allow you to augment or change the functionality of an existing controller. This is particularly useful when you need to change something about how a built-in controller works.
     
    Basic structure
    This is the boilerplate for a mixin:
    ;( function($, _, undefined){ "use strict"; ips.controller.mixin('mixinName', 'core.global.core.table', true, function () { // Your code goes here }); }(jQuery, _)); The method signature is:
    ips.controller.mixin( string mixinName, string extendsController, boolean autoLoad, function mixinBody ) mixinName
    A name that will refer to this mixin extendsController
    The full name of the controller that this mixin will extend (e.g. core.global.core.table) autoLoad
    Boolean indicating whether this mixin should always extend the extendsController controller, or only when specified mixinBody
    A function that returns the behaviors that the mixin defines  
    How a mixin works
    A mixin works by allowing you to provide custom code that will execute at key points when the parent controller's method is called. To do that, there are three important methods available to a mixin:
    before()
    Run the specified code before the parent controller's method after()
    Run the specified code after the parent controller's method around()
    The specified code is passed a reference to the parent controller's method, allowing it to be called when desired (and the return value modified In addition to hooking into existing controller methods, your mixin can also provide new methods for its own use and, notably, simply redefine a method present in the parent controller in order to completely replace its functionality.
     
    A note about this
    Within the mixin body, you'll be adding methods to this. The mixin executes in the same context as the parent controller; that is, this in a mixin refers to both the mixin and the controller it extends, allowing you to call methods from the controller, and any create yourself in the mixin. During execution, they are one and the same.
    The same is also true within methods in your mixin since, like in controllers, methods are automatically bound to the controller for you. You may be familiar with this.scope in controller methods (which refers to the DOM element onto which the controller is applied). Since mixin methods are bound in exactly the same way, using this.scope in a mixin method will still give you the element onto which the controller is applied.
     
    before() and after()
    The behavior of these two methods are very similar. They simply allow you to execute your custom code either immediately before, or immediately after the parent controller's code. Your custom code receives the parameters that are passed into the parent method, but not the return value (if any).
    A common usage of either method is to add additional event handlers to a controller. A controller sets up its event handlers in the initialize method, and so a mixin can add more handlers like so:
    this.before('initialize', function () { this.on('click', '#button', this._doSomething); this.on('click', '#button2', this._doSomethingElse); }); In this case, our function will be executed, and then the parent's own initialize method will be executed.
    In this example we don't deal with any parameters but, if the parent method is called with any, they will also be available to your mixin function as normal parameters, in the same order.
     
    around()
    This behaves differently to the previous example, because rather than simply being executed before or after the parent, it actually provides the parent method as a reference to your own function. This allows you to call the parent method at a time of your choosing - perhaps determined based on some logic in your code. Since you have control over calling the parent method, you also have access to its return value, meaning that around can also be used as a way to modify the value that is returned from a controller method.
    As an example, let's assume that the parent controller method returns a JSON object, but we want to augment this with some additional key/values. We can do this using the around call, like so:
    this.around('parentMethod', function (origFn) { var returned = origFn(); return _.extend( returned, { key1: true, key2: false }); }); Notice that the parent method is passed in as a parameter (if the method has any other parameters, these will appear first, and the parent method will be the last parameter). We call this method in order to get its return value for our own use. When we look at the parent method we know that it returns a JSON object, so we extend it with our own values.
    It's worth noting that since you receive both the original parameters, and a reference to the parent method, you have the ability to modify the parameter values before passing them into the parent method. This approach can offer a lot of flexibility.
     
    Custom methods and replacing existing methods
    Finally, you can create new methods in your mixin, or completely replace methods from the parent controller by redefining them. In both cases, this is done like so:
    this.myMethod = function () { //... }; Of course, if you replace an existing method, be sure it plays nicely with any calls to it!
     
    Calling a mixin
    Mixins can be applied to controllers manually when needed (you don't need to do this if you configured your mixing to automatically apply to the controller, though). To do so, specify the mixin name in parenthesis after the controller. For example:
    <div data-controller='core.front.core.someController( mixinName )'> </div> Multiple mixins can be provided if they are comma-delimited.
    Note that mixin files are not loaded on demand in the same way that controller files may be (but they will be compiled into bundles in the same way at build-time). In order for a mixin to be applied, it must be included in the page output. This means that if you're creating a plugin that (for example) has a mixin that applies to a core controller, you are responsible for ensuring the mixin file is included in the page as needed. This may mean creating a theme hook that modifies the output of the includeJS template.
  12. Like
    Rikki got a reaction from Tomasz Nowak_59903 for a guide, Icons   
    Description
    We make use of an icon font called FontAwesome. This enables us to display icons that are accessible, that don't require an additional HTTP request, that can be styled with CSS (and inherit styling automatically), and which scale without loss of quality.
     
    Usage
    An icon can be included within the markup by using the following code:
    <i class='fa fa-iconname'></i> The list of possible icons and their classnames is available at http://fontawesome.io/icons/. Note that these classnames are not prefixed with ips as with other framework classes; they are left with their default names as they appear on the FontAwesome website.
    Icons can be used anywhere that HTML can be used. For example, within text, on buttons, in menus and more.
        Icon on a button    A caret icon indicates a dropdown     Yes, I think so   No, I disagree   This is another caret  
    Icon consistency
    It is important that icon use remains relatively consistent throughout the suite. This applies to core developers as well as addon developers. If different icons are used for the same purpose (or worse, an icon is used for a purpose different to it's usual purpose), users will become confused by the software.
    To help alleviate this, we have a list of icons that we generally refer to when choosing an icon to represent an action. Check this list to see if your action already has an associated icon, and lean towards using that instead of choosing another.
    The list below organizes actions, with the title being a general concept. The icon names are FontAwesome icons, without the preceding fa-
     
    Adding
      plus-circle   plus Deleting
      times-circle   trash-o Editing
      pencil Reverting
      undo Go Somewhere
      arrow-right Open External Link
      external-link Confirming Yes/No
      check   times Permissions
      lock   unlock Log In/Sign In
      key Copy
      copy Settings
      cog Flagging On/Off
      flag   flag-o Star On/Off
      star   star-o Developer/Application
      cogs Help
      question-circle Merge
      level-up Code/PHP/HTML
      code Mail/Send Mail
      envelope-o Search
      search View
      search Refresh/Reload
      refresh Execute/Run Now
      play-circle Easy Mode/Visual Editor
      magic  
  13. Like
    Rikki got a reaction from Meddysong for a guide, Changing FontAwesome icons per-forum   
    By default, we use the 'comments' icon from FontAwesome to represent forums on the read/unread badges. IPS4 also includes an option to upload an image that will be used instead of the icon. But what if you want to use a different FontAwesome icon for each forum?
    The good news is this is possible using some custom CSS. Each forum row in the index template includes a data attribute with the forum ID, meaning we can write a style to specifically target each individual forum and overwrite the icon it uses.
    Note: Although this method isn't terribly complex, it does require editing custom CSS and working with unicode characters.
     
    Determining the icon unicode value
    The method we're going to use involves replacing the icon using a CSS rule, rather than changing the icon classname in the HTML. The reason we take this approach is it won't make upgrading your templates difficult later - our custom CSS persist through IPS4 versions easily.
    What this means however is that we need to identify the unicode value that FontAwesome assigns to the icons we want to use.
    To do so, head over to the FontAwesome icon list on this page. Locate the icon you'd like to use, and click it. On the information page, you'll see the unicode value for the icon. Make a note of this code. For example:

    Do this for each icon you'll want to use.
     
    Adding the CSS
    We're going to add our CSS to our custom.css file so that it persists through upgrades. In the AdminCP, go to Customizations -> Themes, and click the code edit icon next to the theme you want to change. On the CSS tab, open the custom.css file:

    The rule we need to use looks like this:
    [data-forumid="..."] .fa-comments:before { content: "\f123"; } You'll need to adjust this code to include the forum ID for the forum you want to change. You can find the forum ID by hovering on the link to the forum, and noting the number you see in the URL: 

    You'll also need to replace the f123 unicode value with the one for the icon you want to use that you noted earlier.
     
    Example
    Let's say we have forum ID's 1 and 2, and we want to use FontAwesome's bicycle and car icons, respectively. We note the unicode values for those icons, which are f206 and f1b9.
    The CSS we'd add looks like this:
    [data-forumid="1"] .fa-comments:before { content: "\f206"; } [data-forumid="2"] .fa-comments:before { content: "\f1b9"; } Once we save it, we can see the result:

  14. Like
    Rikki got a reaction from Simon Woods for a guide, Databases part II   
    Database URL structure
    Databases exist inside a page you've created with Pages. Individual categories and records in the database are accessed via the URL of the page. For example, if you had a page with the URL <yourcommunity>/mypage and this page contained your database, you might have a record that's accessed via the URL <yourcommunity>/mypage/category/record, where category is the category name and record is the record name. Your URLs would dynamically update themselves if you renamed your page or moved the database to a different page.
    To facilitate this approach, databases can only exist in one page at a time. They can't be duplicated on other pages (although you can create blocks showing data from the database and use them on other pages).
     
    Fields
    More advanced uses of databases require custom data to achieve their goals, and fields can be set up to gather this data. Fields are created in the AdminCP, and when a user adds a new record, the fields are shown on the form. 
    IPS4 supports a wide range of field types, allowing you to capture data of a specific type easily. Here's the supported types:
    Address
    Provides a special auto-completing address field, powered by Google Checkbox
    A single on/off checkbox Checkbox set
    A group of several on/off checkboxes Code
    Provides a way to syntax-highlight code Date
    A date field, with a date picker Editor
    Provides a rich text editor for WYSIWYG editing Database relationship
    An advanced field type that allows records from different databases to be associated Member
    Provides an auto-complete member search box Number
    A number input box (on older browsers, reverts to a simple text box but with number validation) Password
    A password input field Radio
    A group of radio boxes (meaning only one of the options can be selected) Select box
    A drop-down menu containing the provided options (can allow multiple selections if desired) Soundcloud
    A Soundcloud embed field Spotify
    A Spotify embed field Telephone
    A telephone number input field (on older browsers, reverts to a simple text box) Text (default)
    A one-line text input field Text Area
    A multiple-line text input field Upload
    An IPS4 upload field URL
    A URL input field (on older browsers, reverts to a simple text box with URL format validation) Yes/No
    A toggle field that can accept yes or no values YouTube
    A YouTube embed field Many of these field types have additional options specific to them. For example, select boxes have an option to allow multiple values to be selected, whereas the upload has options to allow multiple files, and a way to restrict file types.
    Field formatting
    Fields can have automatic formatting applied to them. For non-coders, a range of badge colors is available to choose from, and you have some control over the location that the field shows in the listing or record display. For coders, however, you have full control over the HTML output for each field, including having use of IPS4's template logic. This means you have the ability to use the data stored by IPS4 for each field in some very interesting ways - for example, you might take the value of an address field and use it to output an embedded Google Maps map, or even create some fields that you don't output, but instead use to control the layout of your record templates. There are a huge number of possibilities.
     
    Permissions
    There's multiple levels of permissions at play with databases:
    Page-level
    Since pages have their own permission settings, if the user doesn't have permission to see the page, they won't be able to see the database either. Database-level
    Permissions can be set at a database-level, which forms the default permissions for categories in the database too. Category-level
    A category can optionally override the database-level permissions and provide its own. This is useful for hidden categories - perhaps staff only, or a category only for premium members.  
    Managing databases
    Databases are managed by going to Pages -> Databases in the AdminCP. You'll also find that databases are listed in the Pages menu in the AdminCP for quicker access. From this screen, you'll see some simple information about each of your databases, as well as menu items to manage each part:

    Records can be added either via the AdminCP (click the   icon) or via the front-end page that displays the database. This means users don't need AdminCP access to add/edit records.
     
    Creating databases
    To create a database, click the Create New button on the screen above. There's a number of configuration options available to you.
    Details
    The basic settings for this database. At the bottom of this tab, you can choose the templates you want to use for this database. If you haven't created them yet, you always do this later.
    Language
    On the Language tab, you set up the words that will be used to refer to records in this database (rather than the generic 'records' terminology). For example, if you are creating a database for guides, these language choices will mean IPS4 will refer to your database in context, such as "Search Guides", "There are 5 guides in this database" and "Create a new guide".
    Options
    This tab more finely controls how your database will work, including comments, reviews, tagging, and the 'wiki-style' editing we covered earlier. Sorting options are also available here, allowing you to choose the order of records, and more importantly, the field on which they are sorted. For example, if you had a database containing records about dinosaurs, you may want to sort the records by Era (a custom field you will have created). You can return to this tag after creating your fields later to configure it.
    Forum
    This tab configures the aforementioned Forums integration for the database (individual categories can override these settings too).
    Page
    Since a database requires a page in which it displays, you can easily create one here as part of the database creation process. Alternatively, you can add it to one of your existing pages later.
     
    Adding a database to a page
    If you don't create a page as part of the database creation process (above), you can do so manually by using a special database tag in your page content. On the Details tab of the database form, you specified a database key. This is how this database is included in pages. If the key is my-database, you'd insert it into a page by placing this:
    {database="my-database"} As mentioned above, a database can only exist on one page at a time; trying to use this tag on multiple pages won't work correctly.
  15. Like
    Rikki got a reaction from Lewis Parker for a guide, Introduction to template syntax   
    What problem does HTML logic solve?
    In the IPS Community Suite, our templates are the 'view', i.e. how the data is rendered as HTML to the screen. However, basic HTML has no logic capabilities; what is in the HTML file is what is sent to the browser. In a complex application like ours, we need some way to make decisions about what is output.
    These decisions could potentially be made in the PHP backend, but that isn't appropriate in most cases; the backend should be focused on processing the data, while the view (our templates) control how the data is displayed.
    HTML logic allows us to make these decisions inside our templates. It mixes standard HTML with some special tags and flow-control statements, most of which are very similar to PHP.
     
    What other features do templates have?
    The result is that in one template, we can have logic that says output some HTML if a certain condition is met, or different HTML otherwise. We can also do loops on data, reducing repetition. We also have some special tags that call output plugins to transform values in some way (for example, to render dates from a timestamp). 
     
    Basic syntax
    There's three basic types of syntax you'll see. We will explore these in more detail in later steps.
    Logic tags
    Double-curly parenthesis. Controls flow in a template. In these tags, the expressions can be any valid PHP expression. Some examples:
    /* Basic structure */ {{if $condition}} ... {{else}} ... {{endif}} /* Examples of other expressions */ {{if !$condition}} {{if ( $color == 'green' && $size == 'big' ) || $condition}} {{if count( $value ) > 2}}  
    Variables
    Single-curly parenthesis. Outputs values passed into the template (or values from elsewhere, e.g. a loop).
    {$value}  
    Output plugins
    Pass the provided value through the specified output plugin.
    {pluginName="value"}  
  16. Like
    Rikki got a reaction from kar3n2 for a guide, Adding custom fields   
    Custom fields are what you use to make a database that is specific to your needs. IPS4 supports a wide range of field types so that you can collect data in the appropriate formats, from text and numbers, to upload fields and YouTube embeds.
    We're going to create a few different fields to gather information about each recipe that we can then display in our database. They are:
    List of ingredients Prep time Cook time Cuisine A link to a YouTube video recipe We don't need fields for the recipe title, or the instructions. Databases already provide a title field, and we'll also use the built-in content field for the recipe instructions.
    We'll see how to set up the custom fields, as well as how to customize their appearance.
     
    Ingredients field
    1. To create a new field, hover on the Pages tab in the AdminCP, and then click the Fields link under the Recipes database in the menu. The screen will show you the default built-in fields for your database, including Title and Content.
    2. Click the Create New button; you'll see a form where you configure your field.
    3. For Title, enter "Ingredients". This is the field title users will see when adding/viewing recipes on your site.
    4. For Description, enter "One per line". The description is only shown on the add/edit record form, so it's a good place to enter special instructions for filling it in.
    5. For the type, we'll choose Editor in this case, because it will allow the user to format the list if they wish. The other fields on the form will change depending on which field type you choose, since each has specific options.
    6. We don't require a maximum length, but we do want to require this field to be completed, so leave these settings at their default values.
    7. On the Display tab, we'll configure how the field content is shown to users. First, enter ingredients as the field key. This key is how IPS4 identifies this field in templates. We won't actually be using it in this tutorial, but it's good practice to set it anyway so you can use it later if needed.
    8. We don't want our list of ingredients to show on the listing screen, so disable that option.
    9. We do, however, want it to show on the record display screen, since this is the main screen for viewing a recipe. A badge isn't ideal for showing content from an Editor, so change the Display View Format to the simple Label: Value option as shown:

    10. We'll show the list of ingredients above the main record content, so make sure Above the item content is selected for the Display option.
    11. Finally, there's no need to allow this field to be updated when viewing a record; instead, users will go to the full edit form. You can leave the Editable when viewing a record option disabled.
    12. Save the form to create the field.
     
    Other fields
    Other fields are created in the same way, so instead of going through the whole process again, here's the configuration options you need for each field. Where a configuration option isn't listed, leave it at its default value.
    Note: Some field types, including the Select Box type that Cuisine uses (see below), support a fixed set of options from which the user can choose. You'll set these up as key/value pairs in the AdminCP, but the user will only see the values when they select them. The key is just used internally by IPS4 and in custom templates to identify the value, and is best kept as a single lowercase word.
     
    Prep time
    Name: Prep Time
    Type: Text
    Required: No
    Template key: prep-time
    Listing view format: Label: Value
    Display view format: Label: Value
     
    Cook time
    Name: Cook Time
    Type: Text
    Required: No
    Template key: cook-time
    Listing view format: Label: Value
    Display view format: Label: Value
     
    Cuisine
    Name: Cuisine
    Type: Select Box
    Content: (key/value)
    indian / Indian italian / Italian american / American mexican / Mexican Allow filtering: Yes
    Required: Yes
    Template key: cuisine
    Listing view format: Label: Value
    Show to right of listing area: Yes
    Display view format: Label: Value
    Display: Above the item content
     
    Video recipe
    Name: Video tutorial
    Type: YouTube Embed
    Required: No
    Template key: video-tutorial
    Show in listing template: No
    Show in display template: Yes
    In a record, display as: Embedded Player
     
    That's it! If you now head over to the front-end page for your database, click into a category, and click the Add New Recipe button, you'll see your fields on the form, ready to collect information! Feel free to add some sample records to try it out.
    You'll also see the Record Image field that the database provides automatically (discussed earlier). When you upload an image here, you'll see it is automatically included in the record view for you.
    Here's an example recipe in our database:


  17. Like
    Rikki got a reaction from Mike Henry Sr. for a guide, Creating a theme with the Easy Editor   
    For most admins, creating a theme with the Easy Editor is the best option. It allows you to customize the default theme in a point-and-click environment and see your changes in real-time, and requires no coding skills whatsoever.
     
    Creating the theme
    To create the theme we'll edit, navigate to Customization -> Themes in the AdminCP. Click the Add Theme button. In the popup window, ensure the Easy Mode option is selected (it's the default), and then click Next. 
    On the next screen, you can configure some choices about your new theme:
    Name (required)
    As it will appear to users of your site Parent
    You can make this theme a child of another, meaning it will automatically inherit any style/template changes from the parent theme Default theme
    Makes this theme the default for guests and members who have not specifically chosen another theme Available for
    Sets permissions for which groups can use this theme. Example use: a theme that only 'premium' users can access as an added benefit of paying Click Save once you have filled in the information. Your theme will be created and you'll be returned to the theme listing.
     
    Launching the Easy Mode editor
    From the theme listing in the AdminCP, you can click the magic wand icon on any Easy Mode theme to launch the visual editor (you will need to be logged into the front-end of your community to use the visual editor):

    Note: You can launch the visual editor at any time, even long after you've created the theme. However, if you convert an Easy Mode theme to a normal theme, you can't go back and use the visual editor.
    Launching the visual editor will take you to your community in editing mode (that only you can see). Your community will be shown on the left, with editing tools available in a panel on the right:

     
    The visual editor has a few key functions to help you design your theme. We'll cover each in turn.
     
    1. Colorize
    This tool lets you instantly change all of the theme colors to different shades of another color. Click the Colorize button, and you'll see four swatches:

    Clicking a swatch and choosing a new color will immediately update the live preview to show you the result.

    The colorize tool is great as a first step - if you know you want a red theme (for example), you can use it to get the basics done, and then fine-tune the resulting colors later using the other tools.
    If you don't like the result, you can click the Revert Colorizer button to undo your changes.
     
    2. Select tool
    The Select tool allows you to point-and-click at sections of pages on your community, and the visual editor will automatically show you the color editor for the closest available parts.

     
    3. Custom CSS
    If you are familiar with CSS, the Easy Mode editor gives you the ability to add custom CSS to your theme without needing to convert it to a full manual theme. Simply click the CSS button, and a code editor will be shown for you to use. And yes, you still get the live preview!
     
    4. Style editor
    The available styles you can edit are listed in the main panel. Click one to see the color swatches and to edit the colors. Some styles allow you to edit just the background, others will also allow you to edit the font color.

    Background colors can also be turned into gradients by clicking the    button. To use it, you choose a direction in which the gradient should go, and then add colors to form the gradient.

     
    5. Build
    The Build tab is where you'll go once you're happy with your changes and want to save them. Click the Save Theme button to do so. This will save your changes and make them live to any users who have chosen this theme.
     
     
  18. Like
    Rikki got a reaction from Meddysong for a guide, Translating using the visual language editor   
    Setting up the visual language editor
    The easiest way to get start with translating your language pack is to use the visual language editor.
    To enable visual editing, first ensure you are using the desired language. You can select a language to use in the footer of the front-end of your community.
    Next, navigate to Customization -> Languages, and click the Translation Tools button in the header. In the popup window, turn on the Quick Translating option, and save the form.

     
    Using the visual language editor
    With this option enabled, you can now edit phrases that you see in the interface, both in the AdminCP and on the front-end of your community. Phrases that can be translated are highlighted when you hover over them with your mouse cursor.
    To edit a phrase, click and hold for a couple of seconds. The phrase will change into a textbox that allows you to edit the characters.
    Type your new phrase, then click out of the box to save your new translation.
    Tip Using the visual language editor, you can even translate content sections of your site that you have created, such as forum names & descriptions, member group names, ranks and much more.

     
    That's all there is to it! You can make your way through your community translating phrases in this way.
    There will likely be many phrases you don't see in normal use in the interface and that therefore won't be translated with the visual language editor. For those, use the standard translating interface, which we'll cover in the next step.
     
    Turning off the visual editor
    The visual editor will remain active for your whole session. To turn it off, you can either restart your browser, or navigate back to Customization -> Languages in the AdminCP, click Translation Tools and turning off the Quick Translating option.
  19. Like
    Rikki got a reaction from sobrenome for a guide, ips.ui.dialog   
    Description
    The dialog widget displays popup windows within the page, typically loading content from a remote source.
     
    Usage
    A dialog is defined simply by including the widget key as an attribute on a trigger element. It is recommended that the trigger element be a link or button, so that if the user has javascript disabled their browser can take them to a full-page version of the dialog contents.
    <a href='...' data-ipsDialog data-ipsDialog-url='...'>Launch dialog</a> Dialogs offer special functionality for forms contained with the dialog, enabling them to be automatically validated and submitted via AJAX when used with the form helper from the IPS4 PHP framework. See the remoteVerify and remoteSubmit options below.
     
    Obtaining a dialog reference
    If you need to control a dialog programmatically, you can do so by first obtaining the reference to the dialog. To do so, call the getObj method, passing in the element on which the dialog was created as the parameter:
    // HTML <div id='elementWithDialog' data-ipsDialog> ... </div> // Javascript var dialog = ips.ui.dialog.getObj( $('#elementWithDialog') ); The returned reference to the dialog instance can be used to call the methods shown below.
     
    Creating a dialog programmatically
    Dialogs can be created programmatically by controllers instead of being created on particular elements. To achieve this, call the create method:
    var dialog = ips.ui.dialog.create( object options ); The options parameter should be an object containing keys for the options below.
    This method returns a reference to the dialog instance on which you can call methods to control the dialog, for example:
    dialog.show(); dialog.hide();  
    Instance methods
    show( boolean initOnly )
    Initializes and shows the dialog. If initOnly is true, the dialog is initialized but not immediately shown.
     
    hide()
    Hides the dialog.
     
    remove( boolean hideFirst )
    Removes the dialog from the DOM. If hideFirst is true, the dialog will call hide() and remove itself after the animation is completed.
     
    setLoading( boolean loading )
    If loading is true, indicates to the user that something is being loaded (i.e. shows a spinner in the dialog). If loading is false, removes the loading state. Note: this method doesn't empty the dialog content first. Call instance.updateContent('') manually if desired.
     
    updateContent( string newContent )
    Updates the contents of the dialog with the provided newContent. New controllers/widgets are automatically initialized after updating.
     
    Options
    url
    (String; optional)
    If provided, the dialog contents will be loaded by calling this URL when the dialog is launched.
     
    content
    (Selector; optional)
    If the dialog content already exists in the DOM, this option should be a selector that will locate the wrapper element for the content.
     
    modal
    (Boolean; optional; default true)
    If true, the page background will fade, preventing the user from interacting with it until the dialog is dismissed.
     
    title
    (String; optional)
    Sets the title shown in the dialog window. If not set, no title bar will display.
     
    size
    (String; optional)
    If provided, will set a special class on the dialog designed to change its size. Currently, narrow, medium, wide and fullscreen are supported as values for this option. If not provided, the default dialog width will be used (defined in CSS).
     
    close
    (Boolean; optional; default true)
    Determines whether the dialog should be built with a close button.
     
    fixed
    (Boolean; optional; default false)
    Determines whether the dialog is fixed. A fixed dialog is anchored to the viewport, not the page. Its height will also be fixed, with the content scrolling inside if necessary. If this is false, the dialog will scroll with the page, and it will expand to fit all the content being shown, regardless of length.
     
    remoteVerify
    (Boolean; optional; default true)
    When the dialog contains a form built using the IPS4 PHP framework form helper, this option instructs the dialog to automatically validate the form values and present any errors to the user.
     
    remoteSubmit
    (Boolean; optional; default false)
    When the dialog contains a form built using the IPS4 PHP framework form helper, this option instructs the dialog to submit the form values via AJAX. If remoteVerify is also true, two separate AJAX requests are fired; first, the form is validated, and if successful the form is submitted with a second request.
    If remoteSubmit is true, after a successful submit the dialog is closed automatically. If the flashMessage option is provided, it will be shown at this point.
    By default, remoteSubmit is false, which means forms submit via a traditional page reload.
     
    callback
    (Function; optional)
    Specifies a callback function that will be executed after the dialog has loaded remote content. Note: this option cannot be provided via the data API, and is therefore only available when interacting with ips.ui.dialog directly.
     
    forceReload
    (Boolean; optional; default false)
    By default, once a dialog has loaded its content, it will not do so again even if the dialog is relaunched. By setting this option to true, the dialog will call the url every time it is opened. This option only takes effect when the url option is used.
     
    Events emitted by ips.ui.dialog
    openDialog
    Triggered when the dialog is shown.
    Event data:
    elemID
    ID of the element that triggered the dialog dialogID
    ID of the dialog element dialog
    Reference to the dialog element contentLoaded
    Boolean indicating whether the dialog content has been loaded (may be false if remote content is used)  
    hideDialog
    Triggered when the dialog is hidden.
    Event data:
    elemID
    ID of the element that triggered the dialog dialogID
    ID of the dialog element dialog
    Reference to the dialog element  
    dialogContentLoaded
    Triggered after remote content has been loaded and inserted into the dialog.
    Event data:
    elemID
    ID of the element that triggered the dialog dialogID
    ID of the dialog element dialog
    Reference to the dialog element contentLoaded
    Boolean indicating whether the dialog content has been loaded (always true here)  
    Events to which ips.ui.dialog responds
    closeDialog
    Instructs the dialog to close.
    Event data:
    dialogID (required)
    The ID of the dialog to close (the event is ignored if the ID does not match the current dialog)
     
  20. Like
    Rikki got a reaction from lferezy4 for a guide, Buttons   
    Basics
    The button classes described here can be applied to any element, although typically would be applied to an element like a, input[type="submit"] or button so that the user can interact with it.
    As a minimum, a button should receive the basic ipsButton class, plus a size class and a style class (explained below).
     
    Button styles
    ipsButton_normal
    Normal button ipsButton_primary
    Primary button ipsButton_alternate
    Alternate button ipsButton_important
    Important button ipsButton_light
    Light button ipsButton_veryLight
    Very light button ipsButton_overlaid
    Overlaid button ipsButton_link
    Link button  
    Button sizes
    ipsButton_medium
    Medium button ipsButton_verySmall
    Very small button ipsButton_small
    Small button ipsButton_large
    Large button ipsButton_veryLarge
    Very large button ipsButton_fullWidth
    Can be combined with another size, above.
    Full width button  
    Disabled buttons
    Buttons can be visually disabled either by adding the class ipsButton_disabled, or, on relevant input elements, adding the disabled property. For example:
    <a href='#' class='ipsButton ipsButton_normal ipsButton_medium ipsButton_disabled'>Disabled button (link)</a> <input type='submit' class='ipsButton ipsButton_normal ipsButton_medium' disabled value='Disabled button (input)'> These would render like so:
    Disabled button (link)  
    Split buttons
    Split buttons allow you to create toolbars easily by specifying a list of buttons that display joined to each other.
    They are created by specifying the class ipsButton_split on a wrapper element containing two or more buttons. The wrapper element can be a <ul> tag, or any other that makes sense for your use.
    All of the buttons in a split button group should be the same size, otherwise results are unpredictable. Different styles can be used on each button, though.
    <ul class='ipsButton_split'> <li><a href='#' class='ipsButton ipsButton_small ipsButton_primary'>Button 1</a></li> <li><a href='#' class='ipsButton ipsButton_small ipsButton_light'>Button 2</a></li> <li><a href='#' class='ipsButton ipsButton_small ipsButton_light'>Button 3</a></li> </ul> Button 1 Button 2 Button 3  
  21. Like
    Rikki got a reaction from Ambiences for a guide, Using designer's mode   
    While the standard template editor is useful for light template editing, for larger, more complex changes, editing with a real IDE is desirable. The IPS Community Suite facilitates this through something called Designer's Mode.
     
    What is Designer's Mode?
    Designer's Mode allows you to use a real IDE by exporting all of the templates and CSS files to disk as files, and then reimporting them to the suite when you have finished editing them.
    With Designer's Mode enabled, the software will load its theme from this folder, meaning you can edit the files and see the changes as you make them.
    Warning Designer's Mode should not be used on a live community because it will have resource usage implications. We always recommend developing themes with Designer's Mode on a test/development installation.  
    Enabling Designer's Mode
    The first step is to create a folder called themes in your root community directory (that is, the same place your conf_global.php exists). CHMOD this folder to 777 to enable the suite to write the files.
    Next, navigate to Customization -> Themes in the AdminCP. In the toolbar at the top of the page, click the Designer's Mode button. Toggle the setting on after reading the information box, and then save the form. IPS4 will begin writing the theme files to disk.
    Once complete, you will see a directory structure similar to this in the /themes folder on your server:

    All themes currently installed are exported when Designer's Mode is enabled; the parent folders in this structure are named based on the theme ID. You can cross-reference the theme ID you wish to edit on the theme listing page in the AdminCP while Designer's Mode is enabled:

    Each theme folder contains four key parts:
    /css
    The CSS for the theme, grouped first by app, then by location (front/admin/global). /html
    The *.phtml HTML templates this theme uses, grouped first by app, then by location (front/admin/global) then by section. lang.php
    A language file into which you can insert any custom language strings your theme requires. They should be in this format: 'my_language_key' => "The English phrase"  
    /resources
    Resources for the theme (primarily images), grouped first by app, then by location (front/admin/global) then by type.
    Resources aren't allowed to be larger than 1.5 MB . 
     
    Editing templates
    When you edit the *.phtml template files exporting by Designer's Mode, you will notice a special tag on the first line of each file that looks like this:
    <ips:template parameters="$title,$html,$location=array()" /> This tag is how the software knows which variables belong to this template. It is very important that you do not modify this line in template files, or your theme may break.
     
    Completing Designer's Mode
    When you are happy with your changes, you can disable Designer's Mode to import them back into the suite (note that you can enable Designer's Mode again later to continue).
    To do this, go back to the theme listing screen at Customization -> Themes, and click the red Designer's Mode Enabled button. When you toggle the setting off, you will see additional settings asking you to confirm that you want to synchronize the changes.
    Warning Be sure the Synchronize option is enabled when you save this form, otherwise your changes will be lost.
    You can select individual themes to sync, or all of them. You can also choose whether to keep the files on disk or automatically delete them once the sync is done.
  22. Like
    Rikki got a reaction from sobrenome for a guide, Badges   
    Description
    Badges are a useful way of showing some additional information about an item - its status, for example.
     
    Standard badges
    Standard badges receive the base class ipsBadge, and then one or more of the options shown below.
     
    Badge styles
    ipsBadge_new
    Badge
    ipsBadge_style2
    Badge
    ipsBadge_warning
    Badge
    ipsBadge_positive
    Badge
    ipsBadge_negative
    Badge
    ipsBadge_neutral
    Badge
    ipsBadge_intermediary
    Badge
     
    Badge sizes
    ipsBadge_normal (default)
    Badge
    ipsBadge_medium
    Badge
    ipsBadge_large
    Badge
     
    Icon badges
    Any of the above classes can used to create icon badges by adding the additional ipsBadge_icon class, and using a FontAwesome icon as the badge content. For example:

     
    Status badges
    "Status badges" is the term we use to denote the icons shown in datalists, record tables etc. that indicate the read/unread status of the icon to the user. They are separate to the badges described above and don't use the same classes.
    The base class for status badges is ipsItemStatus, with additional options shown below.
    ipsItemStatus_tiny
    Shows a tiny status indicator. Include an icon (usually fa-circle) as the content of the element.
    ipsItemStatus_small
    Shows a small status indicator. Include an icon (usually fa-circle) as the content of the element.
    ipsItemStatus_large
    Shows a full status indicator. The indicator can be customized with an icon by including it as the content of the element:
    <span class='ipsItemStatus ipsItemStatus_large'> <i class='fa fa-comments'></i> </span>
    ipsItemStatus_read
    The 'read' status of the badge, causing it to fade out (a convention for read content in the IPS Community Suite).
     
  23. Like
    Rikki got a reaction from sobrenome for a guide, Messages   
    Description
    The messages module provides a way to style informational messages to bring something to the user's attention.
     
    Usage
    To create a message, simply add the ipsMessage class to a container element (e.g. div), along with one of the message styles below. The message style class will automatically add the appropriate icon to your message box.
     
    Message styles
    Error - ipsMessage_error
    This is an error message. Success - ipsMessage_success
    This message indicates something happened successfully. Warning - ipsMessage_warning
    This message warns the user of something terrible (or not so terrible). Information - ipsMessage_info
    This message provides general information.  
    Message codes
    If you need to add a code to your message, such as an error number, you can do so using the ipsMessage_code class:
    <div class='ipsMessage ipsMessage_error'> <span class='ipsMessage_code'>12345</span> This is an error message. </div> 12345 This is an error message.  
  24. Like
    Rikki got a reaction from sobrenome for a guide, Dropdown Menus   
    Description
    Dropdown menus allow users to select from a number of options. The markup is designed to work in tandem with the ips.ui.menu javascript module.
     
    Usage
    A menu consists of a trigger element, and the menu element itself:
    <!-- The trigger --> <a href='#elMyMenu_menu' id='elMyMenu'>Open Menu</a> <!-- The menu --> <ul id='elMyMenu_menu' class='ipsMenu'> ... </ul> The ID of the menu should be the ID of the trigger element, suffixed by _menu. If the trigger element is a link, its href should be an anchor to the ID of the menu element. This makes the menu accessible even when Javascript is disabled in the browser.
     
    Basic menu
    A basic menu might have the following markup:
    <ul class='ipsMenu ipsHide'> <li class='ipsMenu_item'><a href='#'>Item 1</a></li> <li class='ipsMenu_item'><a href='#'>Item 2</a></li> <li class='ipsMenu_item'><a href='#'>Item 3</a></li> <li class='ipsMenu_sep'><hr></li> <li class='ipsMenu_item'><a href='#'>Item 4</a></li> <li class='ipsMenu_item'><a href='#'>Item 5</a></li> </ul> This would display as follows: see example.
    Item 1 Item 2 Item 3 Item 4 Item 5 ipsMenu is the base class for the menu element. Items within the menu should have the class ipsMenu_item, with the link element inside of that. A separator item can be added by giving the item the class ipsMenu_sep, containing an <hr> element.
    Note that the positioning and stem is added automatically by the menu javascript module; it does not need to be manually specified. The stem can be removed, if necessary, by including the class ipsMenu_noStem on the menu element.
     
    Disabling menu items
    Individual menu items can be disabled by adding the class ipsMenu_itemDisabled to the list item: see example.
    Item 1 Disabled Item 2 Item 3 Note: Disabled items are not foolproof; in browsers that do not support the CSS pointer-events style, a click on a disabled item will still register. Ensure your javascript properly deals with disabled item clicks if necessary.
     
    Menu sizing
    By default, a menu will have no defined width. An additional classname can be specified on the menu element to determine how wide it should display.
    ipsMenu_auto - menu will appear as wide as necessary, though with a minimum width of 200px and a maximum width of 500px ipsMenu_narrow - 200 pixels wide ipsMenu_normal - 300 pixels wide ipsMenu_wide - 450 pixels wide  
    Selectable menus
    A selectable menu allows the user to toggle one or more of the menu items, useful for turning options on and off. For this functionality to work, the javascript module needs to be used.
    A menu can be made selectable by adding the classname ipsMenu_selectable. A menu item can be shown as selected by adding the classname ipsMenu_itemChecked to the list item.
    The markup for a selectable menu might look this:
    <ul id='elMenu2_menu' class='ipsMenu ipsMenu_normal ipsMenu_selectable ipsHide'> <li class='ipsMenu_item'><a href='#'>Item 1</a></li> <li class='ipsMenu_item ipsMenu_itemChecked'><a href='#'>Item 2</a></li> <li class='ipsMenu_item'><a href='#'>Item 3</a></li> </ul> This would display as follows: see example.
    Item 1 Item 2 Item 3  
    Sub-menus
    Submenus can be created by embedding menus within one another. To do so, simply include the ipsMenu_subItems class on the item that contains the submenu, and the submenu itself within the item. For example:
    <ul id='elMenu3_menu' class='ipsMenu ipsMenu_normal ipsHide'> <li class='ipsMenu_item'> <a href='#'>Item 1 (no children)</a> </li> <li class='ipsMenu_item ipsMenu_subItems'> <a href='#'>Item 2 (with children)</a> <ul class='ipsMenu ipsMenu_wide ipsHide'> <li class='ipsMenu_item'><a href='#'>Sub Item 1</a></li> <li class='ipsMenu_item'><a href='#'>Sub Item 2</a></li> <li class='ipsMenu_item'><a href='#'>Sub Item 3</a></li> </ul> </li> </ul> This would display as follows: see example.
    Item 1 (no children) Item 2 (with children) Sub Item 1 Sub Item 2 Sub Item 3  
  25. Like
    Rikki got a reaction from sobrenome for a guide, Icons   
    Description
    We make use of an icon font called FontAwesome. This enables us to display icons that are accessible, that don't require an additional HTTP request, that can be styled with CSS (and inherit styling automatically), and which scale without loss of quality.
     
    Usage
    An icon can be included within the markup by using the following code:
    <i class='fa fa-iconname'></i> The list of possible icons and their classnames is available at http://fontawesome.io/icons/. Note that these classnames are not prefixed with ips as with other framework classes; they are left with their default names as they appear on the FontAwesome website.
    Icons can be used anywhere that HTML can be used. For example, within text, on buttons, in menus and more.
        Icon on a button    A caret icon indicates a dropdown     Yes, I think so   No, I disagree   This is another caret  
    Icon consistency
    It is important that icon use remains relatively consistent throughout the suite. This applies to core developers as well as addon developers. If different icons are used for the same purpose (or worse, an icon is used for a purpose different to it's usual purpose), users will become confused by the software.
    To help alleviate this, we have a list of icons that we generally refer to when choosing an icon to represent an action. Check this list to see if your action already has an associated icon, and lean towards using that instead of choosing another.
    The list below organizes actions, with the title being a general concept. The icon names are FontAwesome icons, without the preceding fa-
     
    Adding
      plus-circle   plus Deleting
      times-circle   trash-o Editing
      pencil Reverting
      undo Go Somewhere
      arrow-right Open External Link
      external-link Confirming Yes/No
      check   times Permissions
      lock   unlock Log In/Sign In
      key Copy
      copy Settings
      cog Flagging On/Off
      flag   flag-o Star On/Off
      star   star-o Developer/Application
      cogs Help
      question-circle Merge
      level-up Code/PHP/HTML
      code Mail/Send Mail
      envelope-o Search
      search View
      search Refresh/Reload
      refresh Execute/Run Now
      play-circle Easy Mode/Visual Editor
      magic  
×
×
  • Create New...

Important Information

We use technologies, such as cookies, to customise content and advertising, to provide social media features and to analyse traffic to the site. We also share information about your use of our site with our trusted social media, advertising and analytics partners. See more about cookies and our Privacy Policy