How does the new Apple page fade in the image? - javascript

Apple changed their home page with a fade in effect that loads fast. Is this HTML 5 or jQuery?
Does anyone know how they did this?

It is JavaScript. HTML5 is a markup language - it doesn't do dynamic things. But the way people are throwing around the term, you'd think it could cure world hunger.
It looks like they use the Prototype library - probably for legacy reasons, now that jQuery has gained more traction. Or maybe they just prefer that library.
In plain JavaScript, you can fade a div with window.setInterval() and animating style.opacity.

With this bit of javascript --> http://images.apple.com/global/scripts/ac_blackout.js.
Here it is after a run through http://jsbeautifier.org/:
AC.Blackout = Class.create({
defaultOptions: {
duration: 1.25,
delay: 2,
showOnce: false,
showWhenReferredByApple: true
},
initialize: function (c, a, b) {
this.uniqueIdentifier = a || Math.floor(Math.random() * 1000000);
this.options = Object.extend(Object.clone(this.defaultOptions), b);
if (!this.shouldShow()) {
return false
}
this._addBodyClass();
Event.onDOMReady(function () {
this.og = {};
this.og.element = $(c);
this.bo = {};
this.bo.offsets = this.og.element ? this.og.element.cumulativeOffset() : [0, 0];
this.images = [];
if (this.options.showOnce) {
this._setHasShown()
}
this._create();
this.fade.bind(this).delay(this.options.delay)
}.bind(this))
},
addImage: function (b, a) {
this.preloadImage(b);
if ( !! this._acceptImages) {
this._addImage(false, b, a)
} else {
this._boundAddImage = this._addImage.bindAsEventListener(this, b, a);
Event.observe(document.body, "ACBlackout:acceptImages", this._boundAddImage)
}
},
preloadImage: function (c) {
var b = function (d) {
delete a
};
var a = new Image();
a.onload = b;
a.src = c
},
_addImage: function (a, c, b) {
if (typeof this.images == "undefined") {
return false
}
this.images.push(new AC.Blackout.Image(this.bo, c, b))
},
wasReferredByApple: function () {
if (typeof this._wasReferredByApple !== "undefined") {
return this._wasReferredByApple
}
this._wasReferredByApple = document.referrer.match(/^\w*:\/\/[^\.]*.apple.com/);
if ( !! document.referrer.match(/\/home/)) {
return false
}
return this._wasReferredByApple
},
shouldShow: function () {
if (typeof this._shouldShow !== "undefined") {
return this._shouldShow
}
if (/msie|MSIE 6/.test(navigator.userAgent)) {
return this._shouldShow = false
}
this._shouldShow = true;
if (this.options.showOnce) {
if (!this.options.showWhenReferredByApple) {
if (!this.wasReferredByApple()) {
return this._shouldShow = true
}
}
try {
typeof localStorage
} catch (b) {
return this._shouldShow = false
}
if (typeof localStorage !== "undefined") {
try {
var a = localStorage.getItem("ACBlackout-" + this.uniqueIdentifier);
this._shouldShow = (a == null) ? true : false
} catch (b) {
return this._shouldShow = false
}
} else {
if ("addBehavior" in document.body) {
document.body.addBehavior("#default#userData");
document.body.load("ACBlackout");
this._shouldShow = document.body.getAttribute("ACBlackout-" + this.uniqueIdentifier) == null ? true : false
}
}
} else {
if (!this.options.showWhenReferredByApple) {
if ( !! this.wasReferredByApple()) {
this._shouldShow = false
}
}
}
return this._shouldShow
},
_addBodyClass: function () {
document.body.className += " ACBlackoutBody"
},
_setHasShown: function () {
var a = new Date;
a = a.getTime();
try {
typeof localStorage
} catch (b) {
return true
}
if (typeof localStorage !== "undefined") {
try {
localStorage.setItem("ACBlackout-" + this.uniqueIdentifier, a)
} catch (b) {
return true
}
} else {
if ("addBehavior" in document.body) {
document.body.addBehavior("#default#userData");
document.body.setAttribute("ACBlackout-" + this.uniqueIdentifier, a);
document.body.save("ACBlackout");
return true
} else {
return true
}
}
},
_create: function () {
this.bo.height = document.documentElement.clientHeight > document.body.scrollHeight ? document.documentElement.clientHeight : document.body.scrollHeight;
if ($("ACBlackout")) {
this.bo.element = $("ACBlackout")
} else {
this.bo.element = new Element("div", {
id: "ACBlackout",
"class": "ACBlackout",
style: "height: " + this.bo.height + "px;"
})
}
this._acceptImages = true;
Event.fire(document.body, "ACBlackout:acceptImages", true);
if (AC.Detector.isCSSAvailable("transition")) {
this.bo.element.setVendorPrefixStyle("transition", this.options.duration + "s opacity ease-in")
}
if (AC.Detector.isIE()) {
Element.insert(document.body, {
bottom: this.bo.element
})
} else {
Element.insert(document.body, {
top: this.bo.element
})
}
Element.removeClassName(document.body, "ACBlackoutBody")
},
fade: function () {
if (AC.Detector.isCSSAvailable("transition")) {
var b = function (c) {
c.target.hide();
c.target.removeVendorEventListener("transitionEnd", a)
};
var a = b.bindAsEventListener(this);
this.bo.element.addVendorEventListener("transitionEnd", a);
this.bo.element.setStyle("opacity: 0;")
} else {
this.bo.element.fade({
duration: this.options.duration
})
}
}
});
AC.Blackout.Image = Class.create({
defaultOptions: {
offsets: [0, 0],
dimensions: false,
duration: 0.75,
delay: 0
},
initialize: function (b, c, a) {
this.options = Object.extend(Object.clone(this.defaultOptions), a);
this.bo = b;
this.src = c;
this._create();
this.fadeIn.bind(this).delay(this.options.delay)
},
_create: function () {
this.left = this.options.offsets[0];
this.top = this.bo.offsets[1] + this.options.offsets[1];
this.main = new Element("div", {
"class": "ACBlackoutMain"
});
this.img = new Element("img", {
src: this.src,
"class": "ACBlackoutImg",
style: "top: " + this.top + "px; left: " + this.left + "px;"
});
if (this.options.dimensions) {
this.img.setStyle("width: " + this.options.dimensions[0] + "px; height: " + this.options.dimensions[1] + "px;")
}
if (AC.Detector.isCSSAvailable("transition")) {
this.img.setStyle("opacity: 0");
this.img.setVendorPrefixStyle("transition", this.options.duration + "s opacity ease-in")
} else {
this.img.hide()
}
this.bo.element.insert(this.main);
this.main.insert(this.img)
},
fadeIn: function () {
if (AC.Detector.isCSSAvailable("transition")) {
this.img.setStyle("opacity: 1;")
} else {
this.img.appear({
duration: this.options.duration
})
}
}
});

Related

light weight javascript text editor not working

I have this light weight text editor that go on a webpage. It all displays well and work almost as expected but when you post the form the text area values do not get posted, I suspect the text is not inserted into the 'real' text box from the 'fake' textbox...
Here is the javascript and css and html. You will have to run this locally to output in php or something the $_POST values, to see what I mean.
window.FontAwesomeKitConfig = {"asyncLoading":{"enabled":true},"autoA11y":{"enabled":true},"baseUrl":"https://ka-f.fontawesome.com","baseUrlKit":"https://kit.fontawesome.com","detectConflictsUntil":null,"iconUploads":{},"id":44475219,"license":"free","method":"css","minify":{"enabled":true},"token":"7ce56be44b","v4FontFaceShim":{"enabled":false},"v4shim":{"enabled":false},"version":"5.15.4"};
!function(t){"function"==typeof define&&define.amd?define("kit-loader",t):t()}((function(){"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}function e(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function n(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function r(t){for(var r=1;r<arguments.length;r++){var o=null!=arguments[r]?arguments[r]:{};r%2?n(Object(o),!0).forEach((function(n){e(t,n,o[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):n(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}function o(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(t)))return;var n=[],r=!0,o=!1,i=void 0;try{for(var c,a=t[Symbol.iterator]();!(r=(c=a.next()).done)&&(n.push(c.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{r||null==a.return||a.return()}finally{if(o)throw i}}return n}(t,e)||function(t,e){if(!t)return;if("string"==typeof t)return i(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Array.from(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return i(t,e)}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function c(t,e){var n=e&&e.addOn||"",r=e&&e.baseFilename||t.license+n,o=e&&e.minify?".min":"",i=e&&e.fileSuffix||t.method,c=e&&e.subdir||t.method;return t.baseUrl+"/releases/"+("latest"===t.version?"latest":"v".concat(t.version))+"/"+c+"/"+r+o+"."+i}function a(t){return t.baseUrlKit+"/"+t.token+"/"+t.id+"/kit-upload.css"}function u(t,e){var n=e||["fa"],r="."+Array.prototype.join.call(n,",."),o=t.querySelectorAll(r);Array.prototype.forEach.call(o,(function(e){var n=e.getAttribute("title");e.setAttribute("aria-hidden","true");var r=!e.nextElementSibling||!e.nextElementSibling.classList.contains("sr-only");if(n&&r){var o=t.createElement("span");o.innerHTML=n,o.classList.add("sr-only"),e.parentNode.insertBefore(o,e.nextSibling)}}))}var f,s=function(){},d="undefined"!=typeof global&&void 0!==global.process&&"function"==typeof global.process.emit,l="undefined"==typeof setImmediate?setTimeout:setImmediate,h=[];function m(){for(var t=0;t<h.length;t++)h[t][0](h[t][1]);h=[],f=!1}function p(t,e){h.push([t,e]),f||(f=!0,l(m,0))}function y(t){var e=t.owner,n=e._state,r=e._data,o=t[n],i=t.then;if("function"==typeof o){n="fulfilled";try{r=o(r)}catch(t){w(i,t)}}b(i,r)||("fulfilled"===n&&v(i,r),"rejected"===n&&w(i,r))}function b(e,n){var r;try{if(e===n)throw new TypeError("A promises callback cannot return that same promise.");if(n&&("function"==typeof n||"object"===t(n))){var o=n.then;if("function"==typeof o)return o.call(n,(function(t){r||(r=!0,n===t?g(e,t):v(e,t))}),(function(t){r||(r=!0,w(e,t))})),!0}}catch(t){return r||w(e,t),!0}return!1}function v(t,e){t!==e&&b(t,e)||g(t,e)}function g(t,e){"pending"===t._state&&(t._state="settled",t._data=e,p(S,t))}function w(t,e){"pending"===t._state&&(t._state="settled",t._data=e,p(O,t))}function A(t){t._then=t._then.forEach(y)}function S(t){t._state="fulfilled",A(t)}function O(t){t._state="rejected",A(t),!t._handled&&d&&global.process.emit("unhandledRejection",t._data,t)}function j(t){global.process.emit("rejectionHandled",t)}function E(t){if("function"!=typeof t)throw new TypeError("Promise resolver "+t+" is not a function");if(this instanceof E==!1)throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this._then=[],function(t,e){function n(t){w(e,t)}try{t((function(t){v(e,t)}),n)}catch(t){n(t)}}(t,this)}E.prototype={constructor:E,_state:"pending",_then:null,_data:void 0,_handled:!1,then:function(t,e){var n={owner:this,then:new this.constructor(s),fulfilled:t,rejected:e};return!e&&!t||this._handled||(this._handled=!0,"rejected"===this._state&&d&&p(j,this)),"fulfilled"===this._state||"rejected"===this._state?p(y,n):this._then.push(n),n.then},catch:function(t){return this.then(null,t)}},E.all=function(t){if(!Array.isArray(t))throw new TypeError("You must pass an array to Promise.all().");return new E((function(e,n){var r=[],o=0;function i(t){return o++,function(n){r[t]=n,--o||e(r)}}for(var c,a=0;a<t.length;a++)(c=t[a])&&"function"==typeof c.then?c.then(i(a),n):r[a]=c;o||e(r)}))},E.race=function(t){if(!Array.isArray(t))throw new TypeError("You must pass an array to Promise.race().");return new E((function(e,n){for(var r,o=0;o<t.length;o++)(r=t[o])&&"function"==typeof r.then?r.then(e,n):e(r)}))},E.resolve=function(e){return e&&"object"===t(e)&&e.constructor===E?e:new E((function(t){t(e)}))},E.reject=function(t){return new E((function(e,n){n(t)}))};var _="function"==typeof Promise?Promise:E;function P(t,e){var n=e.fetch,r=e.XMLHttpRequest,o=e.token,i=t;return"URLSearchParams"in window?(i=new URL(t)).searchParams.set("token",o):i=i+"?token="+encodeURIComponent(o),i=i.toString(),new _((function(t,e){if("function"==typeof n)n(i,{mode:"cors",cache:"default"}).then((function(t){if(t.ok)return t.text();throw new Error("")})).then((function(e){t(e)})).catch(e);else if("function"==typeof r){var o=new r;o.addEventListener("loadend",(function(){this.responseText?t(this.responseText):e(new Error(""))}));["abort","error","timeout"].map((function(t){o.addEventListener(t,(function(){e(new Error(""))}))})),o.open("GET",i),o.send()}else{e(new Error(""))}}))}function C(t,e,n){var r=t;return[[/(url\("?)\.\.\/\.\.\/\.\./g,function(t,n){return"".concat(n).concat(e)}],[/(url\("?)\.\.\/webfonts/g,function(t,r){return"".concat(r).concat(e,"/releases/v").concat(n,"/webfonts")}],[/(url\("?)https:\/\/kit-free([^.])*\.fontawesome\.com/g,function(t,n){return"".concat(n).concat(e)}]].forEach((function(t){var e=o(t,2),n=e[0],i=e[1];r=r.replace(n,i)})),r}function F(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},o=e.document||o,i=u.bind(u,o,["fa","fab","fas","far","fal","fad","fak"]),f=Object.keys(t.iconUploads||{}).length>0;t.autoA11y.enabled&&n(i);var s=[{id:"fa-main",addOn:void 0}];t.v4shim.enabled&&s.push({id:"fa-v4-shims",addOn:"-v4-shims"}),t.v4FontFaceShim.enabled&&s.push({id:"fa-v4-font-face",addOn:"-v4-font-face"}),f&&s.push({id:"fa-kit-upload",customCss:!0});var d=s.map((function(n){return new _((function(o,i){P(n.customCss?a(t):c(t,{addOn:n.addOn,minify:t.minify.enabled}),e).then((function(i){o(U(i,r(r({},e),{},{baseUrl:t.baseUrl,version:t.version,id:n.id,contentFilter:function(t,e){return C(t,e.baseUrl,e.version)}})))})).catch(i)}))}));return _.all(d)}function U(t,e){var n=e.contentFilter||function(t,e){return t},r=document.createElement("style"),o=document.createTextNode(n(t,e));return r.appendChild(o),r.media="all",e.id&&r.setAttribute("id",e.id),e&&e.detectingConflicts&&e.detectionIgnoreAttr&&r.setAttributeNode(document.createAttribute(e.detectionIgnoreAttr)),r}function k(t,e){e.autoA11y=t.autoA11y.enabled,"pro"===t.license&&(e.autoFetchSvg=!0,e.fetchSvgFrom=t.baseUrl+"/releases/"+("latest"===t.version?"latest":"v".concat(t.version))+"/svgs",e.fetchUploadedSvgFrom=t.uploadsUrl);var n=[];return t.v4shim.enabled&&n.push(new _((function(n,o){P(c(t,{addOn:"-v4-shims",minify:t.minify.enabled}),e).then((function(t){n(I(t,r(r({},e),{},{id:"fa-v4-shims"})))})).catch(o)}))),n.push(new _((function(n,o){P(c(t,{minify:t.minify.enabled}),e).then((function(t){var o=I(t,r(r({},e),{},{id:"fa-main"}));n(function(t,e){var n=e&&void 0!==e.autoFetchSvg?e.autoFetchSvg:void 0,r=e&&void 0!==e.autoA11y?e.autoA11y:void 0;void 0!==r&&t.setAttribute("data-auto-a11y",r?"true":"false");n&&(t.setAttributeNode(document.createAttribute("data-auto-fetch-svg")),t.setAttribute("data-fetch-svg-from",e.fetchSvgFrom),t.setAttribute("data-fetch-uploaded-svg-from",e.fetchUploadedSvgFrom));return t}(o,e))})).catch(o)}))),_.all(n)}function I(t,e){var n=document.createElement("SCRIPT"),r=document.createTextNode(t);return n.appendChild(r),n.referrerPolicy="strict-origin",e.id&&n.setAttribute("id",e.id),e&&e.detectingConflicts&&e.detectionIgnoreAttr&&n.setAttributeNode(document.createAttribute(e.detectionIgnoreAttr)),n}function L(t){var e,n=[],r=document,o=r.documentElement.doScroll,i=(o?/^loaded|^c/:/^loaded|^i|^c/).test(r.readyState);i||r.addEventListener("DOMContentLoaded",e=function(){for(r.removeEventListener("DOMContentLoaded",e),i=1;e=n.shift();)e()}),i?setTimeout(t,0):n.push(t)}function T(t){"undefined"!=typeof MutationObserver&&new MutationObserver(t).observe(document,{childList:!0,subtree:!0})}try{if(window.FontAwesomeKitConfig){var x=window.FontAwesomeKitConfig,M={detectingConflicts:x.detectConflictsUntil&&new Date<=new Date(x.detectConflictsUntil),detectionIgnoreAttr:"data-fa-detection-ignore",fetch:window.fetch,token:x.token,XMLHttpRequest:window.XMLHttpRequest,document:document},D=document.currentScript,N=D?D.parentElement:document.head;(function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return"js"===t.method?k(t,e):"css"===t.method?F(t,e,(function(t){L(t),T(t)})):void 0})(x,M).then((function(t){t.map((function(t){try{N.insertBefore(t,D?D.nextSibling:null)}catch(e){N.appendChild(t)}})),M.detectingConflicts&&D&&L((function(){D.setAttributeNode(document.createAttribute(M.detectionIgnoreAttr));var t=function(t,e){var n=document.createElement("script");return e&&e.detectionIgnoreAttr&&n.setAttributeNode(document.createAttribute(e.detectionIgnoreAttr)),n.src=c(t,{baseFilename:"conflict-detection",fileSuffix:"js",subdir:"js",minify:t.minify.enabled}),n}(x,M);document.body.appendChild(t)}))})).catch((function(t){console.error("".concat("Font Awesome Kit:"," ").concat(t))}))}}catch(t){console.error("".concat("Font Awesome Kit:"," ").concat(t))}}));
//internal variables
var show = false;
//textAreaSelector
const textAreaSelector = document.getElementById('text-editor');
//buttonsToolbar
var buttonsToolbar = document.createElement('div');
buttonsToolbar.setAttribute('id', 'buttonsToolbar');
///buttonsToolbar
//textEditor
var textEditor = document.createElement('div');
textEditor.setAttribute('id', 'textEditor');
textEditor.setAttribute('contentEditable', 'true');
///textEditor
insidetext = document.getElementById('text-editor').textContent;
textEditor.innerHTML = insidetext;
//functions
function insertAfter(insertObject) {
insertObject.forEach(insertObj => {
insertObj.reference.parentNode.insertBefore(insertObj.new, insertObj.reference.nextSibling);
});
}
var buttons = [
{
name: 'alignLeft',
cmd: 'justifyLeft',
icon: 'fas fa-align-left'
},
{
name: 'alignCenter',
cmd: 'justifyCenter',
icon: 'fas fa-align-center'
},
{
name: 'alignJustify',
cmd: 'justifyFull',
icon: 'fas fa-align-justify'
},
{
name: 'alignRight',
cmd: 'justifyRight',
icon: 'fas fa-align-right'
},
{
name: 'bold',
cmd: 'bold',
icon: 'fas fa-bold'
},
{
name: 'italic',
cmd: 'italic',
icon: 'fas fa-italic'
},
{
name: 'underline',
cmd: 'underline',
icon: 'fas fa-underline'
},
{
name: 'insertOrderedList',
cmd: 'insertOrderedList',
icon: 'fas fa-list-ol'
},
{
name: 'insertUnorderedList',
cmd: 'insertUnorderedList',
icon: 'fas fa-list-ul'
},
// {
// name: 'insertImage',
// cmd: 'insertImage',
// icon: 'fas fa-image'
// },
// {
// name: 'insertLink',
// cmd: 'createLink',
// icon: 'fas fa-link'
// },
{
name: 'showCode',
cmd: 'showCode',
icon: 'fas fa-code'
},
]
buttons.forEach(button => {
//buttonElement
let buttonElement = document.createElement('button');
buttonElement.type = 'button';
buttonElement.setAttribute('id', button.name);
///buttonElement
//buttonIcon
let buttonIcon = document.createElement('i');
buttonIcon.setAttribute('class', button.icon);
///buttonIcon
buttonElement.addEventListener('click', () => {
let current = document.getElementsByClassName('active');
if (current.length > 0) {
current[0].classList.remove('active');
}
buttonElement.classList.add('active');
switch (button.cmd) {
case 'insertImage':
url = prompt('Enter image link here: ', '');
if (url) {
document.execCommand(button.cmd, false, url);
}
const images = textEditor.querySelectorAll('img');
images.forEach(img => {
img.style.maxWidth = '500px';
});
break;
// case 'createLink':
// url = prompt('Enter URL link here: ', '');
// text = prompt('Enter link text here: ', '');
// if (url && text) {
// document.execCommand(
// 'insertHTML',
// false,
// `<a href=${url} target='_blank'>${text}</a>`
// );
// }
const links = textEditor.querySelectorAll('a');
links.forEach(lnk => {
lnk.target = '_blank';
lnk.addEventListener('mouseover', () => {
textEditor.setAttribute('contentEditable', 'false');
});
lnk.addEventListener('mouseout', () => {
textEditor.setAttribute('contentEditable', 'true');
});
});
break;
case 'showCode':
if (show) {
buttonElement.classList.remove('active');
textEditor.innerHTML = textEditor.textContent;
show = false;
} else {
textEditor.textContent = textEditor.innerHTML;
show = true;
}
break;
default:
document.execCommand(button.cmd, false, null);
break;
}
});
buttonElement.appendChild(buttonIcon);
buttonsToolbar.appendChild(buttonElement);
});
insertAfter([
{
reference: textAreaSelector,
new: textEditor
},
{
reference: textAreaSelector,
new: buttonsToolbar
}
]);
textAreaSelector.remove();
#buttonsToolbar button:last-child {
margin: 0;
}
#buttonsToolbar button {
width: 30px;
height: 30px;
margin: 0 5px 0 0;
border: none;
outline: none;
cursor: pointer;
}
#buttonsToolbar {
width: fit-content;
}
#textEditor {
width: 100%;
height: 250px;
margin-top: 5px;
padding: 5px;
color: black;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 3px;
outline: none;
background-color: white;
box-shadow: 0 8px 18px rgba(0, 0, 0, .1);
}
#buttonsToolbar button.active {
background-color: rgb(214, 214, 214)
}
#textEditor p {
color:black;
}
<form method="post" accept-charset="utf-8">
<div class="input textarea">
<label for="address">Address (200 characters)</label>
<textarea name="businessaddress" id="text-editor" rows="2"></textarea>
</div>
<button class="btn btn-primary float-end" type="submit">Submit</button>
</form>
Some points you were missing:
You need the <textarea> element since an editable div is not a proper form element (so you won't get any $_POST data).
Therefore you need to delete
textAreaSelector.remove(); – but you can just hide it via e.g a display:none;
Besides, you will also need to synchronize current text inputs between editor div and textarea:
textEditor.addEventListener('keyup', function(e){
let currentContent = e.currentTarget.innerHTML;
textAreaSelector.value = currentContent;
})
Edit: editor updating on button click
//internal variables
var show = false;
//textAreaSelector
const textAreaSelector = document.getElementById("text-editor");
//buttonsToolbar
var buttonsToolbar = document.createElement("div");
buttonsToolbar.setAttribute("id", "buttonsToolbar");
var textEditor = document.createElement("div");
textEditor.setAttribute("id", "textEditor");
textEditor.setAttribute("contentEditable", "true");
insidetext = textAreaSelector.textContent;
textEditor.innerHTML = insidetext;
textEditor.addEventListener('keyup', function(e) {
updateText()
});
// update/synchronize and sanitize text
function updateText() {
setTimeout(function() {
let currentContent = textEditor.innerHTML;
let currentContentTxt = textEditor.textContent.replaceAll(/\s/g, '');
currentContent = currentContent.replaceAll('<div>', '<p>').
replaceAll('</div>', '</p>').
replaceAll('<i>', '<em>').
replaceAll('</i>', '</em>').
replaceAll('<b>', '<strong>').
replaceAll('</b>', '</strong>').
replaceAll('<div style=', '<p style=').
replaceAll('</div>', '</p>');
// remove empty html elements
if (!currentContentTxt) {
currentContent = '';
}
textAreaSelector.value = currentContent;
//console.log(currentContent);
//console.log(currentContentTxt);
}, 200);
}
//functions
function insertAfter(insertObject) {
insertObject.forEach((insertObj) => {
insertObj.reference.parentNode.insertBefore(
insertObj.new,
insertObj.reference.nextSibling
);
});
}
var buttons = [{
name: "alignLeft",
cmd: "justifyLeft",
icon: "fas fa-align-left"
},
{
name: "alignCenter",
cmd: "justifyCenter",
icon: "fas fa-align-center"
},
{
name: "alignJustify",
cmd: "justifyFull",
icon: "fas fa-align-justify"
},
{
name: "alignRight",
cmd: "justifyRight",
icon: "fas fa-align-right"
},
{
name: "bold",
cmd: "bold",
icon: "fas fa-bold"
},
{
name: "italic",
cmd: "italic",
icon: "fas fa-italic"
},
{
name: "underline",
cmd: "underline",
icon: "fas fa-underline"
},
{
name: "insertOrderedList",
cmd: "insertOrderedList",
icon: "fas fa-list-ol"
},
{
name: "insertUnorderedList",
cmd: "insertUnorderedList",
icon: "fas fa-list-ul"
},
// {
// name: 'insertImage',
// cmd: 'insertImage',
// icon: 'fas fa-image'
// },
// {
// name: 'insertLink',
// cmd: 'createLink',
// icon: 'fas fa-link'
// },
{
name: "showCode",
cmd: "showCode",
icon: "fas fa-code"
}
];
buttons.forEach((button) => {
//buttonElement
let buttonElement = document.createElement("button");
buttonElement.type = "button";
buttonElement.setAttribute("id", button.name);
///buttonElement
//buttonIcon
let buttonIcon = document.createElement("i");
buttonIcon.setAttribute("class", button.icon);
///buttonIcon
buttonElement.addEventListener("click", () => {
let current = document.getElementsByClassName("active");
if (current.length > 0) {
current[0].classList.remove("active");
}
buttonElement.classList.add("active");
updateText();
switch (button.cmd) {
case "insertImage":
url = prompt("Enter image link here: ", "");
if (url) {
document.execCommand(button.cmd, false, url);
}
const images = textEditor.querySelectorAll("img");
images.forEach((img) => {
img.style.maxWidth = "500px";
});
break;
// case 'createLink':
// url = prompt('Enter URL link here: ', '');
// text = prompt('Enter link text here: ', '');
// if (url && text) {
// document.execCommand(
// 'insertHTML',
// false,
// `<a href=${url} target='_blank'>${text}</a>`
// );
// }
const links = textEditor.querySelectorAll("a");
links.forEach((lnk) => {
lnk.target = "_blank";
lnk.addEventListener("mouseover", () => {
textEditor.setAttribute("contentEditable", "false");
});
lnk.addEventListener("mouseout", () => {
textEditor.setAttribute("contentEditable", "true");
});
});
break;
case "showCode":
if (show) {
buttonElement.classList.remove("active");
textEditor.innerHTML = textEditor.textContent;
show = false;
} else {
textEditor.textContent = textEditor.innerHTML;
show = true;
}
break;
default:
document.execCommand(button.cmd, false, null);
break;
}
});
buttonElement.appendChild(buttonIcon);
buttonsToolbar.appendChild(buttonElement);
});
insertAfter([{
reference: textAreaSelector,
new: textEditor
},
{
reference: textAreaSelector,
new: buttonsToolbar
}
]);
//textAreaSelector.remove();
window.FontAwesomeKitConfig = {
asyncLoading: {
enabled: true
},
autoA11y: {
enabled: true
},
baseUrl: "https://ka-f.fontawesome.com",
baseUrlKit: "https://kit.fontawesome.com",
detectConflictsUntil: null,
iconUploads: {},
id: 44475219,
license: "free",
method: "css",
minify: {
enabled: true
},
token: "7ce56be44b",
v4FontFaceShim: {
enabled: false
},
v4shim: {
enabled: false
},
version: "5.15.4"
};
!(function(t) {
"function" == typeof define && define.amd ? define("kit-loader", t) : t();
})(function() {
"use strict";
function t(e) {
return (t =
"function" == typeof Symbol && "symbol" == typeof Symbol.iterator ?
function(t) {
return typeof t;
} :
function(t) {
return t &&
"function" == typeof Symbol &&
t.constructor === Symbol &&
t !== Symbol.prototype ?
"symbol" :
typeof t;
})(e);
}
function e(t, e, n) {
return (
e in t ?
Object.defineProperty(t, e, {
value: n,
enumerable: !0,
configurable: !0,
writable: !0
}) :
(t[e] = n),
t
);
}
function n(t, e) {
var n = Object.keys(t);
if (Object.getOwnPropertySymbols) {
var r = Object.getOwnPropertySymbols(t);
e &&
(r = r.filter(function(e) {
return Object.getOwnPropertyDescriptor(t, e).enumerable;
})),
n.push.apply(n, r);
}
return n;
}
function r(t) {
for (var r = 1; r < arguments.length; r++) {
var o = null != arguments[r] ? arguments[r] : {};
r % 2 ?
n(Object(o), !0).forEach(function(n) {
e(t, n, o[n]);
}) :
Object.getOwnPropertyDescriptors ?
Object.defineProperties(t, Object.getOwnPropertyDescriptors(o)) :
n(Object(o)).forEach(function(e) {
Object.defineProperty(t, e, Object.getOwnPropertyDescriptor(o, e));
});
}
return t;
}
function o(t, e) {
return (
(function(t) {
if (Array.isArray(t)) return t;
})(t) ||
(function(t, e) {
if ("undefined" == typeof Symbol || !(Symbol.iterator in Object(t)))
return;
var n = [],
r = !0,
o = !1,
i = void 0;
try {
for (
var c, a = t[Symbol.iterator](); !(r = (c = a.next()).done) &&
(n.push(c.value), !e || n.length !== e); r = !0
);
} catch (t) {
(o = !0), (i = t);
} finally {
try {
r || null == a.return || a.return();
} finally {
if (o) throw i;
}
}
return n;
})(t, e) ||
(function(t, e) {
if (!t) return;
if ("string" == typeof t) return i(t, e);
var n = Object.prototype.toString.call(t).slice(8, -1);
"Object" === n && t.constructor && (n = t.constructor.name);
if ("Map" === n || "Set" === n) return Array.from(t);
if (
"Arguments" === n ||
/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)
)
return i(t, e);
})(t, e) ||
(function() {
throw new TypeError(
"Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
})()
);
}
function i(t, e) {
(null == e || e > t.length) && (e = t.length);
for (var n = 0, r = new Array(e); n < e; n++) r[n] = t[n];
return r;
}
function c(t, e) {
var n = (e && e.addOn) || "",
r = (e && e.baseFilename) || t.license + n,
o = e && e.minify ? ".min" : "",
i = (e && e.fileSuffix) || t.method,
c = (e && e.subdir) || t.method;
return (
t.baseUrl +
"/releases/" +
("latest" === t.version ? "latest" : "v".concat(t.version)) +
"/" +
c +
"/" +
r +
o +
"." +
i
);
}
function a(t) {
return t.baseUrlKit + "/" + t.token + "/" + t.id + "/kit-upload.css";
}
function u(t, e) {
var n = e || ["fa"],
r = "." + Array.prototype.join.call(n, ",."),
o = t.querySelectorAll(r);
Array.prototype.forEach.call(o, function(e) {
var n = e.getAttribute("title");
e.setAttribute("aria-hidden", "true");
var r = !e.nextElementSibling ||
!e.nextElementSibling.classList.contains("sr-only");
if (n && r) {
var o = t.createElement("span");
(o.innerHTML = n),
o.classList.add("sr-only"),
e.parentNode.insertBefore(o, e.nextSibling);
}
});
}
var f,
s = function() {},
d =
"undefined" != typeof global &&
void 0 !== global.process &&
"function" == typeof global.process.emit,
l = "undefined" == typeof setImmediate ? setTimeout : setImmediate,
h = [];
function m() {
for (var t = 0; t < h.length; t++) h[t][0](h[t][1]);
(h = []), (f = !1);
}
function p(t, e) {
h.push([t, e]), f || ((f = !0), l(m, 0));
}
function y(t) {
var e = t.owner,
n = e._state,
r = e._data,
o = t[n],
i = t.then;
if ("function" == typeof o) {
n = "fulfilled";
try {
r = o(r);
} catch (t) {
w(i, t);
}
}
b(i, r) || ("fulfilled" === n && v(i, r), "rejected" === n && w(i, r));
}
function b(e, n) {
var r;
try {
if (e === n)
throw new TypeError(
"A promises callback cannot return that same promise."
);
if (n && ("function" == typeof n || "object" === t(n))) {
var o = n.then;
if ("function" == typeof o)
return (
o.call(
n,
function(t) {
r || ((r = !0), n === t ? g(e, t) : v(e, t));
},
function(t) {
r || ((r = !0), w(e, t));
}
), !0
);
}
} catch (t) {
return r || w(e, t), !0;
}
return !1;
}
function v(t, e) {
(t !== e && b(t, e)) || g(t, e);
}
function g(t, e) {
"pending" === t._state && ((t._state = "settled"), (t._data = e), p(S, t));
}
function w(t, e) {
"pending" === t._state && ((t._state = "settled"), (t._data = e), p(O, t));
}
function A(t) {
t._then = t._then.forEach(y);
}
function S(t) {
(t._state = "fulfilled"), A(t);
}
function O(t) {
(t._state = "rejected"),
A(t), !t._handled && d && global.process.emit("unhandledRejection", t._data, t);
}
function j(t) {
global.process.emit("rejectionHandled", t);
}
function E(t) {
if ("function" != typeof t)
throw new TypeError("Promise resolver " + t + " is not a function");
if (this instanceof E == !1)
throw new TypeError(
"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."
);
(this._then = []),
(function(t, e) {
function n(t) {
w(e, t);
}
try {
t(function(t) {
v(e, t);
}, n);
} catch (t) {
n(t);
}
})(t, this);
}
(E.prototype = {
constructor: E,
_state: "pending",
_then: null,
_data: void 0,
_handled: !1,
then: function(t, e) {
var n = {
owner: this,
then: new this.constructor(s),
fulfilled: t,
rejected: e
};
return (
(!e && !t) ||
this._handled ||
((this._handled = !0), "rejected" === this._state && d && p(j, this)),
"fulfilled" === this._state || "rejected" === this._state ?
p(y, n) :
this._then.push(n),
n.then
);
},
catch: function(t) {
return this.then(null, t);
}
}),
(E.all = function(t) {
if (!Array.isArray(t))
throw new TypeError("You must pass an array to Promise.all().");
return new E(function(e, n) {
var r = [],
o = 0;
function i(t) {
return (
o++,
function(n) {
(r[t] = n), --o || e(r);
}
);
}
for (var c, a = 0; a < t.length; a++)
(c = t[a]) && "function" == typeof c.then ?
c.then(i(a), n) :
(r[a] = c);
o || e(r);
});
}),
(E.race = function(t) {
if (!Array.isArray(t))
throw new TypeError("You must pass an array to Promise.race().");
return new E(function(e, n) {
for (var r, o = 0; o < t.length; o++)
(r = t[o]) && "function" == typeof r.then ? r.then(e, n) : e(r);
});
}),
(E.resolve = function(e) {
return e && "object" === t(e) && e.constructor === E ?
e :
new E(function(t) {
t(e);
});
}),
(E.reject = function(t) {
return new E(function(e, n) {
n(t);
});
});
var _ = "function" == typeof Promise ? Promise : E;
function P(t, e) {
var n = e.fetch,
r = e.XMLHttpRequest,
o = e.token,
i = t;
return (
"URLSearchParams" in window ?
(i = new URL(t)).searchParams.set("token", o) :
(i = i + "?token=" + encodeURIComponent(o)),
(i = i.toString()),
new _(function(t, e) {
if ("function" == typeof n)
n(i, {
mode: "cors",
cache: "default"
})
.then(function(t) {
if (t.ok) return t.text();
throw new Error("");
})
.then(function(e) {
t(e);
})
.catch(e);
else if ("function" == typeof r) {
var o = new r();
o.addEventListener("loadend", function() {
this.responseText ? t(this.responseText) : e(new Error(""));
});
["abort", "error", "timeout"].map(function(t) {
o.addEventListener(t, function() {
e(new Error(""));
});
}),
o.open("GET", i),
o.send();
} else {
e(new Error(""));
}
})
);
}
function C(t, e, n) {
var r = t;
return (
[
[
/(url\("?)\.\.\/\.\.\/\.\./g,
function(t, n) {
return "".concat(n).concat(e);
}
],
[
/(url\("?)\.\.\/webfonts/g,
function(t, r) {
return "".concat(r).concat(e, "/releases/v").concat(n, "/webfonts");
}
],
[
/(url\("?)https:\/\/kit-free([^.])*\.fontawesome\.com/g,
function(t, n) {
return "".concat(n).concat(e);
}
]
].forEach(function(t) {
var e = o(t, 2),
n = e[0],
i = e[1];
r = r.replace(n, i);
}),
r
);
}
function F(t, e) {
var n =
arguments.length > 2 && void 0 !== arguments[2] ?
arguments[2] :
function() {},
o = e.document || o,
i = u.bind(u, o, ["fa", "fab", "fas", "far", "fal", "fad", "fak"]),
f = Object.keys(t.iconUploads || {}).length > 0;
t.autoA11y.enabled && n(i);
var s = [{
id: "fa-main",
addOn: void 0
}];
t.v4shim.enabled && s.push({
id: "fa-v4-shims",
addOn: "-v4-shims"
}),
t.v4FontFaceShim.enabled &&
s.push({
id: "fa-v4-font-face",
addOn: "-v4-font-face"
}),
f && s.push({
id: "fa-kit-upload",
customCss: !0
});
var d = s.map(function(n) {
return new _(function(o, i) {
P(
n.customCss ?
a(t) :
c(t, {
addOn: n.addOn,
minify: t.minify.enabled
}),
e
)
.then(function(i) {
o(
U(
i,
r(
r({}, e), {}, {
baseUrl: t.baseUrl,
version: t.version,
id: n.id,
contentFilter: function(t, e) {
return C(t, e.baseUrl, e.version);
}
}
)
)
);
})
.catch(i);
});
});
return _.all(d);
}
function U(t, e) {
var n =
e.contentFilter ||
function(t, e) {
return t;
},
r = document.createElement("style"),
o = document.createTextNode(n(t, e));
return (
r.appendChild(o),
(r.media = "all"),
e.id && r.setAttribute("id", e.id),
e &&
e.detectingConflicts &&
e.detectionIgnoreAttr &&
r.setAttributeNode(document.createAttribute(e.detectionIgnoreAttr)),
r
);
}
function k(t, e) {
(e.autoA11y = t.autoA11y.enabled),
"pro" === t.license &&
((e.autoFetchSvg = !0),
(e.fetchSvgFrom =
t.baseUrl +
"/releases/" +
("latest" === t.version ? "latest" : "v".concat(t.version)) +
"/svgs"),
(e.fetchUploadedSvgFrom = t.uploadsUrl));
var n = [];
return (
t.v4shim.enabled &&
n.push(
new _(function(n, o) {
P(c(t, {
addOn: "-v4-shims",
minify: t.minify.enabled
}), e)
.then(function(t) {
n(I(t, r(r({}, e), {}, {
id: "fa-v4-shims"
})));
})
.catch(o);
})
),
n.push(
new _(function(n, o) {
P(c(t, {
minify: t.minify.enabled
}), e)
.then(function(t) {
var o = I(t, r(r({}, e), {}, {
id: "fa-main"
}));
n(
(function(t, e) {
var n =
e && void 0 !== e.autoFetchSvg ? e.autoFetchSvg : void 0,
r = e && void 0 !== e.autoA11y ? e.autoA11y : void 0;
void 0 !== r &&
t.setAttribute("data-auto-a11y", r ? "true" : "false");
n &&
(t.setAttributeNode(
document.createAttribute("data-auto-fetch-svg")
),
t.setAttribute("data-fetch-svg-from", e.fetchSvgFrom),
t.setAttribute(
"data-fetch-uploaded-svg-from",
e.fetchUploadedSvgFrom
));
return t;
})(o, e)
);
})
.catch(o);
})
),
_.all(n)
);
}
function I(t, e) {
var n = document.createElement("SCRIPT"),
r = document.createTextNode(t);
return (
n.appendChild(r),
(n.referrerPolicy = "strict-origin"),
e.id && n.setAttribute("id", e.id),
e &&
e.detectingConflicts &&
e.detectionIgnoreAttr &&
n.setAttributeNode(document.createAttribute(e.detectionIgnoreAttr)),
n
);
}
function L(t) {
var e,
n = [],
r = document,
o = r.documentElement.doScroll,
i = (o ? /^loaded|^c/ : /^loaded|^i|^c/).test(r.readyState);
i ||
r.addEventListener(
"DOMContentLoaded",
(e = function() {
for (
r.removeEventListener("DOMContentLoaded", e), i = 1;
(e = n.shift());
)
e();
})
),
i ? setTimeout(t, 0) : n.push(t);
}
function T(t) {
"undefined" != typeof MutationObserver &&
new MutationObserver(t).observe(document, {
childList: !0,
subtree: !0
});
}
try {
if (window.FontAwesomeKitConfig) {
var x = window.FontAwesomeKitConfig,
M = {
detectingConflicts: x.detectConflictsUntil &&
new Date() <= new Date(x.detectConflictsUntil),
detectionIgnoreAttr: "data-fa-detection-ignore",
fetch: window.fetch,
token: x.token,
XMLHttpRequest: window.XMLHttpRequest,
document: document
},
D = document.currentScript,
N = D ? D.parentElement : document.head;
(function() {
var t =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
e =
arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
return "js" === t.method ?
k(t, e) :
"css" === t.method ?
F(t, e, function(t) {
L(t), T(t);
}) :
void 0;
})(x, M)
.then(function(t) {
t.map(function(t) {
try {
N.insertBefore(t, D ? D.nextSibling : null);
} catch (e) {
N.appendChild(t);
}
}),
M.detectingConflicts &&
D &&
L(function() {
D.setAttributeNode(
document.createAttribute(M.detectionIgnoreAttr)
);
var t = (function(t, e) {
var n = document.createElement("script");
return (
e &&
e.detectionIgnoreAttr &&
n.setAttributeNode(
document.createAttribute(e.detectionIgnoreAttr)
),
(n.src = c(t, {
baseFilename: "conflict-detection",
fileSuffix: "js",
subdir: "js",
minify: t.minify.enabled
})),
n
);
})(x, M);
document.body.appendChild(t);
});
})
.catch(function(t) {
console.error("".concat("Font Awesome Kit:", " ").concat(t));
});
}
} catch (t) {
console.error("".concat("Font Awesome Kit:", " ").concat(t));
}
});
#buttonsToolbar button:last-child {
margin: 0;
}
#buttonsToolbar button {
width: 30px;
height: 30px;
margin: 0 5px 0 0;
border: none;
outline: none;
cursor: pointer;
}
#buttonsToolbar {
width: fit-content;
}
#textEditor {
width: 100%;
height: 250px;
margin-top: 5px;
padding: 5px;
color: black;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 3px;
outline: none;
background-color: white;
box-shadow: 0 8px 18px rgba(0, 0, 0, .1);
}
#buttonsToolbar button.active {
background-color: rgb(214, 214, 214)
}
#textEditor p {
color: black;
}
<form method="post" accept-charset="utf-8">
<div class="input textarea">
<label for="address">Address (200 characters)</label>
<textarea name="businessaddress" id="text-editor" rows="2"></textarea>
</div>
<button class="btn btn-primary float-end" type="submit">Submit</button>
</form>
Better opt in for a more advanced rich text editor
The problem with most lightweight editors like this hey are lacking a lot of useful if not indispensable features like sanitizing pasteboard formating.
So I strongly recommend searching for other alternatives.
Awesome WYSIWYG – A curated list of awesome WYSIWYG editors.

How to execute all proto chain of a method in a class?

I think the code will be a best explanation of my issue:
function getMyConstructor(){
...
}
const MyConstructor = getMyConstructor({
x: 0,
getX: function(){ return this.x; }
},{
x: 1,
getX: function(){ return this.__getX() + ' first'; }
},{
x: 2,
getX: function(){ return this.__getX() + ' second'; }
},{
x: 3,
getX: function(){ return this.__getX() + ' third'; }
});
const myInstance = new MyConstructor;
console.log( myInstance.getX() ) // 3 first second third
Does someone know how to implement the __getX method?
UPDATE:
I've made the code but I think that it's not so pretty
function getMyConstructor() {
return Array.prototype.reduce.call(arguments, (proto, obj, index, args) => {
function C() {
}
C.prototype = Object.create(proto);
for (let p in obj) {
if (!obj.hasOwnProperty(p)) {
continue;
}
C.prototype[p] = obj[p];
if (index > 0 && typeof obj[p] === 'function') {
C.prototype['__' + p] = setBaseMethod(p, proto);
}
}
return index === args.length - 1 ? C : C.prototype;
});
/**
* #param {string} method
* #param {Object} proto
* #returns Function
*/
function setBaseMethod(method, proto) {
let obj = {};
obj[method] = proto[method];
obj['__' + method] = proto['__' + method];
return function () {
let context = {};
for (let p in proto) {
if (this[p] && typeof this[p] !== 'function') {
Object.defineProperty(context, p, {
get: () => this[p],
set: value => this[p] = value,
enumerable: true,
configurable: true
});
}
}
return Object.assign({}, context, obj)[method]();
}
}
}
I hope the code suggest how to resolve the problem
Just for fun, since you asked for a prototype chain:
function chainPrototypes(...objs) {
return objs.reduce((p, o) => Object.setPrototypeOf(o, p));
}
const myInstance = chainPrototypes({
x: 0,
getX() { return this.x; }
}, {
x: 1,
getX() { return super.getX() + ' first'; }
}, {
x: 2,
getX() { return super.getX() + ' second'; }
}, {
x: 3,
getX() { return super.getX() + ' third'; }
});
console.log(myInstance.getX()); // 3 first second third
Just use method definitions with the super keyword.

Javascript help needed, store local variable

As Javascript newbie I'm not able to store locally a variable and reuse from Google cache.
I have a counter that starts onClick from zero then increments until a specific number then goes to a new page.
In the new page I need to continue the counter from the previous number.
I can't use cookies since this is for a Chrome extension, so I used storage.local and I set my manifest as follow:
...
"permissions": ["storage", "https://example.com/*", "unlimitedStorage"],
"content_scripts": [
{
"matches": ["https://example.com/*"],
"js": ["js/jquery-2.1.4.min.js", "js/example.js"],
"css": ["css/example.css"]
}
],
...
So basically when I click my button it starts the follow function and it increments this.count
function Button(t, e, i) {
var n = this;
n.$el = t,
n.count = (Record.get(function() {tmf.followBtn.counter()}) > 1 ? Record.get(function() {tmf.followBtn.counter()}) : 0),
n.$title = t.find(".tmf-btn__title"),
n.$subtitle = t.find(".tmf-btn__subtitle"),
n.action = new BulkAction(e, i), n.$el.on("click", function() {
n.$el.addClass("tmf-btn--active"),
n.$title.text(n.count),
n.action.paused ? (n.action.proceed(), n.$subtitle.text("Click to pause")) : (n.action.pause(), n.$subtitle.text("Click to continue"))
})
}
function Profile(t) {
this.$el = $(".ProfileCard:eq(" + t + ")"),
this.isLoaded() && (this.$btn = this.$el.find(".user-actions-follow-button"),
this.id = this.$el.data("user-id") + "-")
}
function BulkAction(t, e) {
this.callback = t,
this.interval = e,
this.paused = !0
}
function gotoPage() {
window.location.replace("https://example.com/newpage/");
}
$.fn.isPresent = function() {
return this.length > 0
};
var USER_ID = $("#user-dropdown").find("[data-user-id]").data("user-id"),
Record = {
storage: chrome.storage.local,
key: USER_ID.toString(),
get: function(t) {
var e = this;
this.storage.get(this.key, function(i) {
e.result = i, t.call()
})
},
set: function() {
this.storage.set(this.result)
},
add: function(t) {
this.result[this.key] ? this.result[this.key] += t : this.result[this.key] = t, this.set()
},
includes: function(t) {
return this.result[this.key] ? this.result[this.key].includes(t) : !1
}
},
tmf = {
init: function() {
var t = this;
t.$el = $("<div>").addClass("tmf animated").appendTo("body")
},
toggle: function() {
var t = this;
this.$el.removeClass("flipInY flipOutY tmf--active"), $(".ProfileCard").length > 10 ? t.$el.load(chrome.extension.getURL("html/actions.html"), {}, function() {
$(".tmf-btn").on("click", function() {
t.$el.addClass("tmf--active")
}), t.followBtn = new Button($(".tmf-btn--follow"), function() {
this.follow()
}, 100), t.unfollowBtn = new Button($(".tmf-btn--unfollow"), function() {
this.unfollow()
}, 100), t.$el.addClass("flipInY");
var e = new MutationObserver(function(e) {
e.forEach(function(e) {
var i = $("#message-drawer").html();
i.includes("66885") && t.followBtn.setIdle()
})
});
e.observe(document.getElementById("message-drawer"), {
subtree: !0,
characterData: !0,
childList: !0
}), $("#tmf_without_exception").on("change", function() {
t.withoutException = this.checked,
this.checked ? (t.followBtn.$subtitle.text("without exception"),t.unfollowBtn.$subtitle.text("without exception")) : (t.followBtn.$subtitle.text("who have never been unfollowed"), t.unfollowBtn.$subtitle.text("who do not follow you"))
})
}) : this.$el.addClass("flipOutY")
},
withoutException: !1
};
$.extend(Button.prototype, {
incrementCount: function() {
this.count++,
this.$title.text(this.count)
},
counter: function() {
return this.count
},
setIdle: function() {
var t = this;
if (!t.action.paused) {
t.action.pause();
}
}
}),
$.extend(Profile.prototype, {
isLoaded: function() {
return this.$el.isPresent()
},
isFollowing: function() {
return this.$el.find(".FollowStatus").isPresent()
},
isProtected: function() {
return this.$el.find(".Icon--protected").isPresent()
},
isNotFollowing: function() {
return !this.isFollowing()
},
isFollowable: function() {
return this.$btn.children(".follow-text").is(":visible")
},
isFollowed: function() {
return this.$btn.children(".following-text").is(":visible")
},
follow: function() {
if (tmf.followBtn.counter() > 1) {
tmf.followBtn.action.pause();
Record.set(function() {tmf.followBtn.counter()});
gotoPage();
};
this.isFollowable() && !this.isProtected() && tmf.followBtn.counter() < 6 && (tmf.withoutException || !Record.includes(this.id) ? (this.click(), tmf.followBtn.incrementCount()) : this.log("warn", "Already unfollowed once"))
},
unfollow: function() {
this.isFollowed() && (tmf.withoutException || this.isNotFollowing()) && (this.click(), tmf.unfollowBtn.incrementCount(), Record.add(this.id))
},
click: function() {
this.log("success", 'Clicked on "' + this.$btn.children(":visible").text().trim() + '"'), this.$btn.click(), this.clicked = !0
},
log: function(t, e) {
$("<div>").addClass("tmf-log").addClass("tmf-log--" + t).text(e).insertBefore(this.$el.find(".ProfileCard-bio"))
}
}),
$.extend(BulkAction.prototype, {
nth: 0,
loadAttempts: 0,
_loadProfiles: function() {
this.loadAttempts < 10 && (this.last.$btn.focus(), this.loadAttempts++, this._sleep(700))
},
_sleep: function(t) {
var e = this;
setTimeout(function() {
e.run()
}, t)
},
run: function() {
if (!this.paused) {
var t = new Profile(this.nth);
t.isLoaded() ? (this.loadAttempts = 0, this.callback.call(t), this.last = t, this.nth++, t.clicked ? this._sleep(this.interval) : this.run()) : this._loadProfiles()
}
},
pause: function() {
this.paused = !0
},
proceed: function() {
this.paused = !1, this.run()
}
}),
Record.get(function() {
tmf.init(), tmf.toggle()
});
var observer = new MutationObserver(function(t) {
t.forEach(function(t) {
tmf.toggle()
})
});
$(".tmf-btn--close").click(function(){
$(".flipInY").hide();
});
observer.observe(document.querySelector("head > title"), {
subtree: !0,
characterData: !0,
childList: !0
});
I need to store locally my counter, so as you can see I tried to set it as:
Record.set(function() {tmf.followBtn.counter()}); inside my follow function.
Then I tried to get it from my Button function as:
n.count = (Record.get(function() {tmf.followBtn.counter()}) > 1 ? Record.get(function() {tmf.followBtn.counter()}) : 0),
Why all the time I reload the page, the counter starts from zero?

How can I make a Rickshaw legend with multiple series enaber/disabler?

I need to make a Rickshaw legend where I can make groups of time series.
e.g. I have 20 time series displayed in a graph and I want them to be grouped in 4 groups, named series1, series2, series3, series4. Series1 would contain the first 5 time series in the graph, series2 would contain the 6th to the 10th and so on.
Before I try to add a custom object in my .js to solve my problem someone knows if there is a built in functionality that I couldn't find?
I didn't find anything helpful so I created a personalized version of a multiple legend that works along with the traditional legend.
Unfortunately to update the multiple legend when the standard legend is modified I had to create a myLegend object instead of the default one.
You can use this version in this way:
//you must have a traditional Rickshaw seriesData
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
width: 960,
height: 500,
renderer: 'line',
series: seriesData
} );
graph.render();
var legend = new Rickshaw.Graph.Legend( {
graph: graph,
element: document.getElementById('legend')
} );
var mLegend = new multiLegend( {
graph: graph,
element: document.getElementById('multi_legend'),
multiDivision: [
{
name: "Africa",
indexes: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
}
{
name: "Asia",
indexes: [ 8, 9, 10, 11, 12 ]
},
{
name: "Europe",
indexes: [ 13, 14, 15, 16, 17]
},
{
name: "North America",
indexes: [ 18, 19, 20 ]
}
]
} );
new myToggle( {
graph: graph,
legend: legend,
multiLegend: mLegend
} );
new multiToggle( {
graph: graph,
multiLegend: mLegend,
legend: legend
});
Here's the code:
multiLegend = Rickshaw.Class.create( {
className: 'rickshaw_legend',
initialize: function(args) {
this.element = args.element;
this.graph = args.graph;
this.naturalOrder = args.naturalOrder;
this.seriesGroups = args.multiDivision;
this.element.classList.add(this.className);
this.list = document.createElement('ul');
this.element.appendChild(this.list);
this.render();
// we could bind this.render.bind(this) here
// but triggering the re-render would lose the added
// behavior of the series toggle
this.graph.onUpdate( function() {} );
},
render: function() {
var self = this;
while ( this.list.firstChild ) {
this.list.removeChild( this.list.firstChild );
}
this.lines = [];
var allSeries = this.graph.series;
self.seriesGroups.forEach( function(s) {
var series = allSeries.filter( function(value, index) {
return (s.indexes.indexOf(index)!=-1) ? true : false;
});
series = series.reverse();
self.addLine(s.name, series);
} );
},
addLine: function (name, series) {
var line = document.createElement('li');
line.className = 'line';
if (series.disabled) {
line.className += ' disabled';
}
if (series.className) {
d3.select(line).classed(series.className, true);
}
var swatch = document.createElement('div');
swatch.className = 'swatch';
swatch.style.backgroundColor = "#0000FF";
line.appendChild(swatch);
var label = document.createElement('span');
label.className = 'label';
label.innerHTML = name;
line.appendChild(label);
this.list.appendChild(line);
line.series = series;
var _line = { element: line, series: series, disabled: false};
if (this.shelving) {
this.shelving.addAnchor(_line);
this.shelving.updateBehaviour();
}
if (this.highlighter) {
this.highlighter.addHighlightEvents(_line);
}
this.lines.push(_line);
return line;
}
} );
multiToggle = function(args) {
this.graph = args.graph;
this.multiLegend = args.multiLegend;
this.legend = args.legend;
var self = this;
this.addAnchor = function(line) {
var anchor = document.createElement('a');
anchor.innerHTML = '✔';
anchor.classList.add('action');
line.element.insertBefore(anchor, line.element.firstChild);
anchor.onclick = function(e) {
if (line.disabled) {
line.series.forEach( function(serie) {
serie.enable();
});
line.element.classList.remove('disabled');
line.disabled = false;
self.legend.lines
.filter(function(value) {
return (line.series.indexOf(value.series)!=-1) ? true : false;
})
.forEach( function(l) {
l.element.classList.remove('disabled');
l.disabled = false;
});
} else {
if (this.graph.series.filter(function(s) { return !s.disabled }).length <= 1) return;
line.series.forEach( function(serie) {
serie.disable();
});
line.element.classList.add('disabled');
line.disabled = true;
self.legend.lines
.filter(function(value) {
return (line.series.indexOf(value.series)!=-1) ? true : false;
})
.forEach( function(l) {
l.element.classList.add('disabled');
l.disabled = true;
});
}
self.graph.update();
}.bind(this);
var label = line.element.getElementsByTagName('span')[0];
label.onclick = function(e){
var disableAllOtherLines = line.disabled;
if ( ! disableAllOtherLines ) {
for ( var i = 0; i < self.multiLegend.lines.length; i++ ) {
var l = self.multiLegend.lines[i];
if ( line.series === l.series ) {
// noop
} else if ( l.series.disabled ) {
// noop
} else {
disableAllOtherLines = true;
break;
}
}
}
// show all or none
if ( disableAllOtherLines ) {
// these must happen first or else we try ( and probably fail ) to make a no line graph
line.series.forEach( function(serie) {
serie.enable();
});
line.element.classList.remove('disabled');
line.disabled = false;
self.legend.lines
.filter(function(value) {
return (line.series.indexOf(value.series)!=-1) ? true : false;
})
.forEach( function(l) {
l.element.classList.remove('disabled');
l.disabled = false;
});
self.multiLegend.lines.forEach(function(l){
if ( line.series === l.series ) {
// noop
} else {
l.series.forEach( function(serie) {
serie.disable();
});
l.element.classList.add('disabled');
l.disabled = true;
self.legend.lines
.filter(function(value) {
return (l.series.indexOf(value.series)!=-1) ? true : false;
})
.forEach( function(l2) {
l2.element.classList.add('disabled');
l2.disabled = true;
});
}
});
} else {
self.multiLegend.lines.forEach(function(l){
l.series.forEach( function(serie) {
serie.enable();
});
l.element.classList.remove('disabled');
l.disabled = false;
self.legend.lines
.filter(function(value) {
return (l.series.indexOf(value.series)!=-1) ? true : false;
})
.forEach( function(l2) {
l2.element.classList.remove('disabled');
l2.disabled = false;
});
});
}
self.graph.update();
};
};
if (this.multiLegend) {
var $ = jQuery;
if (typeof $ != 'undefined' && $(this.multiLegend.list).sortable) {
$(this.multiLegend.list).sortable( {
start: function(event, ui) {
ui.item.bind('no.onclick',
function(event) {
event.preventDefault();
}
);
},
stop: function(event, ui) {
setTimeout(function(){
ui.item.unbind('no.onclick');
}, 250);
}
});
}
this.multiLegend.lines.forEach( function(l) {
self.addAnchor(l);
} );
}
this._addBehavior = function() {
this.graph.series.forEach( function(s) {
s.disable = function() {
if (self.graph.series.length <= 1) {
throw('only one series left');
}
s.disabled = true;
};
s.enable = function() {
s.disabled = false;
};
} );
};
this._addBehavior();
this.updateBehaviour = function () { this._addBehavior() };
};
myToggle = function(args) {
this.graph = args.graph;
this.legend = args.legend;
this.multiLegend = args.multiLegend;
var self = this;
this.addAnchor = function(line) {
var anchor = document.createElement('a');
anchor.innerHTML = '✔';
anchor.classList.add('action');
line.element.insertBefore(anchor, line.element.firstChild);
anchor.onclick = function(e) {
if (line.series.disabled) {
line.series.enable();
line.element.classList.remove('disabled');
} else {
if (this.graph.series.filter(function(s) { return !s.disabled }).length <= 1) return;
line.series.disable();
line.element.classList.add('disabled');
self.multiLegend.lines.forEach( function(l) {
if(l.series.indexOf(line.series)!=-1) {
l.element.classList.add('disabled');
l.disabled = true;
}
});
}
self.graph.update();
}.bind(this);
var label = line.element.getElementsByTagName('span')[0];
label.onclick = function(e){
var disableAllOtherLines = line.series.disabled;
if ( ! disableAllOtherLines ) {
for ( var i = 0; i < self.legend.lines.length; i++ ) {
var l = self.legend.lines[i];
if ( line.series === l.series ) {
// noop
} else if ( l.series.disabled ) {
// noop
} else {
disableAllOtherLines = true;
break;
}
}
}
// show all or none
if ( disableAllOtherLines ) {
// these must happen first or else we try ( and probably fail ) to make a no line graph
line.series.enable();
line.element.classList.remove('disabled');
self.legend.lines.forEach(function(l){
if ( line.series === l.series ) {
// noop
} else {
l.series.disable();
l.element.classList.add('disabled');
}
});
self.multiLegend.lines.forEach( function(l) {
l.element.classList.add('disabled');
l.disabled = true;
});
} else {
self.legend.lines.forEach(function(l){
l.series.enable();
l.element.classList.remove('disabled');
});
}
self.graph.update();
};
};
if (this.legend) {
var $ = jQuery;
if (typeof $ != 'undefined' && $(this.legend.list).sortable) {
$(this.legend.list).sortable( {
start: function(event, ui) {
ui.item.bind('no.onclick',
function(event) {
event.preventDefault();
}
);
},
stop: function(event, ui) {
setTimeout(function(){
ui.item.unbind('no.onclick');
}, 250);
}
});
}
this.legend.lines.forEach( function(l) {
self.addAnchor(l);
} );
}
this._addBehavior = function() {
this.graph.series.forEach( function(s) {
s.disable = function() {
if (self.graph.series.length <= 1) {
throw('only one series left');
}
s.disabled = true;
};
s.enable = function() {
s.disabled = false;
};
} );
};
this._addBehavior();
this.updateBehaviour = function () { this._addBehavior() };
};

Soundcloud stratus player won't dynamically add more than an individual track at a time

Thanks to other people's questions, I have gotten AJAX links to work for individual songs when clicked in the DOM. My problem is that I need to find a way to load all of the tracks under a given user's account on soundcloud. I edited the stratus.js file to make it listen for the click by using .delegate(), but I can't figure out how to call the track listing from soundcloud and load it through the given iframe. This is the stratus.js file.
(function() {
var $;
$ = jQuery;
(function($){var g,d,j=1,a,b=this,f=!1,h="postMessage",e="addEventListener",c,i=b[h]&&!$.browser.opera;$[h]=function(k,l,m){if(!l){return}k=typeof k==="string"?k:$.param(k);m=m||parent; if(i){m[h](k,l.replace(/([^:]+:\/\/[^\/]+).*/,"$1"))}else{if(l){m.location=l.replace(/#.*$/,"")+"#"+(+new Date)+(j++)+"&"+k}}};$.receiveMessage=c=function(l,m,k){if(i){if(l){a&&c(); a=function(n){if((typeof m==="string"&&n.origin!==m)||($.isFunction(m)&&m(n.origin)===f)){return f}l(n)}}if(b[e]){b[l?e:"removeEventListener"]("message",a,f)} else{b[l?"attachEvent":"detachEvent"]("onmessage",a)}}else{g&&clearInterval(g);g=null;if(l){k=typeof m==="number"?m:typeof k==="number"?k:100; g=setInterval(function(){var o=document.location.hash,n=/^#?\d+&/;if(o!==d&&n.test(o)){d=o;l({data:o.replace(n,"")})}},k)}}}})(jQuery);
$.fn.stratus = function(settings) {
return $.stratus(settings);
};
$.stratus = function(settings) {
var root_url, src;
root_url = settings.env === 'development' ? 'http://example.com:3000' : 'http://stratus.sc';
$('head').append("<link rel='stylesheet' href='" + root_url + "/stratus.css' type='text/css'/>");
if (settings.align === 'top') {
$('head').append("<style>#stratus{ top: 0; }</style>");
}
if (settings.position === 'absolute') {
$('head').append("<style>#stratus{ position: absolute; }</style>");
}
if (settings.offset) {
$('head').append("<style>#stratus{ " + settings.align + ": " + settings.offset + "px !important; }</style>");
}
$('body').append("<div id='stratus'><iframe allowtransparency='true' frameborder='0' scrolling='0'></div>");
src = root_url + '/player?' + $.param(settings, true) + '&link=' + encodeURIComponent(document.location.href);
$('#stratus iframe').attr({
src: src
});
$('#stratus iframe').load(function() {// /resolve?url=
return $(this).css({
visibility: 'visible'
});
});
$('#stratus').show();
$(document).delegate("a.stratus","click", function () {
$.postMessage($(this).attr('href'), src, $('#stratus iframe')[0].contentWindow);
return false;
});
return $.receiveMessage(function(e) {
return $('#stratus').toggleClass('open');
}, root_url);
};
}).call(this);
I believe that a call through the Soundcloud API will be necessary, then a run through the user data for individual track additions through the iframe. This is the player.js file, which I'm not sure is necessary for this post, but it helped me begin to understand what was happening with the initial adding of tracks from the customisable Links field:
console.log("Stratus loading...");
$(function() {
var b, booleans, getScaledImageData, link, params, scApiUrl, source_origin, strtobool, timecode, _i, _len;
window.Track = Backbone.Model.extend({
initialize: function() {
var that, track;
that = this;
track = this.attributes;
track.timecode = timecode(track.duration);
return soundManager.createSound({
id: "sound_" + track.id,
multiShot: false,
url: track.stream_url + (/\?/.test(track.stream_url) ? '&' : '?') + 'consumer_key=' + Stratus.options.key,
volume: Stratus.options.volume,
whileplaying: function() {
Stratus.$('.played').width((this.position / track.duration * 100) + '%');
return Stratus.$('#player .duration').text(timecode(this.position) + ' / ' + timecode(track.duration));
},
whileloading: function() {
return Stratus.$('.loaded').width((this.bytesLoaded / this.bytesTotal * 100) + '%');
},
onplay: function() {
if (this.loaded) {
return Stratus.$('.loaded').width('100%');
}
},
onresume: function() {
if (this.loaded) {
return Stratus.$('.loaded').width('100%');
}
},
onfinish: function() {
return Stratus.nextTrack();
}
});
},
sound: function() {
return "sound_" + this.id;
},
play: function() {
return soundManager.play(this.sound());
},
pause: function() {
return soundManager.pause(this.sound());
},
seek: function(relative) {
return soundManager.setPosition(this.sound(), this.get('duration') * relative);
},
getWave: function(callback) {
var that;
that = this;
return $.getJSON('http://wave64.heroku.com/w?callback=?', {
url: this.get('waveform_url')
}, function(data) {
var waveform;
waveform = new Image();
waveform.src = data.data;
return waveform.onload = function() {
var waveform_data;
waveform_data = getScaledImageData(waveform);
that.set({
'waveform_data': waveform_data
});
return callback();
};
});
},
comment: function(text) {
return SC.post("/tracks/" + this.id + "/comments", {
"comment[body]": text
}, function() {
Stratus.$('#comment input').val('');
Stratus.toggleComment();
return alert("Comment posted!");
});
},
favorite: function() {
if (Stratus.$('.love').hasClass('loved')) {
return SC["delete"]("/me/favorites/" + this.id, function() {
return Stratus.$('.love').removeClass('loved');
});
} else {
return SC.put("/me/favorites/" + this.id, function() {
return Stratus.$('.love').addClass('loved');
});
}
},
isFavorite: function() {
return SC.get("/me/favorites/" + this.id, function(data) {
if (!(data.errors != null)) {
return Stratus.$('.love').addClass('loved');
}
});
}
});
window.TrackList = Backbone.Collection.extend({
model: Track,
select: function(track) {
this.stop();
this.current = track;
return this.trigger('player:select');
},
toggle: function(track) {
if (track && this.current !== track) {
this.select(track);
}
if (this.playing) {
return this.pause();
} else {
return this.play();
}
},
play: function(track) {
if (track && this.current !== track) {
this.select(track);
}
this.playing = true;
this.current.play();
return this.trigger('player:toggle');
},
pause: function() {
this.playing = false;
this.current.pause();
return this.trigger('player:toggle');
},
stop: function() {
this.playing = false;
return soundManager.stopAll();
},
prev: function() {
var i;
i = this.indexOf(this.current) - 1;
if (i > -1) {
return this.at(i);
} else {
return this.last();
}
},
next: function() {
var i;
i = this.indexOf(this.current) + 1;
if (i < _.size(this)) {
return this.at(i);
} else {
return this.first();
}
},
random: function() {
var i;
i = Math.round(Math.random() * _.size(this));
return this.at(i);
}
});
window.Tracks = new TrackList();
window.TrackView = Backbone.View.extend({
tagName: "li",
events: {
"click": "toggleTrack"
},
render: function() {
return $(this.el).html(ich.track(this.model.toJSON()));
},
toggleTrack: function() {
return Tracks.toggle(this.model);
}
});
window.AppView = Backbone.View.extend({
el: $('#stratus'),
defaults: {
align: 'bottom',
animate: 'slide',
auto_play: false,
buying: true,
color: 'F60',
download: true,
env: 'production',
key: 'ybtyKcnlhP3RKXpJ58fg',
links: ['http://soundcloud.com/qotsa/sets/test'],
random: false,
redirect: 'http://stratus.sc/callback.html',
user: true,
stats: true,
volume: 50
},
events: {
"dblclick": "showDrawer",
"click .prev": "prevTrack",
"click .toggle": "toggleCurrent",
"click .next": "nextTrack",
"click #time": "seekTrack",
"mousemove #time": "movePosition",
"click .share": "toggleShare",
"click .close.sharing": "toggleShare",
"click .comment": "toggleComment",
"click .close.commenting": "toggleComment",
"keypress #add input": "commentTrack",
"click .love": "favoriteTrack",
"click #avatar": "logout",
"click .popup": "popupPlayer"
},
initialize: function() {
var options, that;
console.log("Stratus initializing...");
that = this;
this.options = options = _.extend(this.defaults, this.options);
Tracks.bind('add', this.add, this);
Tracks.bind('player:select', this.render, this);
Tracks.bind('player:toggle', this.toggle, this);
SC.initialize({
client_id: options.key,
redirect_uri: options.redirect
});
return SC.whenStreamingReady(function() {
return that.loadTracks(options.links, function() {
Tracks.select(options.random ? Tracks.random() : Tracks.first());
if (options.auto_play) {
Tracks.play();
}
if (options.align === 'top') {
options.top = true;
}
options.color = {
base: tinycolor(options.color).toHexString(),
light: tinycolor.lighten(options.color).toHexString(),
dark: tinycolor.darken(options.color).toHexString()
};
$('head').append(ich.theme(options));
if (SC.isConnected()) {
that.updateUser();
}
return that.animate(function() {
return that.resize();
});
});
});
},
loadTracks: function(links, callback) {
var index, loadURL;
index = 0;
loadURL = function(link) {
var url;
console.log("Loading " + link + "...");
url = scApiUrl(link);
return SC.get(url, function(data) {
index += 1;
if (data.tracks) {
Tracks.add(data.tracks);
} else if (data.username || data.creator) {
links.push(data.uri + '/tracks');
} else {
Tracks.add(data);
}
if (links[index]) {
return loadURL(links[index]);
} else {
return callback();
}
});
};
return loadURL(links[index]);
},
render: function() {
var artwork, data, el, that, track;
that = this;
track = Tracks.current;
data = Tracks.current.toJSON();
el = this.$('#tracks .track_' + data.id);
this.$('#player .track').html(ich.current(data));
this.$('#buttons').html(ich.buttons(data));
this.$('#stats').html(ich.stats(data));
this.$('#share').html(ich.share(data));
artwork = data.artwork_url ? data.artwork_url : data.user.avatar_url;
this.$('#artwork img').attr({
src: artwork.replace('-large', '-t300x300')
});
el.addClass('current').siblings().removeClass('current');
if (track.has('waveform_data')) {
this.updateWave(track);
} else {
track.getWave(function() {
return that.updateWave(track);
});
}
if (SC.isConnected()) {
track.isFavorite();
}
return this.resize();
},
add: function(track) {
var view;
view = new TrackView({
model: track,
className: 'track track_' + track.id
});
return this.$("#tracks").append(view.render());
},
toggle: function() {
return this.$('#player').toggleClass('playing', Tracks.playing);
},
toggleCurrent: function() {
Tracks.toggle();
return false;
},
prevTrack: function() {
Tracks.play(Tracks.prev());
return false;
},
nextTrack: function() {
Tracks.play(Tracks.next());
return false;
},
seekTrack: function(e) {
var relative;
if (!Tracks.playing) {
Tracks.play();
}
relative = Math.min(this.$('.loaded').width(), (e.pageX - this.$('#time').offset().left) / this.$('#time').width());
Tracks.current.seek(relative);
return false;
},
movePosition: function(e) {
return this.$('.position').css({
"left": e.pageX - this.$('#time').offset().left
});
},
updateWave: function(track) {
var canvas, context;
canvas = this.$('#waveform').get(0);
context = canvas.getContext('2d');
canvas.setAttribute('width', 180);
canvas.setAttribute('height', 40);
context.clearRect(0, 0, 180, 40);
return context.putImageData(track.get('waveform_data'), 0, 0);
},
animate: function(callback) {
if (this.options.popup) {
this.$('#player, #drawer').fadeIn('slow');
}
switch (this.options.animate) {
case 'slide':
return this.$('#player').slideDown('slow', function() {
return callback();
});
case 'fade':
return this.$('#player').fadeIn('slow', function() {
return callback();
});
default:
return this.$('#player').show(0, function() {
return callback();
});
}
},
resize: function() {
this.$('#share').css({
"margin-right": this.$('#buttons').width() - 30
});
return this.$('#comment').css({
"margin-right": this.$('#buttons').width() - 60
});
},
showDrawer: function() {
this.$('#drawer').toggle();
return $.postMessage(true, source_origin, parent);
},
popupPlayer: function() {
Tracks.stop();
this.toggle();
return $.popupWindow($.url().attr('source') + '&popup=true', {
height: 199,
width: 800,
location: false
});
},
toggleShare: function() {
this.$('#share').toggle();
this.$('#share input').select();
return false;
},
toggleComment: function() {
var that;
that = this;
if (SC.isConnected()) {
this.$('#comment').toggle();
this.$('#comment input').select();
} else {
this.login(function() {
return that.toggleComment();
});
}
return false;
},
commentTrack: function(e) {
var text;
text = this.$('#comment input').val();
if (e.keyCode === 13) {
return Tracks.current.comment(text);
}
},
favoriteTrack: function() {
if (SC.isConnected()) {
Tracks.current.favorite();
} else {
this.login(function() {
return Tracks.current.favorite();
});
}
return false;
},
login: function(callback) {
var that;
that = this;
return SC.connect(function(user) {
that.updateUser();
return callback();
});
},
updateUser: function() {
var that;
that = this;
return SC.get("/me", function(user) {
return that.$('#avatar').attr({
src: user.avatar_url
});
});
},
logout: function() {
SC.disconnect();
return alert("Logged out.");
}
});
link = decodeURIComponent($.url().param('link'));
source_origin = $.url(link).attr('base');
$.receiveMessage(function(e) {
var result, url;
url = e.data;
result = Tracks.find(function(track) {
return track.get('permalink_url') === url;
});
if (result) {
return Tracks.toggle(result);
} else {
return SC.get("/resolve", {
url: url
}, function(track) {
Tracks.add(track);
return Tracks.play(Tracks.get(track.id));
});
}
}, source_origin);
scApiUrl = function(url) {
if (/api\./.test(url)) {
return url;
} else {
return "/resolve?url=" + url;
}
};
timecode = function(ms) {
return SC.Helper.millisecondsToHMS(ms);
};
strtobool = function(str) {
switch (str) {
case 'true':
return true;
case true:
return true;
default:
return false;
}
};
getScaledImageData = function(image) {
var color, height, isImageData, lastIndex, orig, origCtx, origImageData, origWidth, populateScaledImagedData, precise, scaleX, scaleY, scaled, scaledCtx, scaledImageData, width, x, y;
color = Stratus.$('#player').css('background-color');
color = tinycolor(color).toRgb();
precise = function(number, precision) {
precision = Math.pow(10, precision || 0);
return Math.round(number * precision) / precision;
};
populateScaledImagedData = function(x, y, srcImageData, indexOffset) {
var alpha, index, indexScaled, isOpaque;
indexOffset = indexOffset || 0;
index = (Math.floor(y / scaleY) * origWidth + Math.floor(x / scaleX)) * 4;
indexScaled = indexOffset + (y * width + x) * 4;
alpha = srcImageData.data[index + 3];
isOpaque = alpha === 255;
scaledImageData.data[indexScaled] = isOpaque ? color['r'] : 0;
scaledImageData.data[indexScaled + 1] = isOpaque ? color['g'] : 0;
scaledImageData.data[indexScaled + 2] = isOpaque ? color['b'] : 0;
scaledImageData.data[indexScaled + 3] = alpha;
return indexScaled;
};
height = 40;
width = 180;
origWidth = image.width;
scaleX = precise(width / image.width, 4);
scaleY = precise(height / image.height, 4);
try {
isImageData = !(image instanceof Image);
} catch (e) {
isImageData = image.hasOwnProperty("data") && image.data.hasOwnProperty("length");
}
orig = document.createElement("canvas");
orig.width = image.width;
orig.height = image.height;
origCtx = orig.getContext("2d");
if (!isImageData) {
origCtx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width, image.height);
} else {
origCtx.putImageData(image, 0, 0);
}
origImageData = origCtx.getImageData(0, 0, image.width, image.height);
scaled = document.createElement("canvas");
scaled.width = width;
scaled.height = height;
scaledCtx = scaled.getContext("2d");
scaledImageData = scaledCtx.getImageData(0, 0, width, height);
y = 0;
while (y < height) {
x = 0;
while (x < width) {
lastIndex = populateScaledImagedData(x, y, origImageData, 0);
x++;
}
y++;
}
return scaledImageData;
};
params = $.url().param();
if (params.links) {
params.links = decodeURIComponent(params.links);
params.links = params.links.split(',');
}
if (params.redirect) {
params.redirect = decodeURIComponent(params.redirect);
}
booleans = ['auto_play', 'buying', 'download', 'random', 'user', 'stats', 'popup'];
for (_i = 0, _len = booleans.length; _i < _len; _i++) {
b = booleans[_i];
if (params[b]) {
params[b] = strtobool(params[b]);
}
}
return window.Stratus = new AppView(params);
});
I'm aware that this is rather intensive, and I apologize for that. Just throwing up a prayer that I won't have to radically alter my website user's experience in a negative way.
I don't know about the stratus player, but in general - if you want to retrieve a list of tracks of a specific user - given that you know the user's id, you indeed have to make a call to the soundcloud API. You can do it like this:
SC.initialize({
client_id: "YOUR_CLIENT_ID",
redirect_uri: "http://example.com/callback.html",
});
/**
Once that's done you are all set and ready to call the SoundCloud API.
**/
/**
Call to the SoundCloud API.
Retrieves list of tracks, and displays a list with links to the tracks showing 'tracktitle' and 'track duration'
**/
var userId = 39090345; // user_id of Prutsonic
SC.get("/tracks", {
user_id: userId,
limit: 100
}, function (tracks) {
for (var i = 0; i < tracks.length; i++) {
console.log(tracks[i].title);
}
});
You can try my fiddle here: http://jsfiddle.net/tobiasbeuving/26pHX/5/
Cheers,
T

Categories