Removing sharedaddy’s (jetbacks sharing) extra og:description without hacking php

I’ve come across a problem where multiple plugins insert facebook opengraph meta tags into the header of my posts without letting me turn that behavior on or off. They all assume that no one explicitly puts open graph tags in their blog. This includes sharedaddy (jetpack sharing). It does so with the following comment:

	public function display_header() {
		if ( $this->share_type == 'share' ) {
			// Set the open graph description, otherwise Facebook may pick up some random text from the page
			global $post;
			
			if ( $post && $post->ID > 0 )
				echo '<meta property="og:description" content="'.esc_attr( apply_filters( 'sharing_post_title', $post->post_title, $post->ID, $this->id ) ).'" />';
		}
	}

Source in wordpress trak.

Problem is I’d rather define my og tags or rely on a plugin focused on doing this well.

There are several plugins to do open graph tag insertion that do a better job. You may want to roll your own directly into your theme or using one of the general SEO plugins.

So, I want to remove these extraneous tags. Online tips suggest I go into each plugin and comment out the php code inserting these tags. That’s a direct option but I hate modifying plugins. I don’t want to maintain these hacks through updates.

So, I solved with javascript. The approach is a hack. It requires that sharedaddy and other plugins insert their og:description tags before the tags I want to preserve and that I start my desired facebook tags with an fb:admins tag.

function removeExtraOpenGraphMetaTags()
{
	//assumes extra og tags occur before an fb:admins
	var first_og_tag = jQuery("meta[property]").first();
        //if the first meta tag with a property attribute is fb:admins - do nothing
	if (jQuery("meta[property]").first().attr('property') != 'fb:admins') 
	{
		//remove all subsequent og tags until fb:admins
		var removed_tags = first_og_tag.nextUntil("meta[property='fb:admins']", "meta[property*='og:']").remove();
		if (removed_tags) { first_og_tag.remove(); }
	}
}

Making a layered brightcove player using the player api and beml



My goal was to build a Brightcove player that the layers the videoplayer and playlist in the same space with a way of toggling from the one to the other. I wanted to create minimal code external to the player and I didn’t want to do any custom Flash development.

Brightcove Experience Markup Language (BEML)

Brightcove offers their customers the ability to customize players via an XML extension called BEML which has a complete, if terse, DTDDoc.

I started with the BEML for a standard player template Video with Dropdown.

It contains the video player and the playlist layout I want to use. I basically want to stack the one on top of the other.

I duplicated it, renamed it and then edited the BEML.

BEML layout is pretty straightforward. It reminded me of java AWT. Components are laid out in canvasses with either vertical (VBox) or horizontal (HBox) arrangements.

<Runtime>
<Theme name=”Deluxe” style=”Light”/>
<Layout id=”application” boxType=”vbox”>
<VideoPlayer id=”videoPlayer” height=”275″ video=”{videoList.selectedItem}”/>
<Spacer height=”3″/>
<ComboBox id=”playlistCombo” height=”25″/>
<List id=”videoList” rowHeight=”75″ automaticAdvance=”true” data=”{playlistCombo.selectedItem.videoDTOs}” itemLeading=”2″ selectOnClick=”true”>
<ListItem boxType=”hbox”>
<Spacer width=”8″/>
<VBox width=”80″ height=”74″ vAlign=”middle”>
<ThumbnailButton height=”60″ data=”{currentItem}” source=”{currentItem.thumbnailURL}”/>
</VBox>
<Spacer width=”7″/>
<VBox>
<Spacer height=”3″/>
<TitleLabel height=”18″ text=”{currentItem.displayName}” truncate=”true”/>
<Label height=”52″ multiline=”true” text=”{currentItem.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”3″/>
</ListItem>
</List>
</Layout>
</Runtime>

And there is an element called ViewStack which takes any child components and layers them one on top of the other.

So, the first change was to place the UI within a ViewStack and then make sure the children of that ViewStack are the layers I want (if I didn’t wrap the components correctly the playlist combobox would be one layer and the playlist another).

<Runtime>
<Theme name=”Deluxe” style=”Light”/>
<Layout id=”application” boxType=”vbox”>
<ViewStack id=”viewStack” selectedIndex=”0″>
<VBox>
<VideoPlayer id=”videoPlayer” height=”275″ video=”{videoList.selectedItem}”/>
<Spacer height=”3″/>
</VBox>
<VBox>
<ComboBox id=”playlistCombo” height=”25″/>
<List id=”videoList” rowHeight=”75″ automaticAdvance=”true” data=”{playlistCombo.selectedItem.videoDTOs}” itemLeading=”2″ selectOnClick=”true”>
<ListItem boxType=”hbox”>
<Spacer width=”8″/>
<VBox width=”80″ height=”74″ vAlign=”middle”>
<ThumbnailButton height=”60″ data=”{currentItem}” source=”{currentItem.thumbnailURL}”/>
</VBox>
<Spacer width=”7″/>
<VBox>
<Spacer height=”3″/>
<TitleLabel height=”18″ text=”{currentItem.displayName}” truncate=”true”/>
<Label height=”52″ multiline=”true” text=”{currentItem.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”3″/>
</ListItem>
</List>
</VBox>
</ViewStack>
</Layout>
</Runtime>

Next, I need a component that lets me toggle back and forth from the player to the playlist and back. I chose to use a simple link. I placed it directly below the ViewStack.

<VBox width=”100%” hAlign=”right” height=”24″>
<Spacer height=”3″/>
<Link id=”moreOrLessLink” text=”Show more video…”/>
</VBox>

Next, I added some text below the videoplayer for the title and short description of the video currently loaded into the player.

<HBox>
<Spacer width=”6″/>
<VBox>
<TitleLabel id=”maintitle” height=”18″ text=”{videoPlayer.video.displayName}” truncate=”true”/>
<Label multiline=”true” height=”54″ text=”{videoPlayer.video.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”6″/>
</HBox>

Finally, some inline CSS as allowed within the BEML dtd in order to have the text fit in the TitleLabel I just added and here’s the complete BEML for the revised player:

<Runtime>
<Theme name=”Flat” style=”Light”/>
</Style>
<Style id=”maintitle”><![CDATA[ .titleText
{
font-size:16;
font-weight:bold;
}
]]></Style>
<Layout id=”application” boxType=”vbox”>
<ViewStack id=”viewStack” selectedIndex=”0″>
<VBox>
<VideoPlayer id=”videoPlayer” height=”275″ video=”{videoList.selectedItem}”/>
<Spacer height=”3″/>
<HBox>
<Spacer width=”6″/>
<VBox>
<TitleLabel id=”maintitle” height=”18″ text=”{videoPlayer.video.displayName}” truncate=”true”/>
<Label multiline=”true” height=”54″ text=”{videoPlayer.video.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”6″/>
</HBox>
</VBox>
<VBox>
<ComboBox id=”playlistCombo” height=”25″/>
<List id=”videoList” rowHeight=”75″ automaticAdvance=”true” data=”{playlistCombo.selectedItem.videoDTOs}” itemLeading=”2″ selectOnClick=”true”>
<ListItem boxType=”hbox”>
<Spacer width=”8″/>
<VBox width=”80″ height=”74″ vAlign=”middle”>
<ThumbnailButton height=”60″ data=”{currentItem}” source=”{currentItem.thumbnailURL}”/>
</VBox>
<Spacer width=”7″/>
<VBox>
<Spacer height=”3″/>
<TitleLabel height=”18″ text=”{currentItem.displayName}” truncate=”true”/>
<Label height=”52″ multiline=”true” text=”{currentItem.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”3″/>
</ListItem>
</List>
</VBox>
</ViewStack>
<VBox width=”100%” hAlign=”right” height=”24″>
<Spacer height=”3″/>
<Link id=”moreOrLessLink” text=”Show more video…”/>
</VBox>
</Layout>
</Runtime>

I did the rest of the color customizations in the publishing tools in Brightcove Studio.

This only addresses the UI of the player. I now need to wire up events.

Brightcove Player API for Javascript

Now I need to enable toggling between the player and playlist when someone clicks on the link. Brightcove doesn’t enable this within BEML itself. You need to interact with the player externally using the Player API.

The first step is to make sure your player is enabled for the Javascript/Actionscript API. This is a checkbox on the Global Tab of the player settings. It is by default unchecked.

Now, you need to load the Brightcove Javascript library. I loaded the combined js file as described in the Brightcove help page.

Brightcove supplies an API document.

When a Brightcove player loads in a page, it calls an onTemplateLoaded method that you can place in the page to gain access to Brightcove’s objects and interact with the player. There are examples of this on a dozen sites.

function onTemplateLoaded(experienceID) { /*insert code here*/ }

For encapsulation, I’ll create my own Javascript object. Construct it in this method passing the experienceID.

function onTemplateLoaded(experienceID) { new SnsCompactListVideoPlayer(experienceID); }

In the constructor, I obtain a reference to the Brightcove module object, lookup the link element by its ID then add an event listener for click events.

function SnsCompactListVideoPlayer(experienceID)
{
var playerExperience = brightcove.getExperience(experienceID);
var experienceModule = playerExperience.getModule(APIModules.EXPERIENCE);

this.moreOrLessLink = experienceModule.getElementByID(“moreOrLessLink”); //the link that toggles between the videoplayer and the playlist
this.viewStack = experienceModule.getElementByID(“viewStack”);//the ui element that contains the videoplayer in one stack and the playlist in another
this.videoPlayer = experienceModule.getElementByID(“videoPlayer”);//the video player ui element
this.videoList = experienceModule.getElementByID(“videoList”);
if (this.moreOrLessLink != null && this.viewStack != null && this.videoPlayer != null)
{
//toggle between videoplayer and playlist based on clicks
this.moreOrLessLink.addEventListener(“elementClick”, bindMethodToObject(this.togglePlayer,this));
//when a video plays make sure the videoplayer element is visible
this.videoPlayer.addEventListener(BCMediaEvent.PLAY, bindMethodToObject(this.togglePlayerToPlay, this));
}
}

I had to bind the click event to the instance of the video player — otherwise when the event fires, the this keyword references the calling page not the player instance. I did this using the apply method.

function bindMethodToObject(method, object)
{
return function() { return method.apply(object, arguments); }
}

In the event handler, I check which layer of the ViewStack is topmost (selectedIndex) and switch to the other one making sure to pause the video if it is currently playing whenever someone clicks to view the playlist.

SnsCompactListVideoPlayer.prototype.togglePlayer = function(e)
{
if (this.viewStack.getSelectedIndex() == 0)
{
this.viewStack.setSelectedIndex(1);
this.moreOrLessLink.setText(“Return to player…”);
if (this.videoPlayer.isPlaying())
{
this.videoPlayer.pause();
}
}
else
{
this.viewStack.setSelectedIndex(0);
this.moreOrLessLink.setText(“Show more video…”);
}
}

I also wired an event to the video player to make sure that whenever the player plays, it becomes the selectedIndex in the ViewStack. This handles whens someone clicks on a video in the playlist.

/*
* Simon & Schuster Compact List Video Player
* Script by Ken Judy
* May 1, 2011
*/

function SnsCompactListVideoPlayer(experienceID)
{
var playerExperience = brightcove.getExperience(experienceID);
var experienceModule = playerExperience.getModule(APIModules.EXPERIENCE);

this.moreOrLessLink = experienceModule.getElementByID(“moreOrLessLink”); //the link that toggles between the videoplayer and the playlist
this.viewStack = experienceModule.getElementByID(“viewStack”);//the ui element that contains the videoplayer in one stack and the playlist in another
this.videoPlayer = experienceModule.getElementByID(“videoPlayer”);//the video player ui element
this.videoList = experienceModule.getElementByID(“videoList”);
if (this.moreOrLessLink != null && this.viewStack != null && this.videoPlayer != null)
{
//toggle between videoplayer and playlist based on clicks
this.moreOrLessLink.addEventListener(“elementClick”, bindMethodToObject(this.togglePlayer,this));
//when a video plays make sure the videoplayer element is visible
this.videoPlayer.addEventListener(BCMediaEvent.PLAY, bindMethodToObject(this.togglePlayerToPlay, this));
}
}

function bindMethodToObject(method, object)
{
return function() { return method.apply(object, arguments); }
}

SnsCompactListVideoPlayer.prototype.togglePlayer = function(e)
{
if (this.viewStack.getSelectedIndex() == 0)
{
this.viewStack.setSelectedIndex(1);
this.moreOrLessLink.setText(“Return to player…”);
if (this.videoPlayer.isPlaying())
{
this.videoPlayer.pause();
}
}
else
{
this.viewStack.setSelectedIndex(0);
this.moreOrLessLink.setText(“Show more video…”);
}
}
SnsCompactListVideoPlayer.prototype.togglePlayerToPlay = function(e)
{
if (this.viewStack.getSelectedIndex() == 1)
{
this.viewStack.setSelectedIndex(0);
this.moreOrLessLink.setText(“Show more video…”);
}
}

Creating a Safari link button to favorite a site with StumbleUpon WebToolbar

Safari user, sometime StumbleUpon user. Don’t like having to remember to use Firefox to favorite a site in StumbleUpon. StumbleUpon has a WebToolbar but for some reason does not provide instructions for setting up a Bookmarks Bar button to it ala Delicious.

In Safari make a new bookmark in your Bookmarks Bar called “StumbleUpon” with the following address:

javascript:(function(){location.href='http://www.stumbleupon.com/toolbar/#url=' + encodeURIComponent(window.location.href);})()

It opens the page you are currently on within the StumbleUpon web toolbar so you can thumbs up or thumbs down it.