Skip to content

Instantly share code, notes, and snippets.

@josephj
Last active December 11, 2015 22:28
Show Gist options
  • Save josephj/4669759 to your computer and use it in GitHub Desktop.
Save josephj/4669759 to your computer and use it in GitHub Desktop.
Using native JavaScript to create an OO-style step control.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="">
<meta name="created" content="2013-01-28">
<title> Prototype</title>
<link rel="stylesheet" href="http://yui.yahooapis.com/3.7.2/build/cssreset/reset-min.css">
<link rel="stylesheet" href="http://yui.yahooapis.com/3.7.2/build/cssfonts/fonts-min.css">
<style type="text/css">
.iframe-popup iframe {
position: absolute;
top: -1000em;
left: -1000em;
}
.iframe-popup iframe.active {
position: static;
}
.iframe-popup-last #next-link,
.iframe-popup-first #prev-link {
display: none
}
</style>
<script src="iframe-step.js"></script>
</head>
<body>
<script>
new IframePopup({
width: 500,
offset: 3,
urls: [
"http://lab.josephj.com/2013/iframe-popup/content.php?step=1",
"http://lab.josephj.com/2013/iframe-popup/content.php?step=2",
"http://lab.josephj.com/2013/iframe-popup/content.php?step=3",
"http://lab.josephj.com/2013/iframe-popup/content.php?step=4",
"http://lab.josephj.com/2013/iframe-popup/content.php?step=5",
"http://lab.josephj.com/2013/iframe-popup/content.php?step=6"
]
}).render();
</script>
</body>
</html>
/*global window, document */
(function () {
var _log = function (msg) {
if (typeof console !== "undefined") {
console.log(msg);
}
};
// Constructor
function IframePopup(config) {
var that = this,
i,
j;
// Provide the default attribute values.
that.offset = parseInt(config.offset, 10) || 0;
that.width = parseInt(config.width, 10) || 500;
that.height = parseInt(config.height, 10) || 500;
that.urls = config.urls || null;
// The urls attribute is required.
if (!that.urls) {
_log("The urls attribute is required.", "error");
return;
}
// Private variables.
that._activeEl = null; // The active showed iframe.
that._data = []; // The data collection.
that._el = null; // The module element.
that._rendered = false; // Whether if the instance has rendered.
// Get the data collection.
for (i = 0, j = that.urls.length; i < j; i += 1) {
that._data[i] = {
"id": "iframe-" + i,
"url": that.urls[i],
"rendered": false
};
}
}
IframePopup.prototype = {
_listeners: {},
_fire: function (type) {
if (this._listeners[type]) {
for (var i in this._listeners[type]) {
this._listeners[type][i]();
}
}
},
on: function (type, callback) {
if (!this._listeners[type]) {
this._listeners[type] = [];
}
this._listeners[type].push(callback);
},
render: function (rootEl) {
_log("render() is executed.");
var that = this,
className,
data = that._data[that.offset],
el;
if (that._rendered) {
_log("You can only render once.", "error");
return;
}
// Render the UI.
el = document.createElement("div");
if (that.offset === 0) {
el.className = "iframe-popup iframe-popup-first";
} else if (that.offset === that._data.length - 1) {
el.className = "iframe-popup iframe-popup-last";
}
el.innerHTML = [
'<div class="mod-content">',
' <div class="bd">',
' <iframe class="active" src="' + data.url + '" id="' + data.id + '"></iframe>',
' </div>',
' <div class="ft">',
' <a href="javascript:void(0);" id="prev-link">Previous Page</a>',
' <a href="javascript:void(0);" id="next-link">Next Page</a>',
' </div>',
'</div>'
].join("");
rootEl = rootEl || document.body;
rootEl.appendChild(el);
that._el = el;
that._activeEl = el.getElementsByTagName("iframe")[0];
// Bind events.
document.getElementById("prev-link").onclick = function () {
that.prev.call(that);
};
document.getElementById("next-link").onclick = function () {
that.next.call(that);
};
that._rendered = true;
},
move: function (isForward) {
var that = this,
activeEl, // Previous iframe element.
bodyEl, // .bd node.
boxEl, // Module.
data, // Next iframe data.
nextEl, // Next iframe element.
offset; // Next offset.
activeEl = that._activeEl;
boxEl = that._el;
offset = (isForward) ? that.offset + 1 : that.offset - 1;
data = that._data[offset];
if (!data) {
return false;
}
// Create iframe if it doesn't exist.
if (!data.rendered) {
nextEl = document.createElement("iframe");
nextEl.src = data.url;
nextEl.id = data.id;
bodyEl = activeEl.parentNode;
if (isForward) {
nextEl = bodyEl.appendChild(nextEl);
} else {
nextEl = bodyEl.insertBefore(nextEl, activeEl);
}
data.rendered = true;
} else {
nextEl = document.getElementById(data.id);
}
// Exchange the 'active' class.
activeEl.className = "";
nextEl.className = "active";
// Update outbox class.
if (isForward && offset === that.urls.length - 1) {
boxEl.className = "iframe-popup iframe-popup-last";
} else if (!isForward && offset === 0) {
boxEl.className = "iframe-popup iframe-popup-first";
} else {
boxEl.className = "iframe-popup";
}
that._activeEl = nextEl;
that.offset = offset;
this._fire("move");
return true;
},
next: function () {
_log("next() is executed.");
this._fire("next");
this.move(true);
},
prev: function () {
_log("prev() is executed.");
this._fire("prev");
this.move(false);
},
destroy: function () {
_log("destroy() is executed.");
var that = this,
data,
el,
i;
for (i = that._data.length - 1; i >= 0; i -= 1) {
data = that._data[i];
if (data.rendered) {
el = document.getElementById(data.id);
el.parentNode.removeChild(el);
el = null;
}
that._data[i] = null;
that._data.splice(i, 1);
}
that._el.parentNode.removeChild(that._el);
that._el = null;
}
};
window.IframePopup = IframePopup;
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment