jQuery UI Operator Overloading? - javascript

I'm attempting to figure out OOP Javascript, jQuery, and jQuery UI all at the same time. Basically, I want to create a custom "panel" component that I can reuse in various places throughout my web app. The panel consists of a title bar and then content below it.
So I'm using jQuery UI to accomplish this. I want to be able to make the component and then change its attributes (like the title bar text). Here's an example:
$(function()
{
$.widget("custom.ShinyPanel",
{
options: {
css:{},
title:""
},
_create:function()
{
$(this.element).addClass("shinyPanel").disableSelection();
this.titleBar = $(createElement("div")).addClass("shinyPanelTitleBar").appendTo(this.element);
this.topShine = $(createElement("div")).addClass("shinyPanelTopShine").appendTo(this.element);
this.leftShine = $(createElement("div")).addClass("shinyPanelLeftShine").appendTo(this.element);
this.content = $(createElement("div")).addClass("shinyPanelContent").appendTo(this.element);
this._refresh();
},
_refresh:function()
{
if (this.options.hasOwnProperty("title"))
$(this.titleBar).html(this.options.title);
}
});
});
// $("#divShotList").ShinyPanel({title:"Shot List"}); // this works
$("#divShotList").ShinyPanel();
$("#divShotList").title = "Shot List"; // this doesn't work
<div id="divShotList" style="position:absolute; top:5px; bottom:10px; width:250px;"></div>
Is there a way for me to overload the = operator or something to make this work with this syntax? I know that I could probably create an extra function, like setProperty or something, but it would be really cool if I could just keep this syntax and get it to work. Any idea how I can modify the widget to make this happen?

The element or jQuery wrapped element is not your widget:
$("#divShotList").data('ShinyPanel')._setOption('title', 'something');
But it is store in the .data() of the element.
Alternatively:
var shinyPanel = $("#divShotList").ShinyPanel().data('ShinyPanel');
shinyPanel.options.title = 'new title';
shinyPanel.refresh();
would also work.
Final Edit: To answer you question: No.

Related

Programmatically insert variables into Meteor Templates with Blaze.render + Blaze.view or Blaze.with

I'm trying to figure out how to programmatically insert a variable helper into a template using the Blaze API. I believe it needs to be done using some form of:
Blaze.render(Blaze.with('variable', contentFunction);
However, I'm struggling to get the contentFunction to work properly. I tried a function that returns a Session variable:
var session_var = function() {
return Session.get('myVariable');
};
However, I keep getting undefined errors. I know this could be done if I defined a separate template to be rendered, but that seems a bit much for this particular case. I was wondering if someone could explain how Blaze.with and Blaze.view work. Also, is it possible to programmatically insert just a variable helper into a template?
Without knowing exactly what you're trying to do, it's not clear if this is the easiest way of going about things.
However, if you look at the docs, you'll see that you can either supply the session variable in a data context and use Blaze.With, or supply no data context and use Blaze.View instead (which appears to be what you're going for).
So, if you want to render a reactive data context, it has to be supplied in the first argument to Blaze.With. Try something like this:
var myView = Blaze.With(
function() {
return {
foo: Session.get('foo')
};
},
function() {
return Spacebars.mustache([
'the value of foo is ',
this.lookup('foo')
]);
}
);
Blaze.render(myView, document.body); // or whatever element you want to render it inside
Alternatively, for Blaze.View:
var myView = Blaze.View(
function() {
return 'the value of foo is ' + Session.get('foo');
}
);
Blaze.render(myView, document.body);
To be honest, the easiest way to learn about the structure of renderable content (which is the difficult bit if you're doing this programmatically) is to study the stuff that the Spacebars compiler churns out. In other words, find an interesting template/sub-template that's been generated from quasi-HTML, pick an element out of it and run Blaze.getView([ELEMENT])._render, then study the result.

Best way to represent HTML part when writing a complex jQuery plugin

I have a complex jQuery plugin to write, It does have a lot of html to show on screen and I am supposed to create them. Well, what is the best way to do the job. I can already hard code them for sure , but is there any other elegant method? is there a way to use some kind of templating?. definitely I don't want to have lot more dependency either.
You can put them in an external file(s) and load them when you need but this means plugin users will have to download all your files, instead of a single js file. Another option I used before (not for a plugin though) is to have an object inside your plugin which holds all the html you want. This makes it easier to write the plugin as the html doesn't clutter the plugin code. Also when you need to edit the html, it's in a single place. You can also put your templating code inside this object.
var pi = function() {
var self = this;
self.getNewDiv = function(){
return repo.getDiv();
}
//..... all your plug in code goes here and at the bottom
var htmlRepository = function() {
var divCode = "<div></div>";
this.getDiv = function(){
return divCode;
};
this.getSpan = function(){
return "Span Content";
}
this.getDivWithSpan = function(){
return getSpan().wrap(divCode); //etc
}
};
var repo = new htmlRepository();
}

How to extend native DOM elements using "is"?

I am trying to using the custom elements spec to extend native DOM elements using the "is" attribute, but it doesn't seem to be doing anything at all. I am using Google Canary so I am able to create custom elements, but no effect in extending.
In my sample, I am trying to add a caption to the native img tag:
<img is="super-img" src="http://lorempixel.com/400/200/"
caption="This is my custom caption!" />
<script>
document.registerElement('super-img', {
prototype: Object.create(HTMLImageElement.prototype, {
createdCallback: function() {
var caption = this.attributes.getNamedItem('caption').value;
alert(caption);
}
})
});
</script>
http://jsbin.com/OMaPIVoV/3/
The createdCallback never fires. Any ideas on how to accomplish this?
Object.create(HTMLImageElement.prototype, {
createdCallback: function() {…}
})
Object.create does create a map of property descriptors as its second parameter - not plain values - like Object.defineProperties does.
This is also mentioned in the article you found at "Adding JS properties and methods":
Of course there are umpteen thousand ways to construct a prototype. If
you're not a fan of creating prototypes like this, here's a more
condensed version of the same thing:
[…] [This] first format allows for the use of ES5 Object.defineProperty.
The second allows the use of get/set.
(The strike-through was added by me as it's rubbish)
So what you want is either
var SuperImgProto = Object.create(HTMLImageElement.prototype);
SuperImgProto.createdCallback = function() { … };
var SuperImg = document.registerElement('super-img', {prototype: SuperImgProto});
or
document.registerElement('super-img', {
prototype: Object.create(HTMLImageElement.prototype, {
createdCallback: {value: function() { … } }
})
});
looks like you forgot to tell your web component, that it extends the native img element. Here's a running example based on your fiddle but broken down to the important bits: http://jsbin.com/OMaPIVoV/7/edit
hope this helps!

How to create a well formed global javascript object containing special functions

I am creating a small project that heavily relies on JavaScript. I come from php/mysql and now stepping into node.js/javascript/mongodb, and I hve to say it's quite a mindswitch.
I want to create a simple object that has some special function that I can use in the page. I have been looking at some tutorial, and looking at the libraries such as jquery and backbone, but I need some final advice on my decision.
I only need some small functions, and no cross-browser support, that's why I don't choose something like backbone. Maybe ill change to that later when I have a better crasp on JavaScript programming.
What is confusing me is whether to use the new, or maybe wrapping the code into a self-invoking function.
I see jquery creates an object inside the window and than exposes that, but I have no idea how that works.
Enough intro, now to the point. I have created something like this:
var $s = Object.create({
page: Object.create({
title: 'pagetitle',
html: '',
data: {},
render: function(){
// Basic render function
}
}),
socket: Object.create({
// My websocket connection
}),
store: function(key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
retrieve: function(key) {
var value = localStorage.getItem(key);
return value && JSON.parse(value);
},
slugify: function(slug){
return slug.replace(/[^a-zA-Z 0-9-]+/g,'').toLowerCase().replace(/ /g,'-');
}
});
This are just a few random functions I put in.
I haven't tested this yet, it is a draft, I want to know if this is any good.
Now I was thinking i can do some stuff like this:
$s.page.html = 'somehtml';
$s.page.render();
// Maybe
$s.store( $s.page.title, $s.page.html );
I do use jQuery and jQuery templating, so something like this could be possible:
$.tmpl( $s.page.html, $s.page.data ).appendTo( "#content" );
Nothing fancy is needed here. You can create a global javascript object with a method like this:
var myGlobalObject = {};
myGlobalObject.testFunction = function() {
// put your code here
};
You can then call that like this:
myGlobalObject.testFunction();
One slightly more flexible design pattern you will often seen used is this:
var myGlobalObject = myGlobalObject || {};
myGlobalObject.testFunction = function() {
// put your code here
};
This is used when there might be lots of different pieces of code contributing to myGlobalObject and they all want to make sure that it's properly declared before adding properties to it. This way of doing it, creates it if it doesn't already exist and if it does already exist, leaves the methods and properties on it that might already be there. This allows multiple modules to each contribute initialization to myGlobalObject without regards for the order they load.

Dojo widget defaults

i'm currently writing a large scale application heavily based on the dojo toolkit. The whole app is working and standing, but one issue i can not find my way out with, is the creation of custom widgets. It would be useful because it would clean up my source code and also i can reuse this 'widgets' in later projects.
For example: i have a main toolbar, which i would like to call using
myapp.toolbar = new myapp.mainToolbar();
instead of using
myapp.toolbar = new new dijit.Toolbar({}, containerID);
var button1 = new dijit.form.Button({
label: 'Delete',
id: 'toolbarbutton1',
showLabel: true,
iconClass: "dijitEditorIcon dijitEditorIcon Delete"
});
myapp.toolbar.addChild(button1);
...
So in short: how do i set up the whole toolbar somewhere else and call it as a simple object? Trying to figure out dojo.declare('myapp.mainToolbar', dijit.Toolbar, {...}) but then i get a bunch of errors like 'startup function not existing' etc...
I'd like to do all this programmatically, so without the template html and css files in a custom widget.
A link to a good tutorial or howto would be nice, although google nor yahoo! will reveal any extra's on this matter for me... :)
There are multiple ways to do this.
It seems like your method of extending Toolbar should work (not sure why it didn't).
You can also declare a class that embeds Toolbar and the buttons, using widgetsInTemplate:
dojo.declare("MyToolbar", [dijit._Widget, dijit._Templated], {
_widgetsInTemplate: true,
templateString: '<div> <div dojoType=dijit.Toolbar>' +
' <button dojoType=dijit.form.Button ...
Note that the top node in MyToolbar can't have a dojoType, so I put Toolbar one level down.
Alternately you can do the same thing by using dijit.Declaration, see http://docs.dojocampus.org/dijit/Declaration.
It works for me when I use declare with the superclass inside of an array:
dojo.declare('myapp.mainToolbar', [ dijit.Toolbar ],
{
....
}
);
var x = new myapp.mainToolbar({ ... });
x.startup();
Which kind of violates the docs. It should take one Function or an array of Functions.

Categories

Resources