Skip to content

Instantly share code, notes, and snippets.

@Kjaer
Created November 13, 2017 07:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kjaer/d14813e02e245a40392f795433a944df to your computer and use it in GitHub Desktop.
Save Kjaer/d14813e02e245a40392f795433a944df to your computer and use it in GitHub Desktop.
knockout String Template solution.

knockout.js stringTemplateEngine solution

What I did accomplish this task is, enhance string template engine so it could be use any other requirements. For that case, I was using string template engine to create video tag html.

Before continue, I was already referring to the existing stringTemplateEngine used by only a extension called modal I was doing a refactoring to re-using engine other extensions too.

stringTemplateEngine provides me seperate some logic should be stay inside a specific code part. I might go for knockout component too, but that challenge attracts me more and see the advantages of using stringTemplateEngine provides me write more component-ish binding extension.

<!-- plyr binding usage -->
<div class="video-player-container" data-bind="plyr:{videos:playerData.videos,cover:playerData.cover, instance:playerData.instance}"></div>
//...
playerData: {
cover: "http://images.host.com/assets/campaign_videos/video_cover.jpg?v=0.2",
videos: [
{ path: "http://images.host.com/assets/campaign_videos/campaign_video.mp4?v=0.2", mimeType: "video/mp4" },
{ path: "http://images.host.com/assets/campaign_videos/campaign_video.ogv?v=0.2", mimeType: "video/ogv" },
{ path: "http://images.host.com/assets/campaign_videos/campaign_video.webm?v=0.2", mimeType: "video/webm" }
],
instance: {} //instance will be set after video player instantiation
},
//...
efine(['knockout', 'plyr', 'stringTemplateEngine'], function (ko, plyr) {
//This bindings needs a cover photo
//This bindings needs a list of video source
// - List of videos must be an object including mime type and video source e.g. {source:'vid_source.mp4', mime-type:'video/mp4'}
//This bindings needs a container element.
//USAGE
/*
<div class="video-container" data-bind="plyr:{videos:[videos],cover:[cover_photo_path]"></div>
*/
ko.videoPlayers = [];
ko.templates.videoPlayer = '<video data-bind="attr:{poster:cover}" id="video-player" controls crossorigin>' +
'<!-- ko foreach:videos -->' +
'<source data-bind="attr:{src:path, type:mimeType}" src="" type="">' +
'<a data-bind="attr:{href:path}" download>Videoyu Indir.</a>' +
'<!-- /ko -->' +
'</video>';
ko.bindingHandlers.plyr = {
instances: [],
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var model = valueAccessor();
ko.renderTemplate("videoPlayer", bindingContext.createChildContext(model), { templateEngine: ko.marketplaceEngine }, element, "replaceChildren");
var id = ko.utils.uniqueId('mp-videoplayer-');
element.setAttribute("id", id);
var instance = plyr.setup(element);
ko.videoPlayers.push({ id: id, instance: instance[0] });
//let knockout know that we'll manually bind the child HTML of our element
return { controlsDescendantBindings: true };
}
};
});
//Enhanced version string template from https://github.com/faulknercs/Knockstrap/blob/master/src/templates/templatesWrapper.js
define(['knockout'], function (ko) {
//string template engine
//define a template source that tries to key into an object to find a template string
var data = {},
engine;
ko.templates = {};
ko.templateSources.stringTemplate = function (template) {
this.templateName = template;
};
ko.utils.extend(ko.templateSources.stringTemplate.prototype, {
data: function (key, value) {
data[this.templateName] = data[this.templateName] || {};
if (arguments.length === 1) {
return data[this.templateName][key];
}
data[this.templateName][key] = value;
},
text: function (value) {
if (arguments.length === 0) {
return ko.templates[this.templateName];
}
ko.templates[this.templateName] = value;
}
});
engine = function () {
this.allowTemplateRewriting = false;
};
engine.prototype = ko.nativeTemplateEngine.prototype;
engine.prototype.constructor = engine;
engine.prototype.makeTemplateSource = function (template, doc) {
var elem;
if (typeof template === "string") {
elem = (doc || document).getElementById(template);
if (elem) {
return new ko.templateSources.domElement(elem);
}
return new ko.templateSources.stringTemplate(template);
} else if (template && (template.nodeType === 1) || (template.nodeType === 8)) {
return new ko.templateSources.anonymousTemplate(template);
}
};
engine.prototype.getTemplate = function (name) {
return ko.templates[name];
};
engine.prototype.addTemplate = function (name, template) {
if (arguments.length < 2) {
throw new Error('template is not provided');
}
ko.templates[name] = template;
};
engine.prototype.removeTemplate = function (name) {
if (!name) {
throw new Error('template name is not provided');
}
delete ko.templates[name];
};
engine.prototype.isTemplateExist = function (name) {
return !!ko.templates[name];
};
ko.marketplaceEngine = new engine();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment