In your Intro to 7.x-2.x video, Travist, you held out hope that you would put out a video about creating OSM Player templates. I could use one of those right now, or at least some guidance on using MF field types.

First, the default player has an info field that doesn't seem to get populated. If I'm not mistaken, this would show up as a tooltip. There doesn't seem to be a field type for info, only Title, Image, Media, or Custom.

Second, I'm not sure how to use Custom. I thought perhaps all I needed to do was add a DIV with an appropriate class:

      <div class="osmplayer-' + template + '-teaser-description"></div>\

and extend the player elements:

      ...
      description:jQuery('.osmplayer-' + template + '-teaser-description', this.display)
      ...

but there appears to be more to it, since the DIV doesn't get populated.

Comments

travist’s picture

So, I just pushed up some changes to the 2.x branch where I upgraded the SimpleBlack template as another template. You can certainly use that as a stepping stone until I have a chance to get that video recorded.

travist’s picture

Title: Using MediaFront Field Types » Need help creating custom templates
Status: Active » Fixed

You can do the following to at least get you started...

  • Create a custom module to house your templates. There is a lot of documentation on how to do this elsewhere.
  • Create a folder in your module called templates and copy the simpleblack template folder from the latest 2.x branch into this folder.
  • Do a mass rename of everything 'simpleblack' in that folder (including filenames) to whatever you want to call your template.
  • Implement the following hook in your module...
    /**
     * Implementation of hook_osmplayer_info
     */
    function mymodule_osmplayer_info() {
      return array(
        'templates' => osmplayer_get_templates(drupal_get_path('module', 'mymodule') . '/templates')
      );
    }
    
  • You can then modify the *.tpl.php file within that template to make changes... the CSS file is in the CSS folder....

This should hopefully get you started until I make a video of it.

Thanks,

Travis.

mrtoner’s picture

I've actually done a fair job of modifying the default template already; starting with the simpleblack template means not having a playlist. (And it doesn't seems the simpleblack player is working, but perhaps more on that later.) However, neither default nor simpleblack deal with custom fields and I'm wondering how I get those (and the info field type) to display? I'll still need to know how to do that if I move my template into a module.

mrtoner’s picture

Title: Need help creating custom templates » Custom MediaFront field types not working
Category: support » bug
Status: Fixed » Active

I'm going to escalate this to a bug report, since the problem that I've had with using a custom MediaFront field type has been caused by OSM Player's failure to use anything from the node except for the title and image (well, and the media).

Here's the relevant section of code from osmplayer.js:

/**
 * Sets the node.
 *
 * @param {object} node The node object to set.
 */
osmplayer.teaser.prototype.setNode = function(node) {

  // Add this to the node info for this teaser.
  this.node = node;

  // Set the title of the teaser.
  if (this.elements.title) {
    this.elements.title.text(node.title);
  }

  // Load the thumbnail image if it exists.
  if (node.mediafiles && node.mediafiles.image) {
    var image = osmplayer.getImage(node.mediafiles.image, 'thumbnail');
    if (image) {
      if (this.elements.image) {
        this.preview = new minplayer.image(this.elements.image);
        this.preview.load(image);
      }
    }
  }

...

Specifically, I'm trying to add the node body to the (player's) teaser. I've added (as I described above) a DIV for the body/description and I've assigned the body to the DIV. Still, nothing appears in the DIV until I add this to osmplayer.js (actually, to osmplayer.compressed.js):

this.elements.body.text(a.body.value);

AFAIK, the node variable ('a') isn't available to the template scripts, so the assignment of node values to the player elements needs to happen in osmplayer.js.

In addition, osmplayer.module never populates the player options ($player_params) with a value for the info field type and osmplayer.js never assigns it to an element, so a tooltip is never displayed for a playlist item.

jaymallison’s picture

This is an issue for me as well. Modifying the default player template under my own module and trying to add the body field as a custom field. Noticed it's not working as you'd expect.

jaymallison’s picture

Once again, this isn't a bug, it's a feature. It's just undocumented (at least seemingly so).

All of the methods in the osmplayer.js can be overridden within the template by adding the [template] call next to the object name.

So for this particular issue, we just copy the entire setNode method into osmplayer.teaser.themename.js file and name it this

osmplayer.teaser[template].prototype.setNode = function(node) {

We then add in our code that sets the custom value we want.

------

I added a plain text description field through fields ui and set it as a Media Front "description" field in the view.

Then as described in the OP, I added a div for it under osmplayer.teaser[template].prototype.getDisplay and an element under osmplayer.teaser[template].prototype.getElements in my osmplayer.teaser.themename.js file.

I then added the following method code from osmplayer.js to my osmplayer.teaser.themename.js file below the construct method:

  /**
   * Sets the node.
   *
   * @param {object} node The node object to set.
   */
  osmplayer.teaser[template].prototype.setNode = function(node) {
  
    // Add this to the node info for this teaser.
    this.node = node;
    
    // Set the title of the teaser.
    if (this.elements.title) {
      this.elements.title.text(node.title);
    }
    
    if (this.elements.description) {
      this.elements.description.text(node.description.value);
    }
  
    // Load the thumbnail image if it exists.
    if (node.mediafiles && node.mediafiles.image) {
      var image = osmplayer.getImage(node.mediafiles.image, 'thumbnail');
      if (image) {
        if (this.elements.image) {
          this.preview = new minplayer.image(this.elements.image);
          this.preview.load(image);
        }
      }
    }
  
    // Bind when they click on this teaser.
    this.display.unbind('click').click((function(teaser) {
      return function(event) {
        event.preventDefault();
        teaser.trigger('nodeLoad', teaser.node);
      };
    })(this));
  };

Works beautifully. I'm a happy camper now. I finally have the baseline for my player working the way I want it. Thanks for this awesome module! Hope this helps someone.

mrtoner’s picture

Ah, a script override! Who knew? That does indeed solve that problem; I never would have guessed.

Travis, if you'd like you can change this back to support and close it, but there is still one niggling thing (unless I'm again wrong): the default template still expects an info element, but that's never provided to the template.

jaymallison’s picture

The info element is just the parent of the title element. Look at the code inside this.context.append. You'll see this line: <div class="osmplayer-' + template + '-teaser-info ui-state-default">\

That element is defined so it can be targeted by the teaser selection method through this.elements.info.addClass. I actually changed that line to this.elements.image.addClass so I can target the image instead for a dynamic "playing" overlay.

mrtoner’s picture

Okay, got that. But what is this line doing?

      info: jQuery('.osmplayer-' + template + '-teaser-info', this.display),

Isn't that supposed to populate that DIV with something? (I guess I'm misreading it as a tooltip when the user mouses over; it only seems to have something to do with the slider.)

travist’s picture

@jaymallison,

Thank you SO much for your effort. For the most part, you are absolutely right with your approach.... there were just a few things that I would recommend changing.

Just so that everyone knows, I started up a MediaFront documentation page here on Drupal.org so that the mediafront.org site isn't the only place to find documentation. Here is the link http://drupal.org/node/1563486. This is a wiki page so everyone can edit it. The first page I am doing is on creating templates found here http://drupal.org/node/1563496 where I do go into some detail that will help. Please edit as you see fit.

Thanks,

Travis.

jaymallison’s picture

@mrtoner

That line is extending the teaser object with a new property based on the target inside the jQuery call... i.e. the info div. This allows the stock functionality to then target the info div in the method that controls which teaser node is active.

@travist

Glad I could help. This is quite the massive project in regards to JS. So much to digest and reverse engineer. I see what you put in the docs and it makes perfect sense. Hard to guess these things without some context. Glad we are making headway on exposing just how powerful this system is. I have to say, the more I work with it, the more I realize how awesome it is!

travist’s picture

I also want to make a modification to your code above... It should derive from the base class and then just extend the custom functionality like this...

/**
 * Sets the node.
 *
 * @param {object} node The node object to set.
 */
osmplayer.teaser[template].prototype.setNode = function(node) {

  // Call the base class first.
  osmplayer.teaser.prototype.setNode.call(this, node);

  // Set the description.
  if (this.elements.description) {
    this.elements.description.text(node.description.value);
  }
};

You will also need to add description to your getElements method in your template as well....

  // Return the elements
  osmplayer.teaser[template].prototype.getElements = function() {
    var elements = osmplayer.teaser.prototype.getElements.call(this);
    return jQuery.extend(elements, {
      info: jQuery('.osmplayer-' + template + '-teaser-info', this.display),
      title:jQuery('.osmplayer-' + template + '-teaser-title', this.display),
      description: jQuery('.osmplayer-' + template + '-teaser-description', this.display),
      image:jQuery('.osmplayer-' + template + '-teaser-image', this.display)
    });
  };

And then, of course add that element to the tpl.php file where you want it to live.

Hope this helps.

Travis.

travist’s picture

Category: bug » support
Status: Active » Fixed
jaymallison’s picture

Yeah my OO experience with JS has been limited as of late and I'm a bit rusty haha.

I agree that approach is preferred, you're calling the base class to essentially "construct" it, and after it's been constructed, then extending it. I'll adjust my code to use that approach as it is obviously preferred. That way if you make a change to the base class in the future to add some functionality project wide, my code isn't bypassing it.

Also your addition to the getElements code is word for word exactly what I had already done. ;-)

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

aniebel’s picture

Thanks for this... very helpful! Can I ask if "description" you refer to in the .js is the machine name of the field?