kongondo

FieldtypeVariations: Upcoming Pro Module for Product Variations & Attributes

4 posts in this topic

Introducing Variations, an Input- and Fieldtype for product variations and their attributes.

Product variations is a topic that has been coming up now and then, especially in the recent past.  This module seeks to fill this gap. Though it's in its early stages of development, it is already functional and can be used as is. I decided to make an early announcement (modules development forum) in order to get early feedback from potential users. 

The module is an alternative take on how variations can be built for a product. Imagine the ubiquitous T-Shirt. The product could vary by ...Size, Colour, Material, etc...These variations could in turn have internal variations, i.e. attributes....so, Size [Small, Large], Colour [Red, Blue]...etc; you get the drift.

The usual approaches to building variations have been either to use Multiple pages, Repeaters, Page Table, Table or Matrix (limited to 1x1 variations). In this module, we do it a bit differently.

First, the variations occur not at the Field level (meaning all product pages would have the same variations and attributes for each template) but at the page level. Secondly, there are no multiple pages for each variation and/or attributes; a product is a single page. The variations and their attributes are defined by site editors at the page level. Once a variations configuration has been defined, it is applied to the page and all possible combinations are generated (i.e. the Red,Small,Cotton; Red,Large,Cotton, etc) in the Inputfield. There is no limit to the number of variations and attributes that can be defined, although you will be amazed at how quickly the combinations grow! Prices are entered for each combination when editing the page. Combinations without prices are not saved to the database. Please note that prices cannot themselves vary at the page-level. Meaning, you cannot have ONE variation configuration that has different price inputs per product in the same FieldtypeVariations field.

The module ships with an API for outputting variation combinations in the frontend. Search, database and in-memory work as normal in the frontend. In the backend, DataTables provides a nice paginated, filterable table. Prices can be entered on any pages (of the table) without loss of data (meaning you can enter prices on page 1, scroll to page 10, enter more prices, filter or search the products table, enter more prices and finally save; no data will be lost).

I still have a couple of ideas and plans pending but would love to hear from you, thanks.

Below is a short video demo of the module in its current state. Things may/will change, both UI and features. Btw, the Fieldtype, although primarily targeted at commerce applications, is by no means limited to this. Other uses requiring combinations of whatever number of variables are very much within the remit of the module.

Planned/Hoped for features

  1. Import/Export product variations and attributes (Excel, etc)
  2. Full integration with Padloper (I will have to  discuss with @apeisa)
  3. SKU fields for each product variation
  4. Add/Remove extra subfields, e.g. multi-currency prices (currently there is only 1 input for each product variations' price)
  5. Product variation images?
  6. Etc...

Please not this module is not related to this other planned module (but it may eventually).

Sneak Peek Demo

 

 

Edited by kongondo
6 people like this

Share this post


Link to post
Share on other sites

Sounds very interesting!

47 minutes ago, kongondo said:

Combinations without prices are not saved to the database.

47 minutes ago, kongondo said:

Btw, the Fieldtype, although primarily targeted at commerce applications, is by no means limited to this.

Does this mean the "Price" field is only an example, and in non-commerce situations you could add some other type of field to store data related to the variation? Will you be able to add multiple data fields to the variations?

1 person likes this

Share this post


Link to post
Share on other sites
27 minutes ago, Robin S said:

Does this mean the "Price" field is only an example, and in non-commerce situations you could add some other type of field to store data related to the variation?

Yes, e commerce being the most likely use for this module.

Just to be clear for the sake of others, technically, these are subfields. E.g., price is a subfield (meaning a database column in a FieldtypeVariations field [technically a database Table] which you access as $variationsfield.price, similar to $page->image.description).

Back to your question, this is a planned feature (although code is already in place). Please note that, in respect of these subfields, there are no plans to include anything as near exhaustive as what Table does. Meaning, these will likely be limited to TEXT, INT, FLOAT, etc fields, but not complicated Fieldtypes such as Page fields, Repeaters, etc. 

 

27 minutes ago, Robin S said:

Will you be able to add multiple data fields to the variations?

Yes, as many or as little as you want, pre or post-field use. For instance, start with price (default but in future versions one will be able to remove the subfield), then later or at field configuration add an SKU subfield, a discount subfield, some text subfield, etc. 

Edited by kongondo
3 people like this

Share this post


Link to post
Share on other sites

I am thinking of changing the way variations +  attributes are created and applied. Currently, these have to be typed whenever one needs them. For different products that share an attribute (e.g. 'Red') but not necessarily a variation configuration, all that typing is repetitive. For instance, the colour Red means the same thing irrespective of whether it is a Car or a T-Shirt or a Phone. If you have all these products for sale, you should be able to just select colour from some list you previously typed and be presented with all colours from which you can select which apply to your product. Meaning, at the product/page configuration level, you will first have to select the variations you want, e.g. Size, Colour, Material, etc....then select the respective values/attributes, e.g. Yellow, etc. Small, etc.

1 person likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By cosmicsafari
      Hi All,
      Fairly new to ProcessWire so apologies if this is a daft question, but I am having a go creating my first module. I have set it up and enabled it as per the docs.
      However I have created another class within the same module directory, which was going to be used in the main module file but I can't get it to work for the life of me and I believe its due to me not fully understanding the namespace side of things.
      Example:
      MyModule.module.php
      <?php namespace ProcessWire; class MyModule extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Test Module', 'version' => 1, 'summary' => 'Test module', 'href' => '', 'singular' => true, 'autoload' => true, 'icon' => 'exchange', ); } public function newMethod( $testMessage ) { $foo = new Foo($testMessage); $foo->getFoo(); } } Foo.php
      <?php namespace ProcessWire; class Foo { protected $foo; public function __construct($foo) { $this->foo = $foo; } public function getFoo() { return $this->foo; } } Now as I understand it both these files should exist under the ProcessWire namespace, so in theory I should be able to use Foo within MyModule without any use statements as they both exist at the same level within the ProcessWire namespace?
      However when I try something like so:
      $myModule = $modules->getModule('MyModule'); $myModule->myMethod('Foo'); I would have thought this should return 'Foo', however I keep running into errors like:
      Any help would be appreciated.
    • By Max Allan Niklasson
      Hi, I think this is my first topic, even though I've been working with PW a few years. But now, I'm trying to restructure my way of coding, cause many templates (like activities for birding societies) are re appearing in multiple different websites. Since this, I've been working on redo this into a module, but as far as I have read I cannot store the templates (related to specific module) in the module's folder. It has to be in the templates folder?
       
    • By kongondo
      Menu Builder
       
      Modules Directory
      Project Page
      Read Me (How to install, use, etc..)

      If you want a navigation that mirrors your ProcessWire page tree, the system allows you to easily create recursive menus using either vanilla PHP or Soma's great MarkupSimpleNavigation. In some cases, however, you may wish to create menus that:
      1. Do not mirror you site's page tree (hirarchies and ancestry); and
      2. You can add custom links (external to your site) to.

      That is primarily where Menu Builder comes in. It is also helpful if you:
      3. Prefer creating menus via drag and drop
      4. Have a need for menus (or other listings) that will be changing regularly or that you want to allow your admin users to edit.

      The issue of custom menus is not new here in the forums. The difference is that this module allows you to easily create such menus via drag and drop in the Admin. Actually, you can even use it to just create some list if you wanted to. In the backend, the module uses the jQueryUI plugin nestedSortable by Manuele J Sarfatti for the drag and drop and is inspired in part by the WP Custom Menu feature.
       
      Please read the Read Me completely before using this module. 
      For Complex or highly-customised menus, it is recommended to use the getMenuItems() method as detailed in this post.
       
      Features
      Ability to create menus that do not mirror your ProcessWire Page Tree hierarchy/structure Menus can contain both ProcessWire pages and custom links Create menu hierarchies and nesting via drag and drop Easily add CSS IDs and Classes to each menu item on creating the menu items (both custom and from ProcessWire pages) or post creation. Optionally set custom links to open in a new tab Change menu item titles built from ProcessWire pages (without affecting the original page). E.g. if you have a page titled 'About Us' but you want the menu item title to be 'About' Readily view the structure and settings for each menu item Menus stored as pages (note: just the menu, not the items!) Menu items stored as JSON in a field in the menu pages (empty values not stored) Add menu items from ProcessWire pages using page fields (option to choose between PageAutocomplete and AsmSelect [default]) or a Selector (e.g. template=basic-page, limit=20, sort=title). For page fields, you can specify a selector to return only those specified pages for selection in the page field (i.e. asm and autocomplete) For superusers, optionally allow markup in your menu titles, e.g. <span>About</span> Menu settings for nestedSortable - e.g. maxLevels (limit nesting levels) Advanced features (e.g. add pages via selector, menu settings) currently permissible to superadmins only (may change to be permission-based) Delete single or all menu items without deleting the menu itself Lock down menus for editing Highly configurable MarkupMenuBuilder - e.g. can pass menu id, title, name or array to render(); Passing an array means you can conditionally manipulate it before rendering, e.g. make certain menu branches visible only to certain users [the code is up to you!]  Optionally grab menu items only (as a Menu object WireArray or a normal array) and use your own code to create custom highly complex menus to meet any need. More... In the backend, ProcessMenuBuilder does the menu creation. For the frontend, menus are displayed using MarkupMenuBuilder.

      Credits

      In this module's infancy (way back!), I wanted to know more about ProcessWire modules as well as improve my PHP skills. As they say, what better way to learn than to actually create something? So, I developed this module (instead of writing PW tutorials as promised, tsk, tsk, naughty, naughty!) in my own summer of code . Props to Wanze, Soma, Pete, Antti and Ryan whose modules I studied (read copied ) to help in my module development and to Teppo for his wonderful write-up on the "Anatomy of fields in ProcessWire" that vastly improved my knowledge and understanding of how PW works. Diogo and marcus for idea about using pages (rather than a custom db table), onjegolders for his helpful UI comments, Martijn Geerts, OrganizedFellow, dazzyweb and Mike Anthony for 'pushing me' to complete this module and netcarver for help with the code.
       
      Screens

    • By bernhard
      hi everybody,
      this is a preview of a module that i'm working on for quite a long time. I needed it for an intranet office management application that i'm still working on. It makes it very easy to create very customized Datatables using the awesome jquery datatables plugin (www.datatables.net)
       
      EARLY ALPHA release!
      It's very likely that there will lots of changes to this module that may cause breaking your implementations.
       
      Module source
      https://gitlab.com/baumrock/RockDataTables2/tree/master
      Screencast:

       
      Remarks:
      The module is intended to be used on the backend. Loading styles is at the moment only done via adding files to the $config->styles/scripts arrays. Also the communicaton to javascript is done via the $config->js() method that is built into the admin and would have to be implemented manually on frontend use. But it would not be difficult of course
       
      Installation:
      Nothing special here, just download + install
       
      Example setup of the most minimal Table:
      you always need 2 files to create a table:
      php file to define the columns and related data (page selector) js file to control the client-side actions like rendering, sorting, etc PHP
      // init datatables module $dt2 = $modules->get('RockDataTables2'); // setup columns // name $col = new dtCol(); $col->name = 'name'; $col->title = 'Name'; $col->data = function($page) { return $page->title; }; $dt2->cols->add($col); // setup table $dt2->id = 'dt_kundenliste'; // give your table an id $dt2->js('/site/modules/ProcessRockProjects/dt_kundenliste.js'); // tell it where to find the related javascript // ################################## // ajax request -> return data // non-ajax -> render table // ################################## if($config->ajax) { // here you can setup your page selector // this will for sure change in the future to support filtering etc echo $dt2->getJSON($pages->find('template=rockcontact, sort=random, limit=10000')); die(); } else return $dt2->render(); JS
      $(document).ready(function() { // setup variables var opt = ProcessWire.config.dt_kundenliste; // options from backend var colDefs = []; // column definitions // custom column definitions here (see https://datatables.net/reference/option/columnDefs for all options) // load default column definitions colDefs = colDefs.concat(dtGetDefaultDefs(opt)); // initialise table $('#dt_kundenliste').DataTable({ ajax: './kundenliste/', columnDefs: colDefs, }); }); that's it - as easy as that!

       
      Customization example:
      in the screencast you see an example that i'm using in a process module. i put the table inside an InputfieldMarkup just to have the same look&feel all around the admin. you see that you could also use this module to create tables quickly and easily using @kongondo s runtime markup module.
      complete PHP code:
      $this->headline('Kundenliste'); $form = $modules->get('InputfieldForm'); // init datatables module $dt2 = $modules->get('RockDataTables2'); // setup columns // name $col = new dtCol(); $col->name = 'name'; $col->title = 'Name'; $col->data = function($page) { return $page->title; }; $dt2->cols->add($col); // type $col = new dtCol(); $col->name = 'type'; $col->data = function($page) { return $page->rockcontact_type->title; }; $dt2->cols->add($col); // modified $col = new dtCol(); $col->name = 'modified'; $col->data = function($page) { $obj = new stdClass(); $obj->timestamp = $page->modified; $obj->display = date('d.m.Y', $page->modified); return $obj; }; $dt2->cols->add($col); // setup table $dt2->id = 'dt_kundenliste'; $dt2->js('/site/modules/ProcessRockProjects/dt_kundenliste.js'); $f = $modules->get('InputfieldMarkup'); $f->value = $dt2->render(); $form->add($f); // ################################## // ajax request -> return data // non-ajax -> render form + table // ################################## if($config->ajax) { echo $dt2->getJSON($pages->find('template=rockcontact, sort=random, limit=10000')); die(); } else $out .= $form->render(); return $out; what is interesting here is this part:
      // modified $col = new dtCol(); $col->name = 'modified'; $col->data = function($page) { $obj = new stdClass(); $obj->timestamp = $page->modified; $obj->display = date('d.m.Y', $page->modified); return $obj; }; $dt2->cols->add($col); datatables support orthogonal data (https://datatables.net/extensions/buttons/examples/html5/outputFormat-orthogonal.html). a date column is a good example, because you need to DISPLAY a formatted date (like 10.02.2017) but you need to be able to SORT this column by a different value (timestamp). its very easy to accomplish this by providing both values in your json. Btw: You could also just transfer the timestamp and do the formatting on the client-side via javascript. Next Example will show ho this would work. Both cases can be necessary, it's just an example here.
      back to topic: now we have both data available and need to tell the table wich data to use for which action. it's easy, just add the definition to the array:
      // modified date colDefs.push({ targets: opt.colnames.indexOf('modified'), render: { _: 'display', sort: 'timestamp', }, }); this tells the datatable to use the display-value for displaying (and filtering) and the timestamp-value for sorting. see https://datatables.net/reference/option/columns.render
      you can also easily modify a simple non-orthogonal data via a render function:
      // name colDefs.push({ targets: opt.colnames.indexOf('name'), render: function ( data, type, full, meta ) { return '<span class="blurry" title="'+data+'">'+data+'</span>'; }, }); this adds the span with "blurry" class to every cell of type "name". i did this to blur all the client data in my screencast
      the complete javascript:
      $(document).ready(function() { // setup variables var opt = ProcessWire.config.dt_kundenliste; // options from backend var colDefs = []; // column definitions // custom column definitions here // see https://datatables.net/reference/option/columnDefs for all options // name colDefs.push({ targets: opt.colnames.indexOf('name'), render: function ( data, type, full, meta ) { return '<span class="blurry" title="'+data+'">'+data+'</span>'; }, }); // typ colDefs.push({ targets: opt.colnames.indexOf('type'), render: function ( data, type, full, meta ) { return '<a href="#" style="white-space: nowrap;">'+data+'</a>'; }, }); // modified date colDefs.push({ targets: opt.colnames.indexOf('modified'), render: { _: 'display', sort: 'timestamp', }, }); // load default column definitions colDefs = colDefs.concat(dtGetDefaultDefs(opt)); // initialise table $('#dt_kundenliste').DataTable({ ajax: './kundenliste/', columnDefs: colDefs, scrollY: "400px", scrollCollapse: true, scrollX: "100%", pageLength: 10, }); }); you can also have scrollbars just by adding options to your datatable. also fixed columns are possible. just see the docs on datatables.net

      Why i created this module:
      of course i know @Soma s module but i needed a lot more features and the newer datatables version. also i like to define all the columns as objects and have everything on one place. lister & markupadmindatatable: nice for basic tables but lacks of features to modify the appearance of the cell values (like rendering icons, background colors and so on) datatables provides a great frontend API for filtering, showing/hiding columns, getting data, modifying it... it also plays well together with frontend charts like google chart api in this case:
       
      todo / roadmap:
      all kinds of column filters (like seen in the example above that shows an older and bloated version of this module) support for ajax filters and pagination (currently all filtering and sorting is done on the client side. i tried it with up to 50.000 rows and got reasonable results. initial loading took around 10sec. but of course this heavily depends on the complexity of your table and your data.
    • By Macrura
      Soundmanager2 Audio for Processwire
      Github:
      https://github.com/outflux3/TextformatterSoundmanager
      Modules Directory:
      http://modules.processwire.com/modules/textformatter-soundmanager/
      This module provides most of the free audio player interfaces for Soundmanager2 by Scott Schiller:
      Bar UI 360 UI 360+ spectrum UI mp3 buttons mp3 links Page Player, muxtape-style UI Cassette Player The module is a Textformatter that works by allowing you to insert shortcodes which are parsed into audio players.
      The players may be placed anywhere in the content (ck editor or other text field) using the shortcode, for example:
      [smplayer tag=audio1]
      The output will be a default single player (as specificed in the module settings), or if multiple audio files have the same tag, and you don't specify a type (UI), it will default to the Bar UI for the playlist. You may also specify page-player for the type as it also supports playlists.
      Here is a more complex tag:
      [smplayer tag=audio1 type=bar-ui color=2288CC]
      the tags available on shortcodes are:
      tag - *required to find the audio file on the page type (the type of player) limit (limit the number of files to load when using a playlist) Player specific tags for Bar UI:
      bar-ui (options for the bar-ui player) skin (applies to a bar-ui skin to load) extra (when set to true, it will display the extra controls) color (hex value for color - applies to bar-ui and mp3 buttons) compact (makes the player very narrow) playlist-open (make the playlist drawer open instead of needing to click the playlist button to open it.) dark-text (instead of white) flat (remove the faux 3d effect) When using the shortcode, you can chain the tags using underscore, for exmaple:
      [smplayer type=bar-ui bar-ui=flat_playlist-open_dark_text]
      Player specific tags for Cassette:
      cassette (options for the cassette player) In case you are not familiar with SM2, it powers a lot of major audio on the web, like Soundcloud, LastFM, AllMusic etc). The players are all rock solid and work on a wide range of browsers and devices.
      Features
      Multiple Audio Formats
      SM2 supports many formats, and those can be enabled/disabled in the module config if you want to prevent any from being loaded. So far this module was tested with MP3 and AAC (.m4a).
      GetID3 Support
      When enabled, ID3 tags from every audio file that pass through the Textformatter are read and cached as arrays using WireCache. Therefore the first load of a page with new audio files may be slow while the tags are read and stored. The tags are indexed by the filename of the audio, so as long as you don't upload multiple files with the same filename, or change the tags, the system will store the metadata permanently. To remove any metadata, you would need to use Soma's Cache Admin module, or clear it from the database.
      Schema Support
      When enabled, some schema tags relating to audio files will be added to the markup.
      CK editor Plugin
      Very basic dropdown that inserts some pre-configured player codes into the editor. Copy the plugin into your CK editor plugins folder, enable and add a button for 'soundmanager'.

      Instructions
      Before you install:
      1) You will need a files field that accepts audio files, so set the extensions you want to use, such as mp3, m4a, mp4, wav etc. 2) Also make sure that you enable tags on the files field because the module references the tags for any audio file in the shortcode. 3) Add the files field to your template.
      Installation and Setup
      1) Install the module and adjust your settings from the module configuration screen.
      2) Add the TextformatterSoundmanager textformatter to the field where you want to insert audio (e.g. 'body').
      3) Optionally install the CK editor plugin to enable quick access to preconfigured shortcodes.
      4) Add a shortcode into the textarea field that has the textformatter applied to.
      5) You must reference the tag you entered in the audio file's tag field in the shortcode, and that will create a player for that audio file.
      5a) To create a playlist, put the same tag in multiple audio files.
      Output
      1) In order for the module to output the necessary styles and scripts, you need to echo the $config->styles and $config->scripts arrays into your site's header/footer. Here is an example:
      // In Header foreach($config->styles as $style) echo "<link rel='stylesheet' type='text/css' href='{$style}' />\n"; // In Footer foreach($config->scripts as $script) echo "<script type='text/javascript' src='{$script}'></script>\n";  
      API Usage
      To access the module's player method directly, you would first init the module in your _init.php file:
      $sm2 = $modules->get('TextformatterSoundmanager'); then anywhere in your templates, you can output any audio file with any player, in an configuration like this:
      $options = [ 'type' => 'bar-ui', 'skin' => 'gradient-fat', //'tag' => 'audio1', // tag is not needed when using the API //'bar-ui' => 'playlist-open' //all of the classes to apply to the bar ui. ]; foreach($page->audio as $track) { $content .= $sm2->player($track, $options); } Advanced Features
      Using other pages for storing music as playlists. You can create a field to hold a tag for a **page* and then refer to that tag in your shortcode. The shortcode word would be smplaylist instead of smplayer. The module will search the site for pages with that tag in that field. Then it will output all of the audio files in that page's audio field using the player and settings you specify. See the module configuration to select the tag field and adjust your shortcode words. Caveats
      Some player will not work well on the same page as other players.
      Bar UI and Page Player 360 Player and 360 Visual (large) players Also note that the cassette player can only occur once on a page. You can have multiple cassettes output, but they will all play the same audio file. The file that the cassette player uses is set in the script tag. In the future the setup may be modified to allow for cassette players to have their own audio files.
      About Soundmanager2
      http://www.schillmania.com/projects/soundmanager2/
      Speak and be heard
      More sound, in more places
      Despite being one of the senses, sound has largely been missing from the web due to inconsistent technology support. SoundManager 2 bridges this gap, making it easier to use audio across a growing variety of devices and platforms, both desktop and mobile.
      HTML5 + flash hybrid
      Complexity, reduced
      Supporting HTML5 audio can be tedious in modern browsers, let alone legacy ones. With real-world visitors using browsers ranging from mobile Safari to IE 6 across a wide range of devices, there can be many support cases to consider.
      SoundManager 2 gives you a single, powerful API that supports both new and old, using HTML5 audio where supported and optional Flash-based fallback where needed. Ideally when using SoundManager 2, audio "just works."
      The ginsu knife: 12 KB
      Big features, small footprint
      Performance is an important metric, too. SoundManager 2 packs a comprehensive, feature-rich API into as little as 12 KB over the wire when optimized; that's less than 8% of the original, uncompressed file size.
      SM2 is self-contained, having no external dependencies, and is compatible with popular JavaScript frameworks.
      The source code is BSD-licensed and is provided in fully-commented, non-debug and compiler-optimized "minified" versions appropriate for development and production use.